blob: 0408230b220aac956c77d4e3a4034b3f47192326 [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 */
larrybr527c39d2022-05-10 14:55:45 +00001194#define SHFLG_Echo 0x00000040 /* .echo on/off, 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{
drh537a6bf2022-02-15 13:23:09 +00002314 sqlite3_int64 ir = (sqlite3_int64)r;
2315 if( r==(double)ir ){
2316 sqlite3_snprintf(50,z,"%lld.0", ir);
2317 }else{
2318 sqlite3_snprintf(50,z,"%!.20g", r);
2319 }
drh2f1f8802018-06-13 17:19:20 +00002320 raw_printf(p->out, "%s", z);
2321 }
drh2ce15c32017-07-11 13:34:40 +00002322 }else if( aiType && aiType[i]==SQLITE_BLOB && p->pStmt ){
2323 const void *pBlob = sqlite3_column_blob(p->pStmt, i);
2324 int nBlob = sqlite3_column_bytes(p->pStmt, i);
2325 output_hex_blob(p->out, pBlob, nBlob);
2326 }else if( isNumber(azArg[i], 0) ){
2327 utf8_printf(p->out,"%s", azArg[i]);
2328 }else if( ShellHasFlag(p, SHFLG_Newlines) ){
2329 output_quoted_string(p->out, azArg[i]);
2330 }else{
2331 output_quoted_escaped_string(p->out, azArg[i]);
2332 }
2333 }
2334 raw_printf(p->out,");\n");
2335 break;
2336 }
drh30c54a02020-05-28 23:49:50 +00002337 case MODE_Json: {
2338 if( azArg==0 ) break;
2339 if( p->cnt==0 ){
2340 fputs("[{", p->out);
2341 }else{
2342 fputs(",\n{", p->out);
2343 }
2344 p->cnt++;
2345 for(i=0; i<nArg; i++){
drh69c093d2020-05-29 00:21:43 +00002346 output_json_string(p->out, azCol[i], -1);
drh30c54a02020-05-28 23:49:50 +00002347 putc(':', p->out);
2348 if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){
2349 fputs("null",p->out);
2350 }else if( aiType && aiType[i]==SQLITE_FLOAT ){
2351 char z[50];
2352 double r = sqlite3_column_double(p->pStmt, i);
2353 sqlite3_uint64 ur;
2354 memcpy(&ur,&r,sizeof(r));
2355 if( ur==0x7ff0000000000000LL ){
2356 raw_printf(p->out, "1e999");
2357 }else if( ur==0xfff0000000000000LL ){
2358 raw_printf(p->out, "-1e999");
2359 }else{
2360 sqlite3_snprintf(50,z,"%!.20g", r);
2361 raw_printf(p->out, "%s", z);
2362 }
2363 }else if( aiType && aiType[i]==SQLITE_BLOB && p->pStmt ){
2364 const void *pBlob = sqlite3_column_blob(p->pStmt, i);
2365 int nBlob = sqlite3_column_bytes(p->pStmt, i);
drh69c093d2020-05-29 00:21:43 +00002366 output_json_string(p->out, pBlob, nBlob);
drh30c54a02020-05-28 23:49:50 +00002367 }else if( aiType && aiType[i]==SQLITE_TEXT ){
drh69c093d2020-05-29 00:21:43 +00002368 output_json_string(p->out, azArg[i], -1);
drh30c54a02020-05-28 23:49:50 +00002369 }else{
2370 utf8_printf(p->out,"%s", azArg[i]);
2371 }
2372 if( i<nArg-1 ){
2373 putc(',', p->out);
2374 }
2375 }
2376 putc('}', p->out);
2377 break;
2378 }
drh2ce15c32017-07-11 13:34:40 +00002379 case MODE_Quote: {
2380 if( azArg==0 ) break;
2381 if( p->cnt==0 && p->showHeader ){
2382 for(i=0; i<nArg; i++){
drhc6835732020-05-28 20:37:17 +00002383 if( i>0 ) fputs(p->colSeparator, p->out);
drh2ce15c32017-07-11 13:34:40 +00002384 output_quoted_string(p->out, azCol[i]);
2385 }
drhc6835732020-05-28 20:37:17 +00002386 fputs(p->rowSeparator, p->out);
drh2ce15c32017-07-11 13:34:40 +00002387 }
2388 p->cnt++;
2389 for(i=0; i<nArg; i++){
drhc6835732020-05-28 20:37:17 +00002390 if( i>0 ) fputs(p->colSeparator, p->out);
drh2ce15c32017-07-11 13:34:40 +00002391 if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){
2392 utf8_printf(p->out,"NULL");
2393 }else if( aiType && aiType[i]==SQLITE_TEXT ){
2394 output_quoted_string(p->out, azArg[i]);
2395 }else if( aiType && aiType[i]==SQLITE_INTEGER ){
2396 utf8_printf(p->out,"%s", azArg[i]);
2397 }else if( aiType && aiType[i]==SQLITE_FLOAT ){
2398 char z[50];
2399 double r = sqlite3_column_double(p->pStmt, i);
2400 sqlite3_snprintf(50,z,"%!.20g", r);
2401 raw_printf(p->out, "%s", z);
2402 }else if( aiType && aiType[i]==SQLITE_BLOB && p->pStmt ){
2403 const void *pBlob = sqlite3_column_blob(p->pStmt, i);
2404 int nBlob = sqlite3_column_bytes(p->pStmt, i);
2405 output_hex_blob(p->out, pBlob, nBlob);
2406 }else if( isNumber(azArg[i], 0) ){
2407 utf8_printf(p->out,"%s", azArg[i]);
2408 }else{
2409 output_quoted_string(p->out, azArg[i]);
2410 }
2411 }
drhc6835732020-05-28 20:37:17 +00002412 fputs(p->rowSeparator, p->out);
drh2ce15c32017-07-11 13:34:40 +00002413 break;
2414 }
2415 case MODE_Ascii: {
2416 if( p->cnt++==0 && p->showHeader ){
2417 for(i=0; i<nArg; i++){
2418 if( i>0 ) utf8_printf(p->out, "%s", p->colSeparator);
2419 utf8_printf(p->out,"%s",azCol[i] ? azCol[i] : "");
2420 }
2421 utf8_printf(p->out, "%s", p->rowSeparator);
2422 }
2423 if( azArg==0 ) break;
2424 for(i=0; i<nArg; i++){
2425 if( i>0 ) utf8_printf(p->out, "%s", p->colSeparator);
2426 utf8_printf(p->out,"%s",azArg[i] ? azArg[i] : p->nullValue);
2427 }
2428 utf8_printf(p->out, "%s", p->rowSeparator);
2429 break;
2430 }
drh4b5345c2018-04-24 13:07:40 +00002431 case MODE_EQP: {
drhe2ca99c2018-05-02 00:33:43 +00002432 eqp_append(p, atoi(azArg[0]), atoi(azArg[1]), azArg[3]);
drh4b5345c2018-04-24 13:07:40 +00002433 break;
2434 }
drh2ce15c32017-07-11 13:34:40 +00002435 }
2436 return 0;
2437}
2438
2439/*
2440** This is the callback routine that the SQLite library
2441** invokes for each row of a query result.
2442*/
2443static int callback(void *pArg, int nArg, char **azArg, char **azCol){
2444 /* since we don't have type info, call the shell_callback with a NULL value */
2445 return shell_callback(pArg, nArg, azArg, azCol, NULL);
2446}
2447
2448/*
2449** This is the callback routine from sqlite3_exec() that appends all
2450** output onto the end of a ShellText object.
2451*/
2452static int captureOutputCallback(void *pArg, int nArg, char **azArg, char **az){
2453 ShellText *p = (ShellText*)pArg;
2454 int i;
2455 UNUSED_PARAMETER(az);
drhb3c45232017-08-28 14:33:27 +00002456 if( azArg==0 ) return 0;
drh2ce15c32017-07-11 13:34:40 +00002457 if( p->n ) appendText(p, "|", 0);
2458 for(i=0; i<nArg; i++){
2459 if( i ) appendText(p, ",", 0);
2460 if( azArg[i] ) appendText(p, azArg[i], 0);
2461 }
2462 return 0;
2463}
2464
2465/*
2466** Generate an appropriate SELFTEST table in the main database.
2467*/
2468static void createSelftestTable(ShellState *p){
2469 char *zErrMsg = 0;
2470 sqlite3_exec(p->db,
2471 "SAVEPOINT selftest_init;\n"
2472 "CREATE TABLE IF NOT EXISTS selftest(\n"
2473 " tno INTEGER PRIMARY KEY,\n" /* Test number */
2474 " op TEXT,\n" /* Operator: memo run */
2475 " cmd TEXT,\n" /* Command text */
2476 " ans TEXT\n" /* Desired answer */
2477 ");"
2478 "CREATE TEMP TABLE [_shell$self](op,cmd,ans);\n"
2479 "INSERT INTO [_shell$self](rowid,op,cmd)\n"
2480 " VALUES(coalesce((SELECT (max(tno)+100)/10 FROM selftest),10),\n"
2481 " 'memo','Tests generated by --init');\n"
2482 "INSERT INTO [_shell$self]\n"
2483 " SELECT 'run',\n"
2484 " 'SELECT hex(sha3_query(''SELECT type,name,tbl_name,sql "
drh067b92b2020-06-19 15:24:12 +00002485 "FROM sqlite_schema ORDER BY 2'',224))',\n"
drh2ce15c32017-07-11 13:34:40 +00002486 " hex(sha3_query('SELECT type,name,tbl_name,sql "
drh067b92b2020-06-19 15:24:12 +00002487 "FROM sqlite_schema ORDER BY 2',224));\n"
drh2ce15c32017-07-11 13:34:40 +00002488 "INSERT INTO [_shell$self]\n"
2489 " SELECT 'run',"
2490 " 'SELECT hex(sha3_query(''SELECT * FROM \"' ||"
2491 " printf('%w',name) || '\" NOT INDEXED'',224))',\n"
2492 " hex(sha3_query(printf('SELECT * FROM \"%w\" NOT INDEXED',name),224))\n"
2493 " FROM (\n"
drh067b92b2020-06-19 15:24:12 +00002494 " SELECT name FROM sqlite_schema\n"
drh2ce15c32017-07-11 13:34:40 +00002495 " WHERE type='table'\n"
2496 " AND name<>'selftest'\n"
2497 " AND coalesce(rootpage,0)>0\n"
2498 " )\n"
2499 " ORDER BY name;\n"
2500 "INSERT INTO [_shell$self]\n"
2501 " VALUES('run','PRAGMA integrity_check','ok');\n"
2502 "INSERT INTO selftest(tno,op,cmd,ans)"
2503 " SELECT rowid*10,op,cmd,ans FROM [_shell$self];\n"
2504 "DROP TABLE [_shell$self];"
2505 ,0,0,&zErrMsg);
2506 if( zErrMsg ){
2507 utf8_printf(stderr, "SELFTEST initialization failure: %s\n", zErrMsg);
2508 sqlite3_free(zErrMsg);
2509 }
2510 sqlite3_exec(p->db, "RELEASE selftest_init",0,0,0);
2511}
2512
2513
2514/*
2515** Set the destination table field of the ShellState structure to
2516** the name of the table given. Escape any quote characters in the
2517** table name.
2518*/
2519static void set_table_name(ShellState *p, const char *zName){
2520 int i, n;
mistachkin2158a0c2017-09-09 00:51:36 +00002521 char cQuote;
drh2ce15c32017-07-11 13:34:40 +00002522 char *z;
2523
2524 if( p->zDestTable ){
2525 free(p->zDestTable);
2526 p->zDestTable = 0;
2527 }
2528 if( zName==0 ) return;
2529 cQuote = quoteChar(zName);
2530 n = strlen30(zName);
2531 if( cQuote ) n += n+2;
2532 z = p->zDestTable = malloc( n+1 );
drhe3e25652021-12-16 13:29:28 +00002533 shell_check_oom(z);
drh2ce15c32017-07-11 13:34:40 +00002534 n = 0;
2535 if( cQuote ) z[n++] = cQuote;
2536 for(i=0; zName[i]; i++){
2537 z[n++] = zName[i];
2538 if( zName[i]==cQuote ) z[n++] = cQuote;
2539 }
2540 if( cQuote ) z[n++] = cQuote;
2541 z[n] = 0;
2542}
2543
drhf62641e2021-12-24 20:22:13 +00002544/*
2545** Maybe construct two lines of text that point out the position of a
2546** syntax error. Return a pointer to the text, in memory obtained from
2547** sqlite3_malloc(). Or, if the most recent error does not involve a
2548** specific token that we can point to, return an empty string.
2549**
2550** In all cases, the memory returned is obtained from sqlite3_malloc64()
2551** and should be released by the caller invoking sqlite3_free().
2552*/
2553static char *shell_error_context(const char *zSql, sqlite3 *db){
2554 int iOffset;
2555 size_t len;
2556 char *zCode;
2557 char *zMsg;
2558 int i;
2559 if( db==0
2560 || zSql==0
2561 || (iOffset = sqlite3_error_offset(db))<0
2562 ){
2563 return sqlite3_mprintf("");
2564 }
2565 while( iOffset>50 ){
2566 iOffset--;
2567 zSql++;
2568 while( (zSql[0]&0xc0)==0x80 ){ zSql++; iOffset--; }
2569 }
2570 len = strlen(zSql);
2571 if( len>78 ){
2572 len = 78;
2573 while( (zSql[len]&0xc0)==0x80 ) len--;
2574 }
2575 zCode = sqlite3_mprintf("%.*s", len, zSql);
2576 for(i=0; zCode[i]; i++){ if( IsSpace(zSql[i]) ) zCode[i] = ' '; }
2577 if( iOffset<25 ){
2578 zMsg = sqlite3_mprintf("\n %z\n %*s^--- error here", zCode, iOffset, "");
2579 }else{
2580 zMsg = sqlite3_mprintf("\n %z\n %*serror here ---^", zCode, iOffset-14, "");
2581 }
2582 return zMsg;
2583}
2584
drh2ce15c32017-07-11 13:34:40 +00002585
2586/*
2587** Execute a query statement that will generate SQL output. Print
2588** the result columns, comma-separated, on a line and then add a
2589** semicolon terminator to the end of that line.
2590**
2591** If the number of columns is 1 and that column contains text "--"
2592** then write the semicolon on a separate line. That way, if a
2593** "--" comment occurs at the end of the statement, the comment
2594** won't consume the semicolon terminator.
2595*/
2596static int run_table_dump_query(
2597 ShellState *p, /* Query context */
drh8e9297f2020-03-25 12:50:13 +00002598 const char *zSelect /* SELECT statement to extract content */
drh2ce15c32017-07-11 13:34:40 +00002599){
2600 sqlite3_stmt *pSelect;
2601 int rc;
2602 int nResult;
2603 int i;
2604 const char *z;
2605 rc = sqlite3_prepare_v2(p->db, zSelect, -1, &pSelect, 0);
2606 if( rc!=SQLITE_OK || !pSelect ){
drhf62641e2021-12-24 20:22:13 +00002607 char *zContext = shell_error_context(zSelect, p->db);
2608 utf8_printf(p->out, "/**** ERROR: (%d) %s *****/\n%s", rc,
2609 sqlite3_errmsg(p->db), zContext);
2610 sqlite3_free(zContext);
drh2ce15c32017-07-11 13:34:40 +00002611 if( (rc&0xff)!=SQLITE_CORRUPT ) p->nErr++;
2612 return rc;
2613 }
2614 rc = sqlite3_step(pSelect);
2615 nResult = sqlite3_column_count(pSelect);
2616 while( rc==SQLITE_ROW ){
drh2ce15c32017-07-11 13:34:40 +00002617 z = (const char*)sqlite3_column_text(pSelect, 0);
2618 utf8_printf(p->out, "%s", z);
2619 for(i=1; i<nResult; i++){
2620 utf8_printf(p->out, ",%s", sqlite3_column_text(pSelect, i));
2621 }
2622 if( z==0 ) z = "";
2623 while( z[0] && (z[0]!='-' || z[1]!='-') ) z++;
2624 if( z[0] ){
2625 raw_printf(p->out, "\n;\n");
2626 }else{
2627 raw_printf(p->out, ";\n");
2628 }
2629 rc = sqlite3_step(pSelect);
2630 }
2631 rc = sqlite3_finalize(pSelect);
2632 if( rc!=SQLITE_OK ){
2633 utf8_printf(p->out, "/**** ERROR: (%d) %s *****/\n", rc,
2634 sqlite3_errmsg(p->db));
2635 if( (rc&0xff)!=SQLITE_CORRUPT ) p->nErr++;
2636 }
2637 return rc;
2638}
2639
2640/*
larrybrf9a49b02021-10-26 16:57:09 +00002641** Allocate space and save off string indicating current error.
drh2ce15c32017-07-11 13:34:40 +00002642*/
2643static char *save_err_msg(
larrybrf9a49b02021-10-26 16:57:09 +00002644 sqlite3 *db, /* Database to query */
drh633c7982022-02-08 12:13:16 +00002645 const char *zPhase, /* When the error occcurs */
drhf62641e2021-12-24 20:22:13 +00002646 int rc, /* Error code returned from API */
2647 const char *zSql /* SQL string, or NULL */
drh2ce15c32017-07-11 13:34:40 +00002648){
drhe3e25652021-12-16 13:29:28 +00002649 char *zErr;
drhf62641e2021-12-24 20:22:13 +00002650 char *zContext;
drh633c7982022-02-08 12:13:16 +00002651 sqlite3_str *pStr = sqlite3_str_new(0);
2652 sqlite3_str_appendf(pStr, "%s, %s", zPhase, sqlite3_errmsg(db));
2653 if( rc>1 ){
2654 sqlite3_str_appendf(pStr, " (%d)", rc);
2655 }
drhf62641e2021-12-24 20:22:13 +00002656 zContext = shell_error_context(zSql, db);
drh633c7982022-02-08 12:13:16 +00002657 if( zContext ){
2658 sqlite3_str_appendall(pStr, zContext);
2659 sqlite3_free(zContext);
2660 }
2661 zErr = sqlite3_str_finish(pStr);
drhe3e25652021-12-16 13:29:28 +00002662 shell_check_oom(zErr);
2663 return zErr;
drh2ce15c32017-07-11 13:34:40 +00002664}
2665
2666#ifdef __linux__
2667/*
2668** Attempt to display I/O stats on Linux using /proc/PID/io
2669*/
2670static void displayLinuxIoStats(FILE *out){
2671 FILE *in;
2672 char z[200];
2673 sqlite3_snprintf(sizeof(z), z, "/proc/%d/io", getpid());
2674 in = fopen(z, "rb");
2675 if( in==0 ) return;
2676 while( fgets(z, sizeof(z), in)!=0 ){
2677 static const struct {
2678 const char *zPattern;
2679 const char *zDesc;
2680 } aTrans[] = {
2681 { "rchar: ", "Bytes received by read():" },
2682 { "wchar: ", "Bytes sent to write():" },
2683 { "syscr: ", "Read() system calls:" },
2684 { "syscw: ", "Write() system calls:" },
2685 { "read_bytes: ", "Bytes read from storage:" },
2686 { "write_bytes: ", "Bytes written to storage:" },
2687 { "cancelled_write_bytes: ", "Cancelled write bytes:" },
2688 };
2689 int i;
2690 for(i=0; i<ArraySize(aTrans); i++){
drhaf2770f2018-01-05 14:55:43 +00002691 int n = strlen30(aTrans[i].zPattern);
drh2ce15c32017-07-11 13:34:40 +00002692 if( strncmp(aTrans[i].zPattern, z, n)==0 ){
2693 utf8_printf(out, "%-36s %s", aTrans[i].zDesc, &z[n]);
2694 break;
2695 }
2696 }
2697 }
2698 fclose(in);
2699}
2700#endif
2701
2702/*
2703** Display a single line of status using 64-bit values.
2704*/
2705static void displayStatLine(
2706 ShellState *p, /* The shell context */
2707 char *zLabel, /* Label for this one line */
2708 char *zFormat, /* Format for the result */
2709 int iStatusCtrl, /* Which status to display */
2710 int bReset /* True to reset the stats */
2711){
2712 sqlite3_int64 iCur = -1;
2713 sqlite3_int64 iHiwtr = -1;
2714 int i, nPercent;
2715 char zLine[200];
2716 sqlite3_status64(iStatusCtrl, &iCur, &iHiwtr, bReset);
2717 for(i=0, nPercent=0; zFormat[i]; i++){
2718 if( zFormat[i]=='%' ) nPercent++;
2719 }
2720 if( nPercent>1 ){
2721 sqlite3_snprintf(sizeof(zLine), zLine, zFormat, iCur, iHiwtr);
2722 }else{
2723 sqlite3_snprintf(sizeof(zLine), zLine, zFormat, iHiwtr);
2724 }
2725 raw_printf(p->out, "%-36s %s\n", zLabel, zLine);
2726}
2727
2728/*
2729** Display memory stats.
2730*/
2731static int display_stats(
2732 sqlite3 *db, /* Database to query */
2733 ShellState *pArg, /* Pointer to ShellState */
2734 int bReset /* True to reset the stats */
2735){
2736 int iCur;
2737 int iHiwtr;
drh393344f2018-03-09 16:37:05 +00002738 FILE *out;
2739 if( pArg==0 || pArg->out==0 ) return 0;
2740 out = pArg->out;
drh2ce15c32017-07-11 13:34:40 +00002741
drha6e6cf22021-01-09 19:10:04 +00002742 if( pArg->pStmt && pArg->statsOn==2 ){
drh393344f2018-03-09 16:37:05 +00002743 int nCol, i, x;
2744 sqlite3_stmt *pStmt = pArg->pStmt;
2745 char z[100];
2746 nCol = sqlite3_column_count(pStmt);
2747 raw_printf(out, "%-36s %d\n", "Number of output columns:", nCol);
2748 for(i=0; i<nCol; i++){
2749 sqlite3_snprintf(sizeof(z),z,"Column %d %nname:", i, &x);
2750 utf8_printf(out, "%-36s %s\n", z, sqlite3_column_name(pStmt,i));
drh929cce82018-03-17 16:26:36 +00002751#ifndef SQLITE_OMIT_DECLTYPE
drh393344f2018-03-09 16:37:05 +00002752 sqlite3_snprintf(30, z+x, "declared type:");
2753 utf8_printf(out, "%-36s %s\n", z, sqlite3_column_decltype(pStmt, i));
drh929cce82018-03-17 16:26:36 +00002754#endif
2755#ifdef SQLITE_ENABLE_COLUMN_METADATA
drh393344f2018-03-09 16:37:05 +00002756 sqlite3_snprintf(30, z+x, "database name:");
2757 utf8_printf(out, "%-36s %s\n", z, sqlite3_column_database_name(pStmt,i));
2758 sqlite3_snprintf(30, z+x, "table name:");
2759 utf8_printf(out, "%-36s %s\n", z, sqlite3_column_table_name(pStmt,i));
2760 sqlite3_snprintf(30, z+x, "origin name:");
2761 utf8_printf(out, "%-36s %s\n", z, sqlite3_column_origin_name(pStmt,i));
drh929cce82018-03-17 16:26:36 +00002762#endif
drh2ce15c32017-07-11 13:34:40 +00002763 }
drh929cce82018-03-17 16:26:36 +00002764 }
drh2ce15c32017-07-11 13:34:40 +00002765
drha6e6cf22021-01-09 19:10:04 +00002766 if( pArg->statsOn==3 ){
2767 if( pArg->pStmt ){
2768 iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_VM_STEP, bReset);
2769 raw_printf(pArg->out, "VM-steps: %d\n", iCur);
2770 }
2771 return 0;
2772 }
2773
drh393344f2018-03-09 16:37:05 +00002774 displayStatLine(pArg, "Memory Used:",
2775 "%lld (max %lld) bytes", SQLITE_STATUS_MEMORY_USED, bReset);
2776 displayStatLine(pArg, "Number of Outstanding Allocations:",
2777 "%lld (max %lld)", SQLITE_STATUS_MALLOC_COUNT, bReset);
2778 if( pArg->shellFlgs & SHFLG_Pagecache ){
2779 displayStatLine(pArg, "Number of Pcache Pages Used:",
2780 "%lld (max %lld) pages", SQLITE_STATUS_PAGECACHE_USED, bReset);
2781 }
2782 displayStatLine(pArg, "Number of Pcache Overflow Bytes:",
2783 "%lld (max %lld) bytes", SQLITE_STATUS_PAGECACHE_OVERFLOW, bReset);
2784 displayStatLine(pArg, "Largest Allocation:",
2785 "%lld bytes", SQLITE_STATUS_MALLOC_SIZE, bReset);
2786 displayStatLine(pArg, "Largest Pcache Allocation:",
2787 "%lld bytes", SQLITE_STATUS_PAGECACHE_SIZE, bReset);
2788#ifdef YYTRACKMAXSTACKDEPTH
2789 displayStatLine(pArg, "Deepest Parser Stack:",
2790 "%lld (max %lld)", SQLITE_STATUS_PARSER_STACK, bReset);
2791#endif
2792
2793 if( db ){
drh2ce15c32017-07-11 13:34:40 +00002794 if( pArg->shellFlgs & SHFLG_Lookaside ){
2795 iHiwtr = iCur = -1;
2796 sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_USED,
2797 &iCur, &iHiwtr, bReset);
2798 raw_printf(pArg->out,
2799 "Lookaside Slots Used: %d (max %d)\n",
2800 iCur, iHiwtr);
2801 sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_HIT,
2802 &iCur, &iHiwtr, bReset);
2803 raw_printf(pArg->out, "Successful lookaside attempts: %d\n",
2804 iHiwtr);
2805 sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE,
2806 &iCur, &iHiwtr, bReset);
2807 raw_printf(pArg->out, "Lookaside failures due to size: %d\n",
2808 iHiwtr);
2809 sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL,
2810 &iCur, &iHiwtr, bReset);
2811 raw_printf(pArg->out, "Lookaside failures due to OOM: %d\n",
2812 iHiwtr);
2813 }
2814 iHiwtr = iCur = -1;
2815 sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_USED, &iCur, &iHiwtr, bReset);
2816 raw_printf(pArg->out, "Pager Heap Usage: %d bytes\n",
2817 iCur);
2818 iHiwtr = iCur = -1;
2819 sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_HIT, &iCur, &iHiwtr, 1);
2820 raw_printf(pArg->out, "Page cache hits: %d\n", iCur);
2821 iHiwtr = iCur = -1;
2822 sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_MISS, &iCur, &iHiwtr, 1);
2823 raw_printf(pArg->out, "Page cache misses: %d\n", iCur);
2824 iHiwtr = iCur = -1;
2825 sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_WRITE, &iCur, &iHiwtr, 1);
2826 raw_printf(pArg->out, "Page cache writes: %d\n", iCur);
2827 iHiwtr = iCur = -1;
drhffc78a42018-03-14 14:53:50 +00002828 sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_SPILL, &iCur, &iHiwtr, 1);
2829 raw_printf(pArg->out, "Page cache spills: %d\n", iCur);
2830 iHiwtr = iCur = -1;
drh2ce15c32017-07-11 13:34:40 +00002831 sqlite3_db_status(db, SQLITE_DBSTATUS_SCHEMA_USED, &iCur, &iHiwtr, bReset);
2832 raw_printf(pArg->out, "Schema Heap Usage: %d bytes\n",
2833 iCur);
2834 iHiwtr = iCur = -1;
2835 sqlite3_db_status(db, SQLITE_DBSTATUS_STMT_USED, &iCur, &iHiwtr, bReset);
2836 raw_printf(pArg->out, "Statement Heap/Lookaside Usage: %d bytes\n",
2837 iCur);
2838 }
2839
drh393344f2018-03-09 16:37:05 +00002840 if( pArg->pStmt ){
drh23d41e62021-12-06 21:45:31 +00002841 int iHit, iMiss;
drh2ce15c32017-07-11 13:34:40 +00002842 iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_FULLSCAN_STEP,
2843 bReset);
2844 raw_printf(pArg->out, "Fullscan Steps: %d\n", iCur);
2845 iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_SORT, bReset);
2846 raw_printf(pArg->out, "Sort Operations: %d\n", iCur);
2847 iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_AUTOINDEX,bReset);
2848 raw_printf(pArg->out, "Autoindex Inserts: %d\n", iCur);
drh23d41e62021-12-06 21:45:31 +00002849 iHit = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_FILTER_HIT, bReset);
2850 iMiss = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_FILTER_MISS, bReset);
2851 if( iHit || iMiss ){
2852 raw_printf(pArg->out, "Bloom filter bypass taken: %d/%d\n",
2853 iHit, iHit+iMiss);
2854 }
drh2ce15c32017-07-11 13:34:40 +00002855 iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_VM_STEP, bReset);
2856 raw_printf(pArg->out, "Virtual Machine Steps: %d\n", iCur);
drhe2754c12019-08-26 12:50:01 +00002857 iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_REPREPARE,bReset);
drh393344f2018-03-09 16:37:05 +00002858 raw_printf(pArg->out, "Reprepare operations: %d\n", iCur);
2859 iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_RUN, bReset);
2860 raw_printf(pArg->out, "Number of times run: %d\n", iCur);
2861 iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_MEMUSED, bReset);
2862 raw_printf(pArg->out, "Memory used by prepared stmt: %d\n", iCur);
drh2ce15c32017-07-11 13:34:40 +00002863 }
2864
2865#ifdef __linux__
2866 displayLinuxIoStats(pArg->out);
2867#endif
2868
2869 /* Do not remove this machine readable comment: extra-stats-output-here */
2870
2871 return 0;
2872}
2873
2874/*
2875** Display scan stats.
2876*/
2877static void display_scanstats(
2878 sqlite3 *db, /* Database to query */
2879 ShellState *pArg /* Pointer to ShellState */
2880){
2881#ifndef SQLITE_ENABLE_STMT_SCANSTATUS
2882 UNUSED_PARAMETER(db);
2883 UNUSED_PARAMETER(pArg);
2884#else
2885 int i, k, n, mx;
2886 raw_printf(pArg->out, "-------- scanstats --------\n");
2887 mx = 0;
2888 for(k=0; k<=mx; k++){
2889 double rEstLoop = 1.0;
2890 for(i=n=0; 1; i++){
2891 sqlite3_stmt *p = pArg->pStmt;
2892 sqlite3_int64 nLoop, nVisit;
2893 double rEst;
2894 int iSid;
2895 const char *zExplain;
2896 if( sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_NLOOP, (void*)&nLoop) ){
2897 break;
2898 }
2899 sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_SELECTID, (void*)&iSid);
2900 if( iSid>mx ) mx = iSid;
2901 if( iSid!=k ) continue;
2902 if( n==0 ){
2903 rEstLoop = (double)nLoop;
2904 if( k>0 ) raw_printf(pArg->out, "-------- subquery %d -------\n", k);
2905 }
2906 n++;
2907 sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_NVISIT, (void*)&nVisit);
2908 sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_EST, (void*)&rEst);
2909 sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_EXPLAIN, (void*)&zExplain);
2910 utf8_printf(pArg->out, "Loop %2d: %s\n", n, zExplain);
2911 rEstLoop *= rEst;
2912 raw_printf(pArg->out,
2913 " nLoop=%-8lld nRow=%-8lld estRow=%-8lld estRow/Loop=%-8g\n",
2914 nLoop, nVisit, (sqlite3_int64)(rEstLoop+0.5), rEst
2915 );
2916 }
2917 }
2918 raw_printf(pArg->out, "---------------------------\n");
2919#endif
2920}
2921
2922/*
2923** Parameter azArray points to a zero-terminated array of strings. zStr
2924** points to a single nul-terminated string. Return non-zero if zStr
2925** is equal, according to strcmp(), to any of the strings in the array.
2926** Otherwise, return zero.
2927*/
2928static int str_in_array(const char *zStr, const char **azArray){
2929 int i;
2930 for(i=0; azArray[i]; i++){
2931 if( 0==strcmp(zStr, azArray[i]) ) return 1;
2932 }
2933 return 0;
2934}
2935
2936/*
2937** If compiled statement pSql appears to be an EXPLAIN statement, allocate
2938** and populate the ShellState.aiIndent[] array with the number of
2939** spaces each opcode should be indented before it is output.
2940**
2941** The indenting rules are:
2942**
2943** * For each "Next", "Prev", "VNext" or "VPrev" instruction, indent
2944** all opcodes that occur between the p2 jump destination and the opcode
2945** itself by 2 spaces.
2946**
drhe603ab02022-04-07 19:06:31 +00002947** * Do the previous for "Return" instructions for when P2 is positive.
2948** See tag-20220407a in wherecode.c and vdbe.c.
2949**
drh2ce15c32017-07-11 13:34:40 +00002950** * For each "Goto", if the jump destination is earlier in the program
2951** and ends on one of:
2952** Yield SeekGt SeekLt RowSetRead Rewind
2953** or if the P1 parameter is one instead of zero,
2954** then indent all opcodes between the earlier instruction
2955** and "Goto" by 2 spaces.
2956*/
2957static void explain_data_prepare(ShellState *p, sqlite3_stmt *pSql){
2958 const char *zSql; /* The text of the SQL statement */
2959 const char *z; /* Used to check if this is an EXPLAIN */
2960 int *abYield = 0; /* True if op is an OP_Yield */
2961 int nAlloc = 0; /* Allocated size of p->aiIndent[], abYield */
2962 int iOp; /* Index of operation in p->aiIndent[] */
2963
drhe603ab02022-04-07 19:06:31 +00002964 const char *azNext[] = { "Next", "Prev", "VPrev", "VNext", "SorterNext",
2965 "Return", 0 };
drh2ce15c32017-07-11 13:34:40 +00002966 const char *azYield[] = { "Yield", "SeekLT", "SeekGT", "RowSetRead",
2967 "Rewind", 0 };
2968 const char *azGoto[] = { "Goto", 0 };
2969
2970 /* Try to figure out if this is really an EXPLAIN statement. If this
2971 ** cannot be verified, return early. */
2972 if( sqlite3_column_count(pSql)!=8 ){
2973 p->cMode = p->mode;
2974 return;
2975 }
2976 zSql = sqlite3_sql(pSql);
2977 if( zSql==0 ) return;
2978 for(z=zSql; *z==' ' || *z=='\t' || *z=='\n' || *z=='\f' || *z=='\r'; z++);
2979 if( sqlite3_strnicmp(z, "explain", 7) ){
2980 p->cMode = p->mode;
2981 return;
2982 }
2983
2984 for(iOp=0; SQLITE_ROW==sqlite3_step(pSql); iOp++){
2985 int i;
2986 int iAddr = sqlite3_column_int(pSql, 0);
2987 const char *zOp = (const char*)sqlite3_column_text(pSql, 1);
2988
2989 /* Set p2 to the P2 field of the current opcode. Then, assuming that
2990 ** p2 is an instruction address, set variable p2op to the index of that
2991 ** instruction in the aiIndent[] array. p2 and p2op may be different if
2992 ** the current instruction is part of a sub-program generated by an
2993 ** SQL trigger or foreign key. */
2994 int p2 = sqlite3_column_int(pSql, 3);
2995 int p2op = (p2 + (iOp-iAddr));
2996
2997 /* Grow the p->aiIndent array as required */
2998 if( iOp>=nAlloc ){
2999 if( iOp==0 ){
3000 /* Do further verfication that this is explain output. Abort if
3001 ** it is not */
3002 static const char *explainCols[] = {
3003 "addr", "opcode", "p1", "p2", "p3", "p4", "p5", "comment" };
3004 int jj;
3005 for(jj=0; jj<ArraySize(explainCols); jj++){
3006 if( strcmp(sqlite3_column_name(pSql,jj),explainCols[jj])!=0 ){
3007 p->cMode = p->mode;
3008 sqlite3_reset(pSql);
3009 return;
3010 }
3011 }
3012 }
3013 nAlloc += 100;
3014 p->aiIndent = (int*)sqlite3_realloc64(p->aiIndent, nAlloc*sizeof(int));
drhe3e25652021-12-16 13:29:28 +00003015 shell_check_oom(p->aiIndent);
drh2ce15c32017-07-11 13:34:40 +00003016 abYield = (int*)sqlite3_realloc64(abYield, nAlloc*sizeof(int));
drhe3e25652021-12-16 13:29:28 +00003017 shell_check_oom(abYield);
drh2ce15c32017-07-11 13:34:40 +00003018 }
3019 abYield[iOp] = str_in_array(zOp, azYield);
3020 p->aiIndent[iOp] = 0;
3021 p->nIndent = iOp+1;
3022
drhe603ab02022-04-07 19:06:31 +00003023 if( str_in_array(zOp, azNext) && p2op>0 ){
drh2ce15c32017-07-11 13:34:40 +00003024 for(i=p2op; i<iOp; i++) p->aiIndent[i] += 2;
3025 }
3026 if( str_in_array(zOp, azGoto) && p2op<p->nIndent
3027 && (abYield[p2op] || sqlite3_column_int(pSql, 2))
3028 ){
3029 for(i=p2op; i<iOp; i++) p->aiIndent[i] += 2;
3030 }
3031 }
3032
3033 p->iIndent = 0;
3034 sqlite3_free(abYield);
3035 sqlite3_reset(pSql);
3036}
3037
3038/*
3039** Free the array allocated by explain_data_prepare().
3040*/
3041static void explain_data_delete(ShellState *p){
3042 sqlite3_free(p->aiIndent);
3043 p->aiIndent = 0;
3044 p->nIndent = 0;
3045 p->iIndent = 0;
3046}
3047
3048/*
drh5e431be2022-04-06 11:08:38 +00003049** Disable and restore .wheretrace and .treetrace/.selecttrace settings.
drh2ce15c32017-07-11 13:34:40 +00003050*/
drhc0622a42020-12-04 01:17:57 +00003051static unsigned int savedSelectTrace;
3052static unsigned int savedWhereTrace;
drh2ce15c32017-07-11 13:34:40 +00003053static void disable_debug_trace_modes(void){
drh0a2fb792020-12-04 16:58:20 +00003054 unsigned int zero = 0;
drhc0622a42020-12-04 01:17:57 +00003055 sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 0, &savedSelectTrace);
drh0a2fb792020-12-04 16:58:20 +00003056 sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 1, &zero);
drhc0622a42020-12-04 01:17:57 +00003057 sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 2, &savedWhereTrace);
drh0a2fb792020-12-04 16:58:20 +00003058 sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 3, &zero);
drh2ce15c32017-07-11 13:34:40 +00003059}
3060static void restore_debug_trace_modes(void){
drhc0622a42020-12-04 01:17:57 +00003061 sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 1, &savedSelectTrace);
3062 sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 3, &savedWhereTrace);
drh2ce15c32017-07-11 13:34:40 +00003063}
3064
drh9cb02642019-02-28 20:10:52 +00003065/* Create the TEMP table used to store parameter bindings */
3066static void bind_table_init(ShellState *p){
drh346f4e22019-03-25 21:35:41 +00003067 int wrSchema = 0;
drh4b86e202020-01-19 20:37:26 +00003068 int defensiveMode = 0;
3069 sqlite3_db_config(p->db, SQLITE_DBCONFIG_DEFENSIVE, -1, &defensiveMode);
3070 sqlite3_db_config(p->db, SQLITE_DBCONFIG_DEFENSIVE, 0, 0);
drh346f4e22019-03-25 21:35:41 +00003071 sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, -1, &wrSchema);
3072 sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, 1, 0);
drh9cb02642019-02-28 20:10:52 +00003073 sqlite3_exec(p->db,
drh65c29fd2019-03-25 21:56:26 +00003074 "CREATE TABLE IF NOT EXISTS temp.sqlite_parameters(\n"
drh9cb02642019-02-28 20:10:52 +00003075 " key TEXT PRIMARY KEY,\n"
larrybrdabada62021-04-04 12:52:58 +00003076 " value\n"
drh9cb02642019-02-28 20:10:52 +00003077 ") WITHOUT ROWID;",
3078 0, 0, 0);
drh346f4e22019-03-25 21:35:41 +00003079 sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, wrSchema, 0);
drh4b86e202020-01-19 20:37:26 +00003080 sqlite3_db_config(p->db, SQLITE_DBCONFIG_DEFENSIVE, defensiveMode, 0);
drh9cb02642019-02-28 20:10:52 +00003081}
3082
drh8b738d02019-02-25 18:43:54 +00003083/*
3084** Bind parameters on a prepared statement.
3085**
3086** Parameter bindings are taken from a TEMP table of the form:
3087**
drh1cb02632019-03-25 22:05:22 +00003088** CREATE TEMP TABLE sqlite_parameters(key TEXT PRIMARY KEY, value)
drh8b738d02019-02-25 18:43:54 +00003089** WITHOUT ROWID;
3090**
drh91654b22020-04-02 13:21:10 +00003091** No bindings occur if this table does not exist. The name of the table
3092** begins with "sqlite_" so that it will not collide with ordinary application
3093** tables. The table must be in the TEMP schema.
drh8b738d02019-02-25 18:43:54 +00003094*/
3095static void bind_prepared_stmt(ShellState *pArg, sqlite3_stmt *pStmt){
3096 int nVar;
3097 int i;
3098 int rc;
3099 sqlite3_stmt *pQ = 0;
3100
3101 nVar = sqlite3_bind_parameter_count(pStmt);
3102 if( nVar==0 ) return; /* Nothing to do */
drh65c29fd2019-03-25 21:56:26 +00003103 if( sqlite3_table_column_metadata(pArg->db, "TEMP", "sqlite_parameters",
drh8b738d02019-02-25 18:43:54 +00003104 "key", 0, 0, 0, 0, 0)!=SQLITE_OK ){
3105 return; /* Parameter table does not exist */
3106 }
3107 rc = sqlite3_prepare_v2(pArg->db,
drh65c29fd2019-03-25 21:56:26 +00003108 "SELECT value FROM temp.sqlite_parameters"
drh8b738d02019-02-25 18:43:54 +00003109 " WHERE key=?1", -1, &pQ, 0);
3110 if( rc || pQ==0 ) return;
3111 for(i=1; i<=nVar; i++){
3112 char zNum[30];
3113 const char *zVar = sqlite3_bind_parameter_name(pStmt, i);
3114 if( zVar==0 ){
3115 sqlite3_snprintf(sizeof(zNum),zNum,"?%d",i);
3116 zVar = zNum;
3117 }
3118 sqlite3_bind_text(pQ, 1, zVar, -1, SQLITE_STATIC);
3119 if( sqlite3_step(pQ)==SQLITE_ROW ){
3120 sqlite3_bind_value(pStmt, i, sqlite3_column_value(pQ, 0));
3121 }else{
3122 sqlite3_bind_null(pStmt, i);
3123 }
3124 sqlite3_reset(pQ);
3125 }
3126 sqlite3_finalize(pQ);
3127}
3128
drh30c54a02020-05-28 23:49:50 +00003129/*
drh0908e382020-06-04 18:05:39 +00003130** UTF8 box-drawing characters. Imagine box lines like this:
3131**
3132** 1
3133** |
3134** 4 --+-- 2
3135** |
3136** 3
3137**
3138** Each box characters has between 2 and 4 of the lines leading from
3139** the center. The characters are here identified by the numbers of
3140** their corresponding lines.
3141*/
3142#define BOX_24 "\342\224\200" /* U+2500 --- */
3143#define BOX_13 "\342\224\202" /* U+2502 | */
3144#define BOX_23 "\342\224\214" /* U+250c ,- */
3145#define BOX_34 "\342\224\220" /* U+2510 -, */
3146#define BOX_12 "\342\224\224" /* U+2514 '- */
3147#define BOX_14 "\342\224\230" /* U+2518 -' */
3148#define BOX_123 "\342\224\234" /* U+251c |- */
3149#define BOX_134 "\342\224\244" /* U+2524 -| */
3150#define BOX_234 "\342\224\254" /* U+252c -,- */
3151#define BOX_124 "\342\224\264" /* U+2534 -'- */
3152#define BOX_1234 "\342\224\274" /* U+253c -|- */
3153
3154/* Draw horizontal line N characters long using unicode box
3155** characters
3156*/
3157static void print_box_line(FILE *out, int N){
3158 const char zDash[] =
3159 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24
3160 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24;
3161 const int nDash = sizeof(zDash) - 1;
3162 N *= 3;
3163 while( N>nDash ){
3164 utf8_printf(out, zDash);
3165 N -= nDash;
3166 }
3167 utf8_printf(out, "%.*s", N, zDash);
3168}
3169
3170/*
3171** Draw a horizontal separator for a MODE_Box table.
3172*/
3173static void print_box_row_separator(
3174 ShellState *p,
3175 int nArg,
3176 const char *zSep1,
3177 const char *zSep2,
3178 const char *zSep3
3179){
3180 int i;
3181 if( nArg>0 ){
3182 utf8_printf(p->out, "%s", zSep1);
3183 print_box_line(p->out, p->actualWidth[0]+2);
3184 for(i=1; i<nArg; i++){
3185 utf8_printf(p->out, "%s", zSep2);
3186 print_box_line(p->out, p->actualWidth[i]+2);
3187 }
3188 utf8_printf(p->out, "%s", zSep3);
3189 }
3190 fputs("\n", p->out);
3191}
3192
drh09a39ed2022-01-30 21:09:03 +00003193/*
3194** z[] is a line of text that is to be displayed the .mode box or table or
3195** similar tabular formats. z[] might contain control characters such
3196** as \n, \t, \f, or \r.
3197**
3198** Compute characters to display on the first line of z[]. Stop at the
3199** first \r, \n, or \f. Expand \t into spaces. Return a copy (obtained
larrybrcc4d55c2022-02-01 02:50:45 +00003200** from malloc()) of that first line, which caller should free sometime.
3201** Write anything to display on the next line into *pzTail. If this is
3202** the last line, write a NULL into *pzTail. (*pzTail is not allocated.)
drh09a39ed2022-01-30 21:09:03 +00003203*/
3204static char *translateForDisplayAndDup(
drhca1776b2022-02-01 12:28:17 +00003205 const unsigned char *z, /* Input text to be transformed */
3206 const unsigned char **pzTail, /* OUT: Tail of the input for next line */
3207 int mxWidth, /* Max width. 0 means no limit */
3208 u8 bWordWrap /* If true, avoid breaking mid-word */
drh09a39ed2022-01-30 21:09:03 +00003209){
drhca1776b2022-02-01 12:28:17 +00003210 int i; /* Input bytes consumed */
3211 int j; /* Output bytes generated */
3212 int k; /* Input bytes to be displayed */
3213 int n; /* Output column number */
3214 unsigned char *zOut; /* Output text */
3215
drh09a39ed2022-01-30 21:09:03 +00003216 if( z==0 ){
3217 *pzTail = 0;
3218 return 0;
3219 }
3220 if( mxWidth<0 ) mxWidth = -mxWidth;
3221 if( mxWidth==0 ) mxWidth = 1000000;
drhca1776b2022-02-01 12:28:17 +00003222 i = j = n = 0;
drh09a39ed2022-01-30 21:09:03 +00003223 while( n<mxWidth ){
3224 if( z[i]>=' ' ){
3225 n++;
drhb6172192022-01-31 10:55:50 +00003226 do{ i++; j++; }while( (z[i]&0xc0)==0x80 );
drh09a39ed2022-01-30 21:09:03 +00003227 continue;
3228 }
3229 if( z[i]=='\t' ){
drhb6172192022-01-31 10:55:50 +00003230 do{
3231 n++;
3232 j++;
3233 }while( (n&7)!=0 && n<mxWidth );
drh09a39ed2022-01-30 21:09:03 +00003234 i++;
3235 continue;
3236 }
3237 break;
3238 }
drhca1776b2022-02-01 12:28:17 +00003239 if( n>=mxWidth && bWordWrap ){
3240 /* Perhaps try to back up to a better place to break the line */
3241 for(k=i; k>i/2; k--){
3242 if( isspace(z[k-1]) ) break;
3243 }
3244 if( k<=i/2 ){
3245 for(k=i; k>i/2; k--){
drhe66532a2022-02-01 13:17:11 +00003246 if( isalnum(z[k-1])!=isalnum(z[k]) && (z[k]&0xc0)!=0x80 ) break;
drhca1776b2022-02-01 12:28:17 +00003247 }
3248 }
3249 if( k<=i/2 ){
3250 k = i;
3251 }else{
3252 i = k;
3253 while( z[i]==' ' ) i++;
3254 }
3255 }else{
3256 k = i;
larrybrcc4d55c2022-02-01 02:50:45 +00003257 }
drh09a39ed2022-01-30 21:09:03 +00003258 if( n>=mxWidth && z[i]>=' ' ){
3259 *pzTail = &z[i];
3260 }else if( z[i]=='\r' && z[i+1]=='\n' ){
3261 *pzTail = z[i+2] ? &z[i+2] : 0;
drhb6172192022-01-31 10:55:50 +00003262 }else if( z[i]==0 || z[i+1]==0 ){
drh09a39ed2022-01-30 21:09:03 +00003263 *pzTail = 0;
3264 }else{
3265 *pzTail = &z[i+1];
3266 }
drhb6172192022-01-31 10:55:50 +00003267 zOut = malloc( j+1 );
drh09a39ed2022-01-30 21:09:03 +00003268 shell_check_oom(zOut);
drhb6172192022-01-31 10:55:50 +00003269 i = j = n = 0;
drhca1776b2022-02-01 12:28:17 +00003270 while( i<k ){
drh09a39ed2022-01-30 21:09:03 +00003271 if( z[i]>=' ' ){
drhb6172192022-01-31 10:55:50 +00003272 n++;
3273 do{ zOut[j++] = z[i++]; }while( (z[i]&0xc0)==0x80 );
drh09a39ed2022-01-30 21:09:03 +00003274 continue;
3275 }
3276 if( z[i]=='\t' ){
3277 do{
drhb6172192022-01-31 10:55:50 +00003278 n++;
3279 zOut[j++] = ' ';
drh09a39ed2022-01-30 21:09:03 +00003280 }while( (n&7)!=0 && n<mxWidth );
3281 i++;
3282 continue;
3283 }
3284 break;
3285 }
drhb6172192022-01-31 10:55:50 +00003286 zOut[j] = 0;
drh09a39ed2022-01-30 21:09:03 +00003287 return (char*)zOut;
3288}
3289
drhe40f2862022-01-31 14:14:29 +00003290/* Extract the value of the i-th current column for pStmt as an SQL literal
3291** value. Memory is obtained from sqlite3_malloc64() and must be freed by
3292** the caller.
3293*/
3294static char *quoted_column(sqlite3_stmt *pStmt, int i){
3295 switch( sqlite3_column_type(pStmt, i) ){
3296 case SQLITE_NULL: {
3297 return sqlite3_mprintf("NULL");
3298 }
3299 case SQLITE_INTEGER:
3300 case SQLITE_FLOAT: {
3301 return sqlite3_mprintf("%s",sqlite3_column_text(pStmt,i));
3302 }
3303 case SQLITE_TEXT: {
3304 return sqlite3_mprintf("%Q",sqlite3_column_text(pStmt,i));
3305 }
3306 case SQLITE_BLOB: {
3307 int j;
3308 sqlite3_str *pStr = sqlite3_str_new(0);
3309 const unsigned char *a = sqlite3_column_blob(pStmt,i);
3310 int n = sqlite3_column_bytes(pStmt,i);
3311 sqlite3_str_append(pStr, "x'", 2);
3312 for(j=0; j<n; j++){
3313 sqlite3_str_appendf(pStr, "%02x", a[j]);
3314 }
3315 sqlite3_str_append(pStr, "'", 1);
3316 return sqlite3_str_finish(pStr);
3317 }
3318 }
3319 return 0; /* Not reached */
3320}
drh0908e382020-06-04 18:05:39 +00003321
3322/*
drh30c54a02020-05-28 23:49:50 +00003323** Run a prepared statement and output the result in one of the
drh0908e382020-06-04 18:05:39 +00003324** table-oriented formats: MODE_Column, MODE_Markdown, MODE_Table,
3325** or MODE_Box.
drh30c54a02020-05-28 23:49:50 +00003326**
3327** This is different from ordinary exec_prepared_stmt() in that
3328** it has to run the entire query and gather the results into memory
3329** first, in order to determine column widths, before providing
3330** any output.
3331*/
drh8c748632020-05-29 16:15:58 +00003332static void exec_prepared_stmt_columnar(
3333 ShellState *p, /* Pointer to ShellState */
3334 sqlite3_stmt *pStmt /* Statment to run */
drh30c54a02020-05-28 23:49:50 +00003335){
drhf82ce382020-08-06 16:45:22 +00003336 sqlite3_int64 nRow = 0;
drh8c748632020-05-29 16:15:58 +00003337 int nColumn = 0;
3338 char **azData = 0;
drhf82ce382020-08-06 16:45:22 +00003339 sqlite3_int64 nAlloc = 0;
drh09a39ed2022-01-30 21:09:03 +00003340 char *abRowDiv = 0;
3341 const unsigned char *uz;
drh8c748632020-05-29 16:15:58 +00003342 const char *z;
drhe40f2862022-01-31 14:14:29 +00003343 char **azQuoted = 0;
drh8c748632020-05-29 16:15:58 +00003344 int rc;
drhf82ce382020-08-06 16:45:22 +00003345 sqlite3_int64 i, nData;
3346 int j, nTotal, w, n;
drh0908e382020-06-04 18:05:39 +00003347 const char *colSep = 0;
3348 const char *rowSep = 0;
drh09a39ed2022-01-30 21:09:03 +00003349 const unsigned char **azNextLine = 0;
3350 int bNextLine = 0;
3351 int bMultiLineRowExists = 0;
drhca1776b2022-02-01 12:28:17 +00003352 int bw = p->cmOpts.bWordWrap;
larrybr6403e772022-04-20 22:41:10 +00003353 const char *zEmpty = "";
3354 const char *zShowNull = p->nullValue;
drh30c54a02020-05-28 23:49:50 +00003355
drhf82ce382020-08-06 16:45:22 +00003356 rc = sqlite3_step(pStmt);
3357 if( rc!=SQLITE_ROW ) return;
3358 nColumn = sqlite3_column_count(pStmt);
3359 nAlloc = nColumn*4;
drh01a8ad22021-03-20 23:15:52 +00003360 if( nAlloc<=0 ) nAlloc = 1;
drhf82ce382020-08-06 16:45:22 +00003361 azData = sqlite3_malloc64( nAlloc*sizeof(char*) );
drhe3e25652021-12-16 13:29:28 +00003362 shell_check_oom(azData);
drh09a39ed2022-01-30 21:09:03 +00003363 azNextLine = sqlite3_malloc64( nColumn*sizeof(char*) );
drh5dce6f92022-01-31 16:29:06 +00003364 shell_check_oom((void*)azNextLine);
3365 memset((void*)azNextLine, 0, nColumn*sizeof(char*) );
larrybrcc4d55c2022-02-01 02:50:45 +00003366 if( p->cmOpts.bQuote ){
drhe40f2862022-01-31 14:14:29 +00003367 azQuoted = sqlite3_malloc64( nColumn*sizeof(char*) );
3368 shell_check_oom(azQuoted);
3369 memset(azQuoted, 0, nColumn*sizeof(char*) );
3370 }
drh09a39ed2022-01-30 21:09:03 +00003371 abRowDiv = sqlite3_malloc64( nAlloc/nColumn );
3372 shell_check_oom(abRowDiv);
drh8c748632020-05-29 16:15:58 +00003373 if( nColumn>p->nWidth ){
drh76fc88f2021-10-02 16:39:16 +00003374 p->colWidth = realloc(p->colWidth, (nColumn+1)*2*sizeof(int));
drhe3e25652021-12-16 13:29:28 +00003375 shell_check_oom(p->colWidth);
drh8c748632020-05-29 16:15:58 +00003376 for(i=p->nWidth; i<nColumn; i++) p->colWidth[i] = 0;
3377 p->nWidth = nColumn;
3378 p->actualWidth = &p->colWidth[nColumn];
3379 }
3380 memset(p->actualWidth, 0, nColumn*sizeof(int));
3381 for(i=0; i<nColumn; i++){
3382 w = p->colWidth[i];
3383 if( w<0 ) w = -w;
3384 p->actualWidth[i] = w;
3385 }
drh09a39ed2022-01-30 21:09:03 +00003386 for(i=0; i<nColumn; i++){
drh47741b82022-01-31 22:14:53 +00003387 const unsigned char *zNotUsed;
3388 int wx = p->colWidth[i];
larrybrcc4d55c2022-02-01 02:50:45 +00003389 if( wx==0 ){
3390 wx = p->cmOpts.iWrap;
larrybrcc4d55c2022-02-01 02:50:45 +00003391 }
drh47741b82022-01-31 22:14:53 +00003392 if( wx<0 ) wx = -wx;
3393 uz = (const unsigned char*)sqlite3_column_name(pStmt,i);
larrybrcc4d55c2022-02-01 02:50:45 +00003394 azData[i] = translateForDisplayAndDup(uz, &zNotUsed, wx, bw);
drh09a39ed2022-01-30 21:09:03 +00003395 }
3396 do{
3397 int useNextLine = bNextLine;
3398 bNextLine = 0;
3399 if( (nRow+2)*nColumn >= nAlloc ){
3400 nAlloc *= 2;
3401 azData = sqlite3_realloc64(azData, nAlloc*sizeof(char*));
3402 shell_check_oom(azData);
3403 abRowDiv = sqlite3_realloc64(abRowDiv, nAlloc/nColumn);
3404 shell_check_oom(abRowDiv);
3405 }
3406 abRowDiv[nRow] = 1;
3407 nRow++;
3408 for(i=0; i<nColumn; i++){
drh5dce6f92022-01-31 16:29:06 +00003409 int wx = p->colWidth[i];
larrybrcc4d55c2022-02-01 02:50:45 +00003410 if( wx==0 ){
3411 wx = p->cmOpts.iWrap;
larrybrcc4d55c2022-02-01 02:50:45 +00003412 }
drh47741b82022-01-31 22:14:53 +00003413 if( wx<0 ) wx = -wx;
drh09a39ed2022-01-30 21:09:03 +00003414 if( useNextLine ){
3415 uz = azNextLine[i];
drh7e9a56f2022-04-21 19:14:23 +00003416 if( uz==0 ) uz = (u8*)zEmpty;
larrybrcc4d55c2022-02-01 02:50:45 +00003417 }else if( p->cmOpts.bQuote ){
drhe40f2862022-01-31 14:14:29 +00003418 sqlite3_free(azQuoted[i]);
3419 azQuoted[i] = quoted_column(pStmt,i);
3420 uz = (const unsigned char*)azQuoted[i];
drh09a39ed2022-01-30 21:09:03 +00003421 }else{
3422 uz = (const unsigned char*)sqlite3_column_text(pStmt,i);
drh7e9a56f2022-04-21 19:14:23 +00003423 if( uz==0 ) uz = (u8*)zShowNull;
drh09a39ed2022-01-30 21:09:03 +00003424 }
larrybrcc4d55c2022-02-01 02:50:45 +00003425 azData[nRow*nColumn + i]
3426 = translateForDisplayAndDup(uz, &azNextLine[i], wx, bw);
drh09a39ed2022-01-30 21:09:03 +00003427 if( azNextLine[i] ){
3428 bNextLine = 1;
3429 abRowDiv[nRow-1] = 0;
3430 bMultiLineRowExists = 1;
3431 }
3432 }
3433 }while( bNextLine || sqlite3_step(pStmt)==SQLITE_ROW );
drh8c748632020-05-29 16:15:58 +00003434 nTotal = nColumn*(nRow+1);
3435 for(i=0; i<nTotal; i++){
3436 z = azData[i];
larrybr6403e772022-04-20 22:41:10 +00003437 if( z==0 ) z = (char*)zEmpty;
drh8c748632020-05-29 16:15:58 +00003438 n = strlenChar(z);
3439 j = i%nColumn;
3440 if( n>p->actualWidth[j] ) p->actualWidth[j] = n;
3441 }
drh99942982020-06-15 20:05:37 +00003442 if( seenInterrupt ) goto columnar_end;
drh01a8ad22021-03-20 23:15:52 +00003443 if( nColumn==0 ) goto columnar_end;
drh0908e382020-06-04 18:05:39 +00003444 switch( p->cMode ){
3445 case MODE_Column: {
3446 colSep = " ";
3447 rowSep = "\n";
3448 if( p->showHeader ){
3449 for(i=0; i<nColumn; i++){
3450 w = p->actualWidth[i];
3451 if( p->colWidth[i]<0 ) w = -w;
3452 utf8_width_print(p->out, w, azData[i]);
3453 fputs(i==nColumn-1?"\n":" ", p->out);
3454 }
3455 for(i=0; i<nColumn; i++){
3456 print_dashes(p->out, p->actualWidth[i]);
3457 fputs(i==nColumn-1?"\n":" ", p->out);
3458 }
3459 }
3460 break;
3461 }
3462 case MODE_Table: {
3463 colSep = " | ";
3464 rowSep = " |\n";
3465 print_row_separator(p, nColumn, "+");
3466 fputs("| ", p->out);
drh8c748632020-05-29 16:15:58 +00003467 for(i=0; i<nColumn; i++){
3468 w = p->actualWidth[i];
drh0908e382020-06-04 18:05:39 +00003469 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;
3475 }
3476 case MODE_Markdown: {
3477 colSep = " | ";
3478 rowSep = " |\n";
3479 fputs("| ", p->out);
drh8c748632020-05-29 16:15:58 +00003480 for(i=0; i<nColumn; i++){
drh0908e382020-06-04 18:05:39 +00003481 w = p->actualWidth[i];
3482 n = strlenChar(azData[i]);
3483 utf8_printf(p->out, "%*s%s%*s", (w-n)/2, "", azData[i], (w-n+1)/2, "");
3484 fputs(i==nColumn-1?" |\n":" | ", p->out);
drh8c748632020-05-29 16:15:58 +00003485 }
drh0908e382020-06-04 18:05:39 +00003486 print_row_separator(p, nColumn, "|");
3487 break;
drh8c748632020-05-29 16:15:58 +00003488 }
drh0908e382020-06-04 18:05:39 +00003489 case MODE_Box: {
3490 colSep = " " BOX_13 " ";
3491 rowSep = " " BOX_13 "\n";
3492 print_box_row_separator(p, nColumn, BOX_23, BOX_234, BOX_34);
3493 utf8_printf(p->out, BOX_13 " ");
3494 for(i=0; i<nColumn; i++){
3495 w = p->actualWidth[i];
3496 n = strlenChar(azData[i]);
3497 utf8_printf(p->out, "%*s%s%*s%s",
3498 (w-n)/2, "", azData[i], (w-n+1)/2, "",
3499 i==nColumn-1?" "BOX_13"\n":" "BOX_13" ");
3500 }
3501 print_box_row_separator(p, nColumn, BOX_123, BOX_1234, BOX_134);
3502 break;
drh8c748632020-05-29 16:15:58 +00003503 }
drh8c748632020-05-29 16:15:58 +00003504 }
3505 for(i=nColumn, j=0; i<nTotal; i++, j++){
drh0908e382020-06-04 18:05:39 +00003506 if( j==0 && p->cMode!=MODE_Column ){
3507 utf8_printf(p->out, "%s", p->cMode==MODE_Box?BOX_13" ":"| ");
3508 }
drh8c748632020-05-29 16:15:58 +00003509 z = azData[i];
3510 if( z==0 ) z = p->nullValue;
3511 w = p->actualWidth[j];
3512 if( p->colWidth[j]<0 ) w = -w;
3513 utf8_width_print(p->out, w, z);
3514 if( j==nColumn-1 ){
drh0908e382020-06-04 18:05:39 +00003515 utf8_printf(p->out, "%s", rowSep);
drh09a39ed2022-01-30 21:09:03 +00003516 if( bMultiLineRowExists && abRowDiv[i/nColumn-1] && i+1<nTotal ){
3517 if( p->cMode==MODE_Table ){
3518 print_row_separator(p, nColumn, "+");
3519 }else if( p->cMode==MODE_Box ){
3520 print_box_row_separator(p, nColumn, BOX_123, BOX_1234, BOX_134);
drh5aabdae2022-02-01 00:00:08 +00003521 }else if( p->cMode==MODE_Column ){
3522 raw_printf(p->out, "\n");
drh09a39ed2022-01-30 21:09:03 +00003523 }
3524 }
drh8c748632020-05-29 16:15:58 +00003525 j = -1;
drhdd853c32020-06-16 17:34:40 +00003526 if( seenInterrupt ) goto columnar_end;
drh8c748632020-05-29 16:15:58 +00003527 }else{
drh0908e382020-06-04 18:05:39 +00003528 utf8_printf(p->out, "%s", colSep);
drh8c748632020-05-29 16:15:58 +00003529 }
3530 }
3531 if( p->cMode==MODE_Table ){
3532 print_row_separator(p, nColumn, "+");
drh0908e382020-06-04 18:05:39 +00003533 }else if( p->cMode==MODE_Box ){
3534 print_box_row_separator(p, nColumn, BOX_12, BOX_124, BOX_14);
drh8c748632020-05-29 16:15:58 +00003535 }
drh99942982020-06-15 20:05:37 +00003536columnar_end:
drhdd853c32020-06-16 17:34:40 +00003537 if( seenInterrupt ){
3538 utf8_printf(p->out, "Interrupt\n");
3539 }
drhf82ce382020-08-06 16:45:22 +00003540 nData = (nRow+1)*nColumn;
larrybr6403e772022-04-20 22:41:10 +00003541 for(i=0; i<nData; i++){
3542 z = azData[i];
drh744c17c2022-05-05 10:02:19 +00003543 if( z!=zEmpty && z!=zShowNull ) free(azData[i]);
larrybr6403e772022-04-20 22:41:10 +00003544 }
drhf82ce382020-08-06 16:45:22 +00003545 sqlite3_free(azData);
drh5dce6f92022-01-31 16:29:06 +00003546 sqlite3_free((void*)azNextLine);
drh09a39ed2022-01-30 21:09:03 +00003547 sqlite3_free(abRowDiv);
drhe40f2862022-01-31 14:14:29 +00003548 if( azQuoted ){
3549 for(i=0; i<nColumn; i++) sqlite3_free(azQuoted[i]);
3550 sqlite3_free(azQuoted);
3551 }
drh30c54a02020-05-28 23:49:50 +00003552}
drh30c54a02020-05-28 23:49:50 +00003553
drh2ce15c32017-07-11 13:34:40 +00003554/*
3555** Run a prepared statement
3556*/
3557static void exec_prepared_stmt(
3558 ShellState *pArg, /* Pointer to ShellState */
drha10b9992018-03-09 15:24:33 +00003559 sqlite3_stmt *pStmt /* Statment to run */
drh2ce15c32017-07-11 13:34:40 +00003560){
3561 int rc;
drh5d88be82021-12-09 16:17:43 +00003562 sqlite3_uint64 nRow = 0;
drh2ce15c32017-07-11 13:34:40 +00003563
drh8c748632020-05-29 16:15:58 +00003564 if( pArg->cMode==MODE_Column
3565 || pArg->cMode==MODE_Table
drh0908e382020-06-04 18:05:39 +00003566 || pArg->cMode==MODE_Box
drh8c748632020-05-29 16:15:58 +00003567 || pArg->cMode==MODE_Markdown
3568 ){
3569 exec_prepared_stmt_columnar(pArg, pStmt);
3570 return;
3571 }
3572
drh2ce15c32017-07-11 13:34:40 +00003573 /* perform the first step. this will tell us if we
3574 ** have a result set or not and how wide it is.
3575 */
3576 rc = sqlite3_step(pStmt);
3577 /* if we have a result set... */
3578 if( SQLITE_ROW == rc ){
drha10b9992018-03-09 15:24:33 +00003579 /* allocate space for col name ptr, value ptr, and type */
3580 int nCol = sqlite3_column_count(pStmt);
3581 void *pData = sqlite3_malloc64(3*nCol*sizeof(const char*) + 1);
3582 if( !pData ){
drhe85e1da2021-10-01 21:01:07 +00003583 shell_out_of_memory();
drh2ce15c32017-07-11 13:34:40 +00003584 }else{
drha10b9992018-03-09 15:24:33 +00003585 char **azCols = (char **)pData; /* Names of result columns */
3586 char **azVals = &azCols[nCol]; /* Results */
3587 int *aiTypes = (int *)&azVals[nCol]; /* Result types */
3588 int i, x;
3589 assert(sizeof(int) <= sizeof(char *));
3590 /* save off ptrs to column names */
3591 for(i=0; i<nCol; i++){
3592 azCols[i] = (char *)sqlite3_column_name(pStmt, i);
3593 }
drh2ce15c32017-07-11 13:34:40 +00003594 do{
drh5d88be82021-12-09 16:17:43 +00003595 nRow++;
drha10b9992018-03-09 15:24:33 +00003596 /* extract the data and data types */
3597 for(i=0; i<nCol; i++){
3598 aiTypes[i] = x = sqlite3_column_type(pStmt, i);
drh5d1bf4f2022-01-02 20:54:33 +00003599 if( x==SQLITE_BLOB
3600 && pArg
3601 && (pArg->cMode==MODE_Insert || pArg->cMode==MODE_Quote)
3602 ){
drha10b9992018-03-09 15:24:33 +00003603 azVals[i] = "";
3604 }else{
3605 azVals[i] = (char*)sqlite3_column_text(pStmt, i);
3606 }
3607 if( !azVals[i] && (aiTypes[i]!=SQLITE_NULL) ){
3608 rc = SQLITE_NOMEM;
3609 break; /* from for */
3610 }
3611 } /* end for */
3612
3613 /* if data and types extracted successfully... */
3614 if( SQLITE_ROW == rc ){
3615 /* call the supplied callback with the result row data */
3616 if( shell_callback(pArg, nCol, azVals, azCols, aiTypes) ){
3617 rc = SQLITE_ABORT;
3618 }else{
3619 rc = sqlite3_step(pStmt);
3620 }
3621 }
3622 } while( SQLITE_ROW == rc );
3623 sqlite3_free(pData);
drh0908e382020-06-04 18:05:39 +00003624 if( pArg->cMode==MODE_Json ){
drh30c54a02020-05-28 23:49:50 +00003625 fputs("]\n", pArg->out);
drh5d88be82021-12-09 16:17:43 +00003626 }else if( pArg->cMode==MODE_Count ){
mistachkinc158c072021-12-31 19:08:20 +00003627 char zBuf[200];
3628 sqlite3_snprintf(sizeof(zBuf), zBuf, "%llu row%s\n",
3629 nRow, nRow!=1 ? "s" : "");
3630 printf("%s", zBuf);
drh30c54a02020-05-28 23:49:50 +00003631 }
drh2ce15c32017-07-11 13:34:40 +00003632 }
3633 }
3634}
3635
dan6b046be2018-01-09 15:25:55 +00003636#ifndef SQLITE_OMIT_VIRTUALTABLE
drh2ce15c32017-07-11 13:34:40 +00003637/*
dan43efc182017-12-19 17:42:13 +00003638** This function is called to process SQL if the previous shell command
3639** was ".expert". It passes the SQL in the second argument directly to
3640** the sqlite3expert object.
3641**
3642** If successful, SQLITE_OK is returned. Otherwise, an SQLite error
3643** code. In this case, (*pzErr) may be set to point to a buffer containing
3644** an English language error message. It is the responsibility of the
3645** caller to eventually free this buffer using sqlite3_free().
3646*/
3647static int expertHandleSQL(
3648 ShellState *pState,
3649 const char *zSql,
3650 char **pzErr
3651){
3652 assert( pState->expert.pExpert );
3653 assert( pzErr==0 || *pzErr==0 );
3654 return sqlite3_expert_sql(pState->expert.pExpert, zSql, pzErr);
3655}
3656
3657/*
3658** This function is called either to silently clean up the object
3659** created by the ".expert" command (if bCancel==1), or to generate a
3660** report from it and then clean it up (if bCancel==0).
3661**
3662** If successful, SQLITE_OK is returned. Otherwise, an SQLite error
3663** code. In this case, (*pzErr) may be set to point to a buffer containing
3664** an English language error message. It is the responsibility of the
3665** caller to eventually free this buffer using sqlite3_free().
3666*/
3667static int expertFinish(
3668 ShellState *pState,
3669 int bCancel,
3670 char **pzErr
3671){
3672 int rc = SQLITE_OK;
3673 sqlite3expert *p = pState->expert.pExpert;
3674 assert( p );
3675 assert( bCancel || pzErr==0 || *pzErr==0 );
3676 if( bCancel==0 ){
3677 FILE *out = pState->out;
3678 int bVerbose = pState->expert.bVerbose;
3679
3680 rc = sqlite3_expert_analyze(p, pzErr);
3681 if( rc==SQLITE_OK ){
3682 int nQuery = sqlite3_expert_count(p);
3683 int i;
3684
3685 if( bVerbose ){
3686 const char *zCand = sqlite3_expert_report(p,0,EXPERT_REPORT_CANDIDATES);
3687 raw_printf(out, "-- Candidates -----------------------------\n");
3688 raw_printf(out, "%s\n", zCand);
3689 }
3690 for(i=0; i<nQuery; i++){
3691 const char *zSql = sqlite3_expert_report(p, i, EXPERT_REPORT_SQL);
3692 const char *zIdx = sqlite3_expert_report(p, i, EXPERT_REPORT_INDEXES);
3693 const char *zEQP = sqlite3_expert_report(p, i, EXPERT_REPORT_PLAN);
3694 if( zIdx==0 ) zIdx = "(no new indexes)\n";
3695 if( bVerbose ){
3696 raw_printf(out, "-- Query %d --------------------------------\n",i+1);
3697 raw_printf(out, "%s\n\n", zSql);
3698 }
3699 raw_printf(out, "%s\n", zIdx);
3700 raw_printf(out, "%s\n", zEQP);
3701 }
3702 }
3703 }
3704 sqlite3_expert_destroy(p);
3705 pState->expert.pExpert = 0;
3706 return rc;
3707}
3708
dan6b046be2018-01-09 15:25:55 +00003709/*
3710** Implementation of ".expert" dot command.
3711*/
3712static int expertDotCommand(
3713 ShellState *pState, /* Current shell tool state */
3714 char **azArg, /* Array of arguments passed to dot command */
3715 int nArg /* Number of entries in azArg[] */
3716){
3717 int rc = SQLITE_OK;
3718 char *zErr = 0;
3719 int i;
3720 int iSample = 0;
3721
3722 assert( pState->expert.pExpert==0 );
3723 memset(&pState->expert, 0, sizeof(ExpertInfo));
3724
3725 for(i=1; rc==SQLITE_OK && i<nArg; i++){
3726 char *z = azArg[i];
3727 int n;
3728 if( z[0]=='-' && z[1]=='-' ) z++;
3729 n = strlen30(z);
3730 if( n>=2 && 0==strncmp(z, "-verbose", n) ){
3731 pState->expert.bVerbose = 1;
3732 }
3733 else if( n>=2 && 0==strncmp(z, "-sample", n) ){
3734 if( i==(nArg-1) ){
3735 raw_printf(stderr, "option requires an argument: %s\n", z);
3736 rc = SQLITE_ERROR;
3737 }else{
3738 iSample = (int)integerValue(azArg[++i]);
3739 if( iSample<0 || iSample>100 ){
3740 raw_printf(stderr, "value out of range: %s\n", azArg[i]);
3741 rc = SQLITE_ERROR;
3742 }
3743 }
3744 }
3745 else{
3746 raw_printf(stderr, "unknown option: %s\n", z);
3747 rc = SQLITE_ERROR;
3748 }
3749 }
3750
3751 if( rc==SQLITE_OK ){
3752 pState->expert.pExpert = sqlite3_expert_new(pState->db, &zErr);
3753 if( pState->expert.pExpert==0 ){
drhe0adf602021-12-16 14:26:16 +00003754 raw_printf(stderr, "sqlite3_expert_new: %s\n", zErr ? zErr : "out of memory");
dan6b046be2018-01-09 15:25:55 +00003755 rc = SQLITE_ERROR;
3756 }else{
3757 sqlite3_expert_config(
3758 pState->expert.pExpert, EXPERT_CONFIG_SAMPLE, iSample
3759 );
3760 }
3761 }
drhe0adf602021-12-16 14:26:16 +00003762 sqlite3_free(zErr);
dan6b046be2018-01-09 15:25:55 +00003763
3764 return rc;
3765}
3766#endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */
dan43efc182017-12-19 17:42:13 +00003767
3768/*
drh2ce15c32017-07-11 13:34:40 +00003769** Execute a statement or set of statements. Print
3770** any result rows/columns depending on the current mode
3771** set via the supplied callback.
3772**
3773** This is very similar to SQLite's built-in sqlite3_exec()
3774** function except it takes a slightly different callback
3775** and callback data argument.
3776*/
3777static int shell_exec(
drh2ce15c32017-07-11 13:34:40 +00003778 ShellState *pArg, /* Pointer to ShellState */
drha10b9992018-03-09 15:24:33 +00003779 const char *zSql, /* SQL to be evaluated */
drh2ce15c32017-07-11 13:34:40 +00003780 char **pzErrMsg /* Error msg written here */
3781){
3782 sqlite3_stmt *pStmt = NULL; /* Statement to execute. */
3783 int rc = SQLITE_OK; /* Return Code */
3784 int rc2;
3785 const char *zLeftover; /* Tail of unprocessed SQL */
drha10b9992018-03-09 15:24:33 +00003786 sqlite3 *db = pArg->db;
drh2ce15c32017-07-11 13:34:40 +00003787
3788 if( pzErrMsg ){
3789 *pzErrMsg = NULL;
3790 }
3791
dan6b046be2018-01-09 15:25:55 +00003792#ifndef SQLITE_OMIT_VIRTUALTABLE
dan43efc182017-12-19 17:42:13 +00003793 if( pArg->expert.pExpert ){
3794 rc = expertHandleSQL(pArg, zSql, pzErrMsg);
3795 return expertFinish(pArg, (rc!=SQLITE_OK), pzErrMsg);
3796 }
dan6b046be2018-01-09 15:25:55 +00003797#endif
dan43efc182017-12-19 17:42:13 +00003798
drh2ce15c32017-07-11 13:34:40 +00003799 while( zSql[0] && (SQLITE_OK == rc) ){
3800 static const char *zStmtSql;
3801 rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zLeftover);
3802 if( SQLITE_OK != rc ){
3803 if( pzErrMsg ){
drh633c7982022-02-08 12:13:16 +00003804 *pzErrMsg = save_err_msg(db, "in prepare", rc, zSql);
drh2ce15c32017-07-11 13:34:40 +00003805 }
3806 }else{
3807 if( !pStmt ){
3808 /* this happens for a comment or white-space */
3809 zSql = zLeftover;
3810 while( IsSpace(zSql[0]) ) zSql++;
3811 continue;
3812 }
3813 zStmtSql = sqlite3_sql(pStmt);
3814 if( zStmtSql==0 ) zStmtSql = "";
3815 while( IsSpace(zStmtSql[0]) ) zStmtSql++;
3816
3817 /* save off the prepared statment handle and reset row count */
3818 if( pArg ){
3819 pArg->pStmt = pStmt;
3820 pArg->cnt = 0;
3821 }
3822
drh2ce15c32017-07-11 13:34:40 +00003823 /* Show the EXPLAIN QUERY PLAN if .eqp is on */
drh39c5c4a2019-03-06 14:53:27 +00003824 if( pArg && pArg->autoEQP && sqlite3_stmt_isexplain(pStmt)==0 ){
drh2ce15c32017-07-11 13:34:40 +00003825 sqlite3_stmt *pExplain;
3826 char *zEQP;
drhada70452017-12-21 21:02:27 +00003827 int triggerEQP = 0;
drh2ce15c32017-07-11 13:34:40 +00003828 disable_debug_trace_modes();
drhada70452017-12-21 21:02:27 +00003829 sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, -1, &triggerEQP);
3830 if( pArg->autoEQP>=AUTOEQP_trigger ){
3831 sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, 1, 0);
3832 }
drh2ce15c32017-07-11 13:34:40 +00003833 zEQP = sqlite3_mprintf("EXPLAIN QUERY PLAN %s", zStmtSql);
drhe3e25652021-12-16 13:29:28 +00003834 shell_check_oom(zEQP);
drh2ce15c32017-07-11 13:34:40 +00003835 rc = sqlite3_prepare_v2(db, zEQP, -1, &pExplain, 0);
3836 if( rc==SQLITE_OK ){
3837 while( sqlite3_step(pExplain)==SQLITE_ROW ){
drh4b5345c2018-04-24 13:07:40 +00003838 const char *zEQPLine = (const char*)sqlite3_column_text(pExplain,3);
drhe2ca99c2018-05-02 00:33:43 +00003839 int iEqpId = sqlite3_column_int(pExplain, 0);
3840 int iParentId = sqlite3_column_int(pExplain, 1);
drh7e088a62020-05-02 00:01:39 +00003841 if( zEQPLine==0 ) zEQPLine = "";
drh4b5345c2018-04-24 13:07:40 +00003842 if( zEQPLine[0]=='-' ) eqp_render(pArg);
drhe2ca99c2018-05-02 00:33:43 +00003843 eqp_append(pArg, iEqpId, iParentId, zEQPLine);
drh2ce15c32017-07-11 13:34:40 +00003844 }
drh4b5345c2018-04-24 13:07:40 +00003845 eqp_render(pArg);
drh2ce15c32017-07-11 13:34:40 +00003846 }
3847 sqlite3_finalize(pExplain);
3848 sqlite3_free(zEQP);
drhada70452017-12-21 21:02:27 +00003849 if( pArg->autoEQP>=AUTOEQP_full ){
drh2ce15c32017-07-11 13:34:40 +00003850 /* Also do an EXPLAIN for ".eqp full" mode */
3851 zEQP = sqlite3_mprintf("EXPLAIN %s", zStmtSql);
drhe3e25652021-12-16 13:29:28 +00003852 shell_check_oom(zEQP);
drh2ce15c32017-07-11 13:34:40 +00003853 rc = sqlite3_prepare_v2(db, zEQP, -1, &pExplain, 0);
3854 if( rc==SQLITE_OK ){
3855 pArg->cMode = MODE_Explain;
3856 explain_data_prepare(pArg, pExplain);
drha10b9992018-03-09 15:24:33 +00003857 exec_prepared_stmt(pArg, pExplain);
drh2ce15c32017-07-11 13:34:40 +00003858 explain_data_delete(pArg);
3859 }
3860 sqlite3_finalize(pExplain);
3861 sqlite3_free(zEQP);
3862 }
drh51efe092018-03-20 12:04:38 +00003863 if( pArg->autoEQP>=AUTOEQP_trigger && triggerEQP==0 ){
3864 sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, 0, 0);
3865 /* Reprepare pStmt before reactiving trace modes */
3866 sqlite3_finalize(pStmt);
3867 sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
drh3c49eaf2018-06-07 15:23:43 +00003868 if( pArg ) pArg->pStmt = pStmt;
drh51efe092018-03-20 12:04:38 +00003869 }
drh2ce15c32017-07-11 13:34:40 +00003870 restore_debug_trace_modes();
3871 }
3872
3873 if( pArg ){
3874 pArg->cMode = pArg->mode;
drh4b5345c2018-04-24 13:07:40 +00003875 if( pArg->autoExplain ){
drh39c5c4a2019-03-06 14:53:27 +00003876 if( sqlite3_stmt_isexplain(pStmt)==1 ){
drh4b5345c2018-04-24 13:07:40 +00003877 pArg->cMode = MODE_Explain;
3878 }
drh39c5c4a2019-03-06 14:53:27 +00003879 if( sqlite3_stmt_isexplain(pStmt)==2 ){
drh4b5345c2018-04-24 13:07:40 +00003880 pArg->cMode = MODE_EQP;
3881 }
drh2ce15c32017-07-11 13:34:40 +00003882 }
3883
3884 /* If the shell is currently in ".explain" mode, gather the extra
3885 ** data required to add indents to the output.*/
3886 if( pArg->cMode==MODE_Explain ){
3887 explain_data_prepare(pArg, pStmt);
3888 }
3889 }
3890
drh8b738d02019-02-25 18:43:54 +00003891 bind_prepared_stmt(pArg, pStmt);
drha10b9992018-03-09 15:24:33 +00003892 exec_prepared_stmt(pArg, pStmt);
drh2ce15c32017-07-11 13:34:40 +00003893 explain_data_delete(pArg);
drh4b5345c2018-04-24 13:07:40 +00003894 eqp_render(pArg);
drh2ce15c32017-07-11 13:34:40 +00003895
3896 /* print usage stats if stats on */
3897 if( pArg && pArg->statsOn ){
3898 display_stats(db, pArg, 0);
3899 }
3900
3901 /* print loop-counters if required */
3902 if( pArg && pArg->scanstatsOn ){
3903 display_scanstats(db, pArg);
3904 }
3905
3906 /* Finalize the statement just executed. If this fails, save a
3907 ** copy of the error message. Otherwise, set zSql to point to the
3908 ** next statement to execute. */
3909 rc2 = sqlite3_finalize(pStmt);
3910 if( rc!=SQLITE_NOMEM ) rc = rc2;
3911 if( rc==SQLITE_OK ){
3912 zSql = zLeftover;
3913 while( IsSpace(zSql[0]) ) zSql++;
3914 }else if( pzErrMsg ){
drh633c7982022-02-08 12:13:16 +00003915 *pzErrMsg = save_err_msg(db, "stepping", rc, 0);
drh2ce15c32017-07-11 13:34:40 +00003916 }
3917
3918 /* clear saved stmt handle */
3919 if( pArg ){
3920 pArg->pStmt = NULL;
3921 }
3922 }
3923 } /* end while */
3924
3925 return rc;
3926}
3927
3928/*
3929** Release memory previously allocated by tableColumnList().
3930*/
3931static void freeColumnList(char **azCol){
3932 int i;
3933 for(i=1; azCol[i]; i++){
3934 sqlite3_free(azCol[i]);
3935 }
3936 /* azCol[0] is a static string */
3937 sqlite3_free(azCol);
3938}
3939
3940/*
3941** Return a list of pointers to strings which are the names of all
3942** columns in table zTab. The memory to hold the names is dynamically
3943** allocated and must be released by the caller using a subsequent call
3944** to freeColumnList().
3945**
3946** The azCol[0] entry is usually NULL. However, if zTab contains a rowid
3947** value that needs to be preserved, then azCol[0] is filled in with the
3948** name of the rowid column.
3949**
3950** The first regular column in the table is azCol[1]. The list is terminated
3951** by an entry with azCol[i]==0.
3952*/
3953static char **tableColumnList(ShellState *p, const char *zTab){
3954 char **azCol = 0;
3955 sqlite3_stmt *pStmt;
3956 char *zSql;
3957 int nCol = 0;
3958 int nAlloc = 0;
3959 int nPK = 0; /* Number of PRIMARY KEY columns seen */
3960 int isIPK = 0; /* True if one PRIMARY KEY column of type INTEGER */
3961 int preserveRowid = ShellHasFlag(p, SHFLG_PreserveRowid);
3962 int rc;
3963
3964 zSql = sqlite3_mprintf("PRAGMA table_info=%Q", zTab);
drhe3e25652021-12-16 13:29:28 +00003965 shell_check_oom(zSql);
drh2ce15c32017-07-11 13:34:40 +00003966 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
3967 sqlite3_free(zSql);
3968 if( rc ) return 0;
3969 while( sqlite3_step(pStmt)==SQLITE_ROW ){
3970 if( nCol>=nAlloc-2 ){
3971 nAlloc = nAlloc*2 + nCol + 10;
3972 azCol = sqlite3_realloc(azCol, nAlloc*sizeof(azCol[0]));
drhe3e25652021-12-16 13:29:28 +00003973 shell_check_oom(azCol);
drh2ce15c32017-07-11 13:34:40 +00003974 }
3975 azCol[++nCol] = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 1));
drhe3e25652021-12-16 13:29:28 +00003976 shell_check_oom(azCol[nCol]);
drh2ce15c32017-07-11 13:34:40 +00003977 if( sqlite3_column_int(pStmt, 5) ){
3978 nPK++;
3979 if( nPK==1
3980 && sqlite3_stricmp((const char*)sqlite3_column_text(pStmt,2),
3981 "INTEGER")==0
3982 ){
3983 isIPK = 1;
3984 }else{
3985 isIPK = 0;
3986 }
3987 }
3988 }
3989 sqlite3_finalize(pStmt);
drh4c6cddc2017-10-12 10:28:30 +00003990 if( azCol==0 ) return 0;
drh2ce15c32017-07-11 13:34:40 +00003991 azCol[0] = 0;
3992 azCol[nCol+1] = 0;
3993
3994 /* The decision of whether or not a rowid really needs to be preserved
3995 ** is tricky. We never need to preserve a rowid for a WITHOUT ROWID table
3996 ** or a table with an INTEGER PRIMARY KEY. We are unable to preserve
3997 ** rowids on tables where the rowid is inaccessible because there are other
3998 ** columns in the table named "rowid", "_rowid_", and "oid".
3999 */
4000 if( preserveRowid && isIPK ){
4001 /* If a single PRIMARY KEY column with type INTEGER was seen, then it
4002 ** might be an alise for the ROWID. But it might also be a WITHOUT ROWID
4003 ** table or a INTEGER PRIMARY KEY DESC column, neither of which are
4004 ** ROWID aliases. To distinguish these cases, check to see if
4005 ** there is a "pk" entry in "PRAGMA index_list". There will be
4006 ** no "pk" index if the PRIMARY KEY really is an alias for the ROWID.
4007 */
4008 zSql = sqlite3_mprintf("SELECT 1 FROM pragma_index_list(%Q)"
4009 " WHERE origin='pk'", zTab);
drhe3e25652021-12-16 13:29:28 +00004010 shell_check_oom(zSql);
drh2ce15c32017-07-11 13:34:40 +00004011 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
4012 sqlite3_free(zSql);
4013 if( rc ){
4014 freeColumnList(azCol);
4015 return 0;
4016 }
4017 rc = sqlite3_step(pStmt);
4018 sqlite3_finalize(pStmt);
4019 preserveRowid = rc==SQLITE_ROW;
4020 }
4021 if( preserveRowid ){
4022 /* Only preserve the rowid if we can find a name to use for the
4023 ** rowid */
4024 static char *azRowid[] = { "rowid", "_rowid_", "oid" };
4025 int i, j;
4026 for(j=0; j<3; j++){
4027 for(i=1; i<=nCol; i++){
4028 if( sqlite3_stricmp(azRowid[j],azCol[i])==0 ) break;
4029 }
4030 if( i>nCol ){
4031 /* At this point, we know that azRowid[j] is not the name of any
4032 ** ordinary column in the table. Verify that azRowid[j] is a valid
4033 ** name for the rowid before adding it to azCol[0]. WITHOUT ROWID
4034 ** tables will fail this last check */
4035 rc = sqlite3_table_column_metadata(p->db,0,zTab,azRowid[j],0,0,0,0,0);
4036 if( rc==SQLITE_OK ) azCol[0] = azRowid[j];
4037 break;
4038 }
4039 }
4040 }
4041 return azCol;
4042}
4043
4044/*
4045** Toggle the reverse_unordered_selects setting.
4046*/
4047static void toggleSelectOrder(sqlite3 *db){
4048 sqlite3_stmt *pStmt = 0;
4049 int iSetting = 0;
4050 char zStmt[100];
4051 sqlite3_prepare_v2(db, "PRAGMA reverse_unordered_selects", -1, &pStmt, 0);
4052 if( sqlite3_step(pStmt)==SQLITE_ROW ){
4053 iSetting = sqlite3_column_int(pStmt, 0);
4054 }
4055 sqlite3_finalize(pStmt);
4056 sqlite3_snprintf(sizeof(zStmt), zStmt,
4057 "PRAGMA reverse_unordered_selects(%d)", !iSetting);
4058 sqlite3_exec(db, zStmt, 0, 0, 0);
4059}
4060
4061/*
4062** This is a different callback routine used for dumping the database.
4063** Each row received by this callback consists of a table name,
4064** the table type ("index" or "table") and SQL to create the table.
4065** This routine should print text sufficient to recreate the table.
4066*/
4067static int dump_callback(void *pArg, int nArg, char **azArg, char **azNotUsed){
4068 int rc;
4069 const char *zTable;
4070 const char *zType;
4071 const char *zSql;
4072 ShellState *p = (ShellState *)pArg;
mistachkina00a0162020-10-18 18:35:34 +00004073 int dataOnly;
4074 int noSys;
drh2ce15c32017-07-11 13:34:40 +00004075
4076 UNUSED_PARAMETER(azNotUsed);
drhb3c45232017-08-28 14:33:27 +00004077 if( nArg!=3 || azArg==0 ) return 0;
drh2ce15c32017-07-11 13:34:40 +00004078 zTable = azArg[0];
4079 zType = azArg[1];
4080 zSql = azArg[2];
mistachkina00a0162020-10-18 18:35:34 +00004081 dataOnly = (p->shellFlgs & SHFLG_DumpDataOnly)!=0;
4082 noSys = (p->shellFlgs & SHFLG_DumpNoSys)!=0;
drh2ce15c32017-07-11 13:34:40 +00004083
drhc1962192020-10-12 16:54:28 +00004084 if( strcmp(zTable, "sqlite_sequence")==0 && !noSys ){
4085 if( !dataOnly ) raw_printf(p->out, "DELETE FROM sqlite_sequence;\n");
4086 }else if( sqlite3_strglob("sqlite_stat?", zTable)==0 && !noSys ){
4087 if( !dataOnly ) raw_printf(p->out, "ANALYZE sqlite_schema;\n");
drh2ce15c32017-07-11 13:34:40 +00004088 }else if( strncmp(zTable, "sqlite_", 7)==0 ){
4089 return 0;
drhc1962192020-10-12 16:54:28 +00004090 }else if( dataOnly ){
4091 /* no-op */
drh2ce15c32017-07-11 13:34:40 +00004092 }else if( strncmp(zSql, "CREATE VIRTUAL TABLE", 20)==0 ){
4093 char *zIns;
4094 if( !p->writableSchema ){
4095 raw_printf(p->out, "PRAGMA writable_schema=ON;\n");
4096 p->writableSchema = 1;
4097 }
4098 zIns = sqlite3_mprintf(
drh067b92b2020-06-19 15:24:12 +00004099 "INSERT INTO sqlite_schema(type,name,tbl_name,rootpage,sql)"
drh2ce15c32017-07-11 13:34:40 +00004100 "VALUES('table','%q','%q',0,'%q');",
4101 zTable, zTable, zSql);
drhe3e25652021-12-16 13:29:28 +00004102 shell_check_oom(zIns);
drh2ce15c32017-07-11 13:34:40 +00004103 utf8_printf(p->out, "%s\n", zIns);
4104 sqlite3_free(zIns);
4105 return 0;
4106 }else{
4107 printSchemaLine(p->out, zSql, ";\n");
4108 }
4109
4110 if( strcmp(zType, "table")==0 ){
4111 ShellText sSelect;
4112 ShellText sTable;
4113 char **azCol;
4114 int i;
4115 char *savedDestTable;
4116 int savedMode;
4117
4118 azCol = tableColumnList(p, zTable);
4119 if( azCol==0 ){
4120 p->nErr++;
4121 return 0;
4122 }
4123
4124 /* Always quote the table name, even if it appears to be pure ascii,
4125 ** in case it is a keyword. Ex: INSERT INTO "table" ... */
4126 initText(&sTable);
4127 appendText(&sTable, zTable, quoteChar(zTable));
4128 /* If preserving the rowid, add a column list after the table name.
4129 ** In other words: "INSERT INTO tab(rowid,a,b,c,...) VALUES(...)"
4130 ** instead of the usual "INSERT INTO tab VALUES(...)".
4131 */
4132 if( azCol[0] ){
4133 appendText(&sTable, "(", 0);
4134 appendText(&sTable, azCol[0], 0);
4135 for(i=1; azCol[i]; i++){
4136 appendText(&sTable, ",", 0);
4137 appendText(&sTable, azCol[i], quoteChar(azCol[i]));
4138 }
4139 appendText(&sTable, ")", 0);
4140 }
4141
4142 /* Build an appropriate SELECT statement */
4143 initText(&sSelect);
4144 appendText(&sSelect, "SELECT ", 0);
4145 if( azCol[0] ){
4146 appendText(&sSelect, azCol[0], 0);
4147 appendText(&sSelect, ",", 0);
4148 }
4149 for(i=1; azCol[i]; i++){
4150 appendText(&sSelect, azCol[i], quoteChar(azCol[i]));
4151 if( azCol[i+1] ){
4152 appendText(&sSelect, ",", 0);
4153 }
4154 }
4155 freeColumnList(azCol);
4156 appendText(&sSelect, " FROM ", 0);
4157 appendText(&sSelect, zTable, quoteChar(zTable));
4158
4159 savedDestTable = p->zDestTable;
4160 savedMode = p->mode;
4161 p->zDestTable = sTable.z;
4162 p->mode = p->cMode = MODE_Insert;
drha10b9992018-03-09 15:24:33 +00004163 rc = shell_exec(p, sSelect.z, 0);
drh2ce15c32017-07-11 13:34:40 +00004164 if( (rc&0xff)==SQLITE_CORRUPT ){
4165 raw_printf(p->out, "/****** CORRUPTION ERROR *******/\n");
4166 toggleSelectOrder(p->db);
drha10b9992018-03-09 15:24:33 +00004167 shell_exec(p, sSelect.z, 0);
drh2ce15c32017-07-11 13:34:40 +00004168 toggleSelectOrder(p->db);
4169 }
4170 p->zDestTable = savedDestTable;
4171 p->mode = savedMode;
4172 freeText(&sTable);
4173 freeText(&sSelect);
4174 if( rc ) p->nErr++;
4175 }
4176 return 0;
4177}
4178
4179/*
4180** Run zQuery. Use dump_callback() as the callback routine so that
4181** the contents of the query are output as SQL statements.
4182**
4183** If we get a SQLITE_CORRUPT error, rerun the query after appending
4184** "ORDER BY rowid DESC" to the end.
4185*/
4186static int run_schema_dump_query(
4187 ShellState *p,
4188 const char *zQuery
4189){
4190 int rc;
4191 char *zErr = 0;
4192 rc = sqlite3_exec(p->db, zQuery, dump_callback, p, &zErr);
4193 if( rc==SQLITE_CORRUPT ){
4194 char *zQ2;
4195 int len = strlen30(zQuery);
4196 raw_printf(p->out, "/****** CORRUPTION ERROR *******/\n");
4197 if( zErr ){
4198 utf8_printf(p->out, "/****** %s ******/\n", zErr);
4199 sqlite3_free(zErr);
4200 zErr = 0;
4201 }
4202 zQ2 = malloc( len+100 );
4203 if( zQ2==0 ) return rc;
4204 sqlite3_snprintf(len+100, zQ2, "%s ORDER BY rowid DESC", zQuery);
4205 rc = sqlite3_exec(p->db, zQ2, dump_callback, p, &zErr);
4206 if( rc ){
4207 utf8_printf(p->out, "/****** ERROR: %s ******/\n", zErr);
4208 }else{
4209 rc = SQLITE_CORRUPT;
4210 }
4211 sqlite3_free(zErr);
4212 free(zQ2);
4213 }
4214 return rc;
4215}
4216
4217/*
drh98aa2ab2018-09-26 16:53:51 +00004218** Text of help messages.
4219**
4220** The help text for each individual command begins with a line that starts
4221** with ".". Subsequent lines are supplimental information.
4222**
4223** There must be two or more spaces between the end of the command and the
4224** start of the description of what that command does.
drh2ce15c32017-07-11 13:34:40 +00004225*/
drh98aa2ab2018-09-26 16:53:51 +00004226static const char *(azHelp[]) = {
drhe37c0e12018-01-06 19:19:50 +00004227#if defined(SQLITE_HAVE_ZLIB) && !defined(SQLITE_OMIT_VIRTUALTABLE)
drh98aa2ab2018-09-26 16:53:51 +00004228 ".archive ... Manage SQL archives",
4229 " Each command must have exactly one of the following options:",
4230 " -c, --create Create a new archive",
drhe2754c12019-08-26 12:50:01 +00004231 " -u, --update Add or update files with changed mtime",
4232 " -i, --insert Like -u but always add even if unchanged",
larrybr47061b92021-11-01 17:22:52 +00004233 " -r, --remove Remove files from archive",
drh98aa2ab2018-09-26 16:53:51 +00004234 " -t, --list List contents of archive",
4235 " -x, --extract Extract files from archive",
4236 " Optional arguments:",
4237 " -v, --verbose Print each filename as it is processed",
drhe2754c12019-08-26 12:50:01 +00004238 " -f FILE, --file FILE Use archive FILE (default is current db)",
4239 " -a FILE, --append FILE Open FILE using the apndvfs VFS",
4240 " -C DIR, --directory DIR Read/extract files from directory DIR",
larrybr8f09f4b2021-11-02 00:18:11 +00004241 " -g, --glob Use glob matching for names in archive",
drh98aa2ab2018-09-26 16:53:51 +00004242 " -n, --dryrun Show the SQL that would have occurred",
4243 " Examples:",
drhe2754c12019-08-26 12:50:01 +00004244 " .ar -cf ARCHIVE foo bar # Create ARCHIVE from files foo and bar",
4245 " .ar -tf ARCHIVE # List members of ARCHIVE",
4246 " .ar -xvf ARCHIVE # Verbosely extract files from ARCHIVE",
drh98aa2ab2018-09-26 16:53:51 +00004247 " See also:",
larrybrbd0d62c2021-06-13 08:23:28 +00004248 " http://sqlite.org/cli.html#sqlite_archive_support",
drhe37c0e12018-01-06 19:19:50 +00004249#endif
drh2ce15c32017-07-11 13:34:40 +00004250#ifndef SQLITE_OMIT_AUTHORIZATION
drh98aa2ab2018-09-26 16:53:51 +00004251 ".auth ON|OFF Show authorizer callbacks",
drh2ce15c32017-07-11 13:34:40 +00004252#endif
drh98aa2ab2018-09-26 16:53:51 +00004253 ".backup ?DB? FILE Backup DB (default \"main\") to FILE",
larrybra7919ad2022-02-19 21:25:48 +00004254 " Options:",
drh98aa2ab2018-09-26 16:53:51 +00004255 " --append Use the appendvfs",
drhe2754c12019-08-26 12:50:01 +00004256 " --async Write to FILE without journal and fsync()",
drh98aa2ab2018-09-26 16:53:51 +00004257 ".bail on|off Stop after hitting an error. Default OFF",
4258 ".binary on|off Turn binary output on or off. Default OFF",
4259 ".cd DIRECTORY Change the working directory to DIRECTORY",
4260 ".changes on|off Show number of rows changed by SQL",
4261 ".check GLOB Fail if output since .testcase does not match",
4262 ".clone NEWDB Clone data into NEWDB from the existing database",
drh37407122021-07-23 18:43:58 +00004263 ".connection [close] [#] Open or close an auxiliary database connection",
drh98aa2ab2018-09-26 16:53:51 +00004264 ".databases List names and files of attached databases",
4265 ".dbconfig ?op? ?val? List or change sqlite3_db_config() options",
4266 ".dbinfo ?DB? Show status information about the database",
larrybr7bdbe592021-03-15 12:56:00 +00004267 ".dump ?OBJECTS? Render database content as SQL",
drheb7f2a02018-09-26 18:02:32 +00004268 " Options:",
drhc1962192020-10-12 16:54:28 +00004269 " --data-only Output only INSERT statements",
drheb7f2a02018-09-26 18:02:32 +00004270 " --newlines Allow unescaped newline characters in output",
drhc1962192020-10-12 16:54:28 +00004271 " --nosys Omit system tables (ex: \"sqlite_stat1\")",
4272 " --preserve-rowids Include ROWID values in the output",
larrybr7bdbe592021-03-15 12:56:00 +00004273 " OBJECTS is a LIKE pattern for tables, indexes, triggers or views to dump",
drh8e9297f2020-03-25 12:50:13 +00004274 " Additional LIKE patterns can be given in subsequent arguments",
drh98aa2ab2018-09-26 16:53:51 +00004275 ".echo on|off Turn command echo on or off",
drhb4e50392019-01-26 15:40:04 +00004276 ".eqp on|off|full|... Enable or disable automatic EXPLAIN QUERY PLAN",
4277 " Other Modes:",
4278#ifdef SQLITE_DEBUG
4279 " test Show raw EXPLAIN QUERY PLAN output",
drhe2754c12019-08-26 12:50:01 +00004280 " trace Like \"full\" but enable \"PRAGMA vdbe_trace\"",
drhb4e50392019-01-26 15:40:04 +00004281#endif
4282 " trigger Like \"full\" but also show trigger bytecode",
drhe2754c12019-08-26 12:50:01 +00004283 ".excel Display the output of next command in spreadsheet",
drh7a431002020-04-18 14:12:00 +00004284 " --bom Put a UTF8 byte-order mark on intermediate file",
drheb7f2a02018-09-26 18:02:32 +00004285 ".exit ?CODE? Exit this program with return-code CODE",
drhe2754c12019-08-26 12:50:01 +00004286 ".expert EXPERIMENTAL. Suggest indexes for queries",
drh978256f2019-11-02 00:00:14 +00004287 ".explain ?on|off|auto? Change the EXPLAIN formatting mode. Default: auto",
drhd985f722019-06-05 14:29:53 +00004288 ".filectrl CMD ... Run various sqlite3_file_control() operations",
drh541ef2c2020-04-20 16:21:30 +00004289 " --schema SCHEMA Use SCHEMA instead of \"main\"",
4290 " --help Show CMD details",
drh98aa2ab2018-09-26 16:53:51 +00004291 ".fullschema ?--indent? Show schema and the content of sqlite_stat tables",
4292 ".headers on|off Turn display of headers on or off",
4293 ".help ?-all? ?PATTERN? Show help text for PATTERN",
4294 ".import FILE TABLE Import data from FILE into TABLE",
drhccb37812020-03-09 15:39:39 +00004295 " Options:",
4296 " --ascii Use \\037 and \\036 as column and row separators",
4297 " --csv Use , and \\n as column and row separators",
4298 " --skip N Skip the first N rows of input",
larrybr738d7b92022-01-13 21:22:54 +00004299 " --schema S Target table to be S.TABLE",
drhccb37812020-03-09 15:39:39 +00004300 " -v \"Verbose\" - increase auxiliary output",
4301 " Notes:",
4302 " * If TABLE does not exist, it is created. The first row of input",
4303 " determines the column names.",
4304 " * If neither --csv or --ascii are used, the input mode is derived",
4305 " from the \".mode\" output mode",
4306 " * If FILE begins with \"|\" then it is a command that generates the",
4307 " input text.",
drh2ce15c32017-07-11 13:34:40 +00004308#ifndef SQLITE_OMIT_TEST_CONTROL
drh98aa2ab2018-09-26 16:53:51 +00004309 ".imposter INDEX TABLE Create imposter table TABLE on index INDEX",
drh2ce15c32017-07-11 13:34:40 +00004310#endif
drh98aa2ab2018-09-26 16:53:51 +00004311 ".indexes ?TABLE? Show names of indexes",
4312 " If TABLE is specified, only show indexes for",
4313 " tables matching TABLE using the LIKE operator.",
drh2ce15c32017-07-11 13:34:40 +00004314#ifdef SQLITE_ENABLE_IOTRACE
drh98aa2ab2018-09-26 16:53:51 +00004315 ".iotrace FILE Enable I/O diagnostic logging to FILE",
drh2ce15c32017-07-11 13:34:40 +00004316#endif
drh98aa2ab2018-09-26 16:53:51 +00004317 ".limit ?LIMIT? ?VAL? Display or change the value of an SQLITE_LIMIT",
4318 ".lint OPTIONS Report potential schema issues.",
4319 " Options:",
4320 " fkey-indexes Find missing foreign key indexes",
drh2ce15c32017-07-11 13:34:40 +00004321#ifndef SQLITE_OMIT_LOAD_EXTENSION
drh98aa2ab2018-09-26 16:53:51 +00004322 ".load FILE ?ENTRY? Load an extension library",
drh2ce15c32017-07-11 13:34:40 +00004323#endif
drh98aa2ab2018-09-26 16:53:51 +00004324 ".log FILE|off Turn logging on or off. FILE can be stderr/stdout",
drh47741b82022-01-31 22:14:53 +00004325 ".mode MODE ?OPTIONS? Set output mode",
drh98aa2ab2018-09-26 16:53:51 +00004326 " MODE is one of:",
drhe40f2862022-01-31 14:14:29 +00004327 " ascii Columns/rows delimited by 0x1F and 0x1E",
4328 " box Tables using unicode box-drawing characters",
4329 " csv Comma-separated values",
4330 " column Output in columns. (See .width)",
4331 " html HTML <table> code",
4332 " insert SQL insert statements for TABLE",
4333 " json Results in a JSON array",
4334 " line One value per line",
4335 " list Values delimited by \"|\"",
4336 " markdown Markdown table format",
4337 " qbox Shorthand for \"box --width 60 --quote\"",
4338 " quote Escape answers as for SQL",
4339 " table ASCII-art table",
4340 " tabs Tab-separated values",
4341 " tcl TCL list elements",
larrybrcc4d55c2022-02-01 02:50:45 +00004342 " OPTIONS: (for columnar modes or insert mode):",
4343 " --wrap N Wrap output lines to no longer than N characters",
drhca1776b2022-02-01 12:28:17 +00004344 " --wordwrap B Wrap or not at word boundaries per B (on/off)",
4345 " --ww Shorthand for \"--wordwrap 1\"",
larrybrcc4d55c2022-02-01 02:50:45 +00004346 " --quote Quote output text as SQL literals",
4347 " --noquote Do not quote output text",
4348 " TABLE The name of SQL table used for \"insert\" mode",
4349 ".nonce STRING Suspend safe mode for one command if nonce matches",
drh98aa2ab2018-09-26 16:53:51 +00004350 ".nullvalue STRING Use STRING in place of NULL values",
drh7a431002020-04-18 14:12:00 +00004351 ".once ?OPTIONS? ?FILE? Output for the next SQL command only to FILE",
drh98aa2ab2018-09-26 16:53:51 +00004352 " If FILE begins with '|' then open as a pipe",
drh7a431002020-04-18 14:12:00 +00004353 " --bom Put a UTF8 byte-order mark at the beginning",
4354 " -e Send output to the system text editor",
4355 " -x Send output as CSV to a spreadsheet (same as \".excel\")",
drh98aa2ab2018-09-26 16:53:51 +00004356 ".open ?OPTIONS? ?FILE? Close existing database and reopen FILE",
4357 " Options:",
drh60f34ae2018-10-30 13:19:49 +00004358 " --append Use appendvfs to append database to the end of FILE",
drh8d889af2021-05-08 17:18:23 +00004359#ifndef SQLITE_OMIT_DESERIALIZE
drhd10c3ca2021-05-08 11:57:35 +00004360 " --deserialize Load into memory using sqlite3_deserialize()",
drhe2754c12019-08-26 12:50:01 +00004361 " --hexdb Load the output of \"dbtotxt\" as an in-memory db",
drh6ca64482019-01-22 16:06:20 +00004362 " --maxsize N Maximum size for --hexdb or --deserialized database",
drha751f392018-10-30 15:31:22 +00004363#endif
drh60f34ae2018-10-30 13:19:49 +00004364 " --new Initialize FILE to an empty database",
drh0933aad2019-11-18 17:46:38 +00004365 " --nofollow Do not follow symbolic links",
drh60f34ae2018-10-30 13:19:49 +00004366 " --readonly Open FILE readonly",
4367 " --zip FILE is a ZIP archive",
drh98aa2ab2018-09-26 16:53:51 +00004368 ".output ?FILE? Send output to FILE or stdout if FILE is omitted",
drh7a431002020-04-18 14:12:00 +00004369 " If FILE begins with '|' then open it as a pipe.",
4370 " Options:",
4371 " --bom Prefix output with a UTF8 byte-order mark",
4372 " -e Send output to the system text editor",
4373 " -x Send output as CSV to a spreadsheet",
drh9cb02642019-02-28 20:10:52 +00004374 ".parameter CMD ... Manage SQL parameter bindings",
4375 " clear Erase all bindings",
4376 " init Initialize the TEMP table that holds bindings",
4377 " list List the current parameter bindings",
4378 " set PARAMETER VALUE Given SQL parameter PARAMETER a value of VALUE",
drhe2754c12019-08-26 12:50:01 +00004379 " PARAMETER should start with one of: $ : @ ?",
drh9cb02642019-02-28 20:10:52 +00004380 " unset PARAMETER Remove PARAMETER from the binding table",
drh98aa2ab2018-09-26 16:53:51 +00004381 ".print STRING... Print literal STRING",
drh569b1d92019-02-05 20:51:41 +00004382#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
drh3f83f592019-02-04 14:53:18 +00004383 ".progress N Invoke progress handler after every N opcodes",
4384 " --limit N Interrupt after N progress callbacks",
4385 " --once Do no more than one progress interrupt",
4386 " --quiet|-q No output except at interrupts",
4387 " --reset Reset the count for each input and interrupt",
drh569b1d92019-02-05 20:51:41 +00004388#endif
drh98aa2ab2018-09-26 16:53:51 +00004389 ".prompt MAIN CONTINUE Replace the standard prompts",
4390 ".quit Exit this program",
larrybra2ba25b2021-12-28 05:08:38 +00004391 ".read FILE Read input from FILE or command output",
4392 " If FILE begins with \"|\", it is a command that generates the input.",
dan1b162162019-04-27 20:15:15 +00004393#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
dan42ebb012019-04-27 18:47:03 +00004394 ".recover Recover as much data as possible from corrupt db.",
drhe2754c12019-08-26 12:50:01 +00004395 " --freelist-corrupt Assume the freelist is corrupt",
4396 " --recovery-db NAME Store recovery metadata in database file NAME",
4397 " --lost-and-found TABLE Alternative name for the lost-and-found table",
dan8cce6b82019-09-14 16:44:51 +00004398 " --no-rowids Do not attempt to recover rowid values",
4399 " that are not also INTEGER PRIMARY KEYs",
dan1b162162019-04-27 20:15:15 +00004400#endif
drh98aa2ab2018-09-26 16:53:51 +00004401 ".restore ?DB? FILE Restore content of DB (default \"main\") from FILE",
larrybra7919ad2022-02-19 21:25:48 +00004402 ".save ?OPTIONS? FILE Write database to FILE (an alias for .backup ...)",
drh98aa2ab2018-09-26 16:53:51 +00004403 ".scanstats on|off Turn sqlite3_stmt_scanstatus() metrics on or off",
4404 ".schema ?PATTERN? Show the CREATE statements matching PATTERN",
drhbbb29ec2020-10-12 14:56:47 +00004405 " Options:",
4406 " --indent Try to pretty-print the schema",
4407 " --nosys Omit objects whose names start with \"sqlite_\"",
drheb7f2a02018-09-26 18:02:32 +00004408 ".selftest ?OPTIONS? Run tests defined in the SELFTEST table",
4409 " Options:",
4410 " --init Create a new SELFTEST table",
4411 " -v Verbose output",
drh98aa2ab2018-09-26 16:53:51 +00004412 ".separator COL ?ROW? Change the column and row separators",
drh2ce15c32017-07-11 13:34:40 +00004413#if defined(SQLITE_ENABLE_SESSION)
drheb7f2a02018-09-26 18:02:32 +00004414 ".session ?NAME? CMD ... Create or control sessions",
4415 " Subcommands:",
4416 " attach TABLE Attach TABLE",
4417 " changeset FILE Write a changeset into FILE",
4418 " close Close one session",
4419 " enable ?BOOLEAN? Set or query the enable bit",
4420 " filter GLOB... Reject tables matching GLOBs",
4421 " indirect ?BOOLEAN? Mark or query the indirect status",
4422 " isempty Query whether the session is empty",
4423 " list List currently open session names",
4424 " open DB NAME Open a new session on DB",
4425 " patchset FILE Write a patchset into FILE",
4426 " If ?NAME? is omitted, the first defined session is used.",
drh2ce15c32017-07-11 13:34:40 +00004427#endif
drheb7f2a02018-09-26 18:02:32 +00004428 ".sha3sum ... Compute a SHA3 hash of database content",
4429 " Options:",
drh067b92b2020-06-19 15:24:12 +00004430 " --schema Also hash the sqlite_schema table",
drheb7f2a02018-09-26 18:02:32 +00004431 " --sha3-224 Use the sha3-224 algorithm",
drhe2754c12019-08-26 12:50:01 +00004432 " --sha3-256 Use the sha3-256 algorithm (default)",
drheb7f2a02018-09-26 18:02:32 +00004433 " --sha3-384 Use the sha3-384 algorithm",
4434 " --sha3-512 Use the sha3-512 algorithm",
4435 " Any other argument is a LIKE pattern for tables to hash",
drh04a28c32018-01-31 01:38:44 +00004436#ifndef SQLITE_NOHAVE_SYSTEM
drh98aa2ab2018-09-26 16:53:51 +00004437 ".shell CMD ARGS... Run CMD ARGS... in a system shell",
drh04a28c32018-01-31 01:38:44 +00004438#endif
drh98aa2ab2018-09-26 16:53:51 +00004439 ".show Show the current values for various settings",
drha6e6cf22021-01-09 19:10:04 +00004440 ".stats ?ARG? Show stats or turn stats on or off",
4441 " off Turn off automatic stat display",
4442 " on Turn on automatic stat display",
4443 " stmt Show statement stats",
4444 " vmstep Show the virtual machine step count only",
drh04a28c32018-01-31 01:38:44 +00004445#ifndef SQLITE_NOHAVE_SYSTEM
drh98aa2ab2018-09-26 16:53:51 +00004446 ".system CMD ARGS... Run CMD ARGS... in a system shell",
drh04a28c32018-01-31 01:38:44 +00004447#endif
drh98aa2ab2018-09-26 16:53:51 +00004448 ".tables ?TABLE? List names of tables matching LIKE pattern TABLE",
4449 ".testcase NAME Begin redirecting output to 'testcase-out.txt'",
drhd985f722019-06-05 14:29:53 +00004450 ".testctrl CMD ... Run various sqlite3_test_control() operations",
4451 " Run \".testctrl\" with no arguments for details",
drh98aa2ab2018-09-26 16:53:51 +00004452 ".timeout MS Try opening locked tables for MS milliseconds",
4453 ".timer on|off Turn SQL timer on or off",
drh707821f2018-12-05 13:39:06 +00004454#ifndef SQLITE_OMIT_TRACE
4455 ".trace ?OPTIONS? Output each SQL statement as it is run",
4456 " FILE Send output to FILE",
4457 " stdout Send output to stdout",
4458 " stderr Send output to stderr",
4459 " off Disable tracing",
4460 " --expanded Expand query parameters",
4461#ifdef SQLITE_ENABLE_NORMALIZE
4462 " --normalized Normal the SQL statements",
4463#endif
4464 " --plain Show SQL as it is input",
4465 " --stmt Trace statement execution (SQLITE_TRACE_STMT)",
4466 " --profile Profile statements (SQLITE_TRACE_PROFILE)",
4467 " --row Trace each row (SQLITE_TRACE_ROW)",
4468 " --close Trace connection close (SQLITE_TRACE_CLOSE)",
4469#endif /* SQLITE_OMIT_TRACE */
drhcc5979d2019-08-16 22:58:29 +00004470#ifdef SQLITE_DEBUG
4471 ".unmodule NAME ... Unregister virtual table modules",
drh5df84282019-08-17 19:45:25 +00004472 " --allexcept Unregister everything except those named",
drhcc5979d2019-08-16 22:58:29 +00004473#endif
drh98aa2ab2018-09-26 16:53:51 +00004474 ".vfsinfo ?AUX? Information about the top-level VFS",
4475 ".vfslist List all available VFSes",
4476 ".vfsname ?AUX? Print the name of the VFS stack",
drh7da29a32020-05-29 19:17:20 +00004477 ".width NUM1 NUM2 ... Set minimum column widths for columnar output",
drh98aa2ab2018-09-26 16:53:51 +00004478 " Negative values right-justify",
4479};
4480
4481/*
4482** Output help text.
4483**
4484** zPattern describes the set of commands for which help text is provided.
4485** If zPattern is NULL, then show all commands, but only give a one-line
4486** description of each.
4487**
4488** Return the number of matches.
4489*/
4490static int showHelp(FILE *out, const char *zPattern){
drhe93f8262018-10-11 16:53:37 +00004491 int i = 0;
4492 int j = 0;
drh98aa2ab2018-09-26 16:53:51 +00004493 int n = 0;
4494 char *zPat;
drh488cddf2018-10-06 14:38:17 +00004495 if( zPattern==0
4496 || zPattern[0]=='0'
4497 || strcmp(zPattern,"-a")==0
4498 || strcmp(zPattern,"-all")==0
drh7a431002020-04-18 14:12:00 +00004499 || strcmp(zPattern,"--all")==0
drh488cddf2018-10-06 14:38:17 +00004500 ){
drh98aa2ab2018-09-26 16:53:51 +00004501 /* Show all commands, but only one line per command */
drh488cddf2018-10-06 14:38:17 +00004502 if( zPattern==0 ) zPattern = "";
drh98aa2ab2018-09-26 16:53:51 +00004503 for(i=0; i<ArraySize(azHelp); i++){
drh488cddf2018-10-06 14:38:17 +00004504 if( azHelp[i][0]=='.' || zPattern[0] ){
drh98aa2ab2018-09-26 16:53:51 +00004505 utf8_printf(out, "%s\n", azHelp[i]);
4506 n++;
4507 }
4508 }
4509 }else{
4510 /* Look for commands that for which zPattern is an exact prefix */
4511 zPat = sqlite3_mprintf(".%s*", zPattern);
drhe3e25652021-12-16 13:29:28 +00004512 shell_check_oom(zPat);
drh98aa2ab2018-09-26 16:53:51 +00004513 for(i=0; i<ArraySize(azHelp); i++){
4514 if( sqlite3_strglob(zPat, azHelp[i])==0 ){
4515 utf8_printf(out, "%s\n", azHelp[i]);
drheb7f2a02018-09-26 18:02:32 +00004516 j = i+1;
drh98aa2ab2018-09-26 16:53:51 +00004517 n++;
4518 }
4519 }
4520 sqlite3_free(zPat);
drheb7f2a02018-09-26 18:02:32 +00004521 if( n ){
4522 if( n==1 ){
4523 /* when zPattern is a prefix of exactly one command, then include the
4524 ** details of that command, which should begin at offset j */
4525 while( j<ArraySize(azHelp)-1 && azHelp[j][0]!='.' ){
4526 utf8_printf(out, "%s\n", azHelp[j]);
4527 j++;
4528 }
4529 }
4530 return n;
4531 }
4532 /* Look for commands that contain zPattern anywhere. Show the complete
4533 ** text of all commands that match. */
drh98aa2ab2018-09-26 16:53:51 +00004534 zPat = sqlite3_mprintf("%%%s%%", zPattern);
drhe3e25652021-12-16 13:29:28 +00004535 shell_check_oom(zPat);
drh98aa2ab2018-09-26 16:53:51 +00004536 for(i=0; i<ArraySize(azHelp); i++){
4537 if( azHelp[i][0]=='.' ) j = i;
4538 if( sqlite3_strlike(zPat, azHelp[i], 0)==0 ){
4539 utf8_printf(out, "%s\n", azHelp[j]);
4540 while( j<ArraySize(azHelp)-1 && azHelp[j+1][0]!='.' ){
4541 j++;
4542 utf8_printf(out, "%s\n", azHelp[j]);
4543 }
4544 i = j;
4545 n++;
4546 }
4547 }
4548 sqlite3_free(zPat);
4549 }
4550 return n;
4551}
drh2ce15c32017-07-11 13:34:40 +00004552
drh2ce15c32017-07-11 13:34:40 +00004553/* Forward reference */
drh60379d42018-12-13 18:30:01 +00004554static int process_input(ShellState *p);
drh2ce15c32017-07-11 13:34:40 +00004555
4556/*
4557** Read the content of file zName into memory obtained from sqlite3_malloc64()
4558** and return a pointer to the buffer. The caller is responsible for freeing
4559** the memory.
4560**
4561** If parameter pnByte is not NULL, (*pnByte) is set to the number of bytes
4562** read.
4563**
4564** For convenience, a nul-terminator byte is always appended to the data read
4565** from the file before the buffer is returned. This byte is not included in
4566** the final value of (*pnByte), if applicable.
4567**
4568** NULL is returned if any error is encountered. The final value of *pnByte
4569** is undefined in this case.
4570*/
4571static char *readFile(const char *zName, int *pnByte){
4572 FILE *in = fopen(zName, "rb");
4573 long nIn;
4574 size_t nRead;
4575 char *pBuf;
4576 if( in==0 ) return 0;
4577 fseek(in, 0, SEEK_END);
4578 nIn = ftell(in);
4579 rewind(in);
4580 pBuf = sqlite3_malloc64( nIn+1 );
drh1dbb1472018-10-11 10:37:24 +00004581 if( pBuf==0 ){ fclose(in); return 0; }
drh2ce15c32017-07-11 13:34:40 +00004582 nRead = fread(pBuf, nIn, 1, in);
4583 fclose(in);
4584 if( nRead!=1 ){
4585 sqlite3_free(pBuf);
4586 return 0;
4587 }
4588 pBuf[nIn] = 0;
4589 if( pnByte ) *pnByte = nIn;
4590 return pBuf;
4591}
4592
4593#if defined(SQLITE_ENABLE_SESSION)
4594/*
4595** Close a single OpenSession object and release all of its associated
4596** resources.
4597*/
4598static void session_close(OpenSession *pSession){
4599 int i;
4600 sqlite3session_delete(pSession->p);
4601 sqlite3_free(pSession->zName);
4602 for(i=0; i<pSession->nFilter; i++){
4603 sqlite3_free(pSession->azFilter[i]);
4604 }
4605 sqlite3_free(pSession->azFilter);
4606 memset(pSession, 0, sizeof(OpenSession));
4607}
4608#endif
4609
4610/*
4611** Close all OpenSession objects and release all associated resources.
4612*/
4613#if defined(SQLITE_ENABLE_SESSION)
drh37407122021-07-23 18:43:58 +00004614static void session_close_all(ShellState *p, int i){
4615 int j;
4616 struct AuxDb *pAuxDb = i<0 ? p->pAuxDb : &p->aAuxDb[i];
4617 for(j=0; j<pAuxDb->nSession; j++){
4618 session_close(&pAuxDb->aSession[j]);
drh2ce15c32017-07-11 13:34:40 +00004619 }
drh37407122021-07-23 18:43:58 +00004620 pAuxDb->nSession = 0;
drh2ce15c32017-07-11 13:34:40 +00004621}
4622#else
drh37407122021-07-23 18:43:58 +00004623# define session_close_all(X,Y)
drh2ce15c32017-07-11 13:34:40 +00004624#endif
4625
4626/*
4627** Implementation of the xFilter function for an open session. Omit
4628** any tables named by ".session filter" but let all other table through.
4629*/
4630#if defined(SQLITE_ENABLE_SESSION)
4631static int session_filter(void *pCtx, const char *zTab){
4632 OpenSession *pSession = (OpenSession*)pCtx;
4633 int i;
4634 for(i=0; i<pSession->nFilter; i++){
4635 if( sqlite3_strglob(pSession->azFilter[i], zTab)==0 ) return 0;
4636 }
4637 return 1;
4638}
4639#endif
4640
4641/*
drh1fa6d9f2018-01-06 21:46:01 +00004642** Try to deduce the type of file for zName based on its content. Return
4643** one of the SHELL_OPEN_* constants.
drh1bf208c2018-03-09 21:54:01 +00004644**
4645** If the file does not exist or is empty but its name looks like a ZIP
4646** archive and the dfltZip flag is true, then assume it is a ZIP archive.
4647** Otherwise, assume an ordinary database regardless of the filename if
4648** the type cannot be determined from content.
drh1fa6d9f2018-01-06 21:46:01 +00004649*/
drhfc97c1c2018-05-14 00:41:12 +00004650int deduceDatabaseType(const char *zName, int dfltZip){
drh1fa6d9f2018-01-06 21:46:01 +00004651 FILE *f = fopen(zName, "rb");
4652 size_t n;
4653 int rc = SHELL_OPEN_UNSPEC;
4654 char zBuf[100];
drh1bf208c2018-03-09 21:54:01 +00004655 if( f==0 ){
drhbe4ccb22018-05-17 20:04:24 +00004656 if( dfltZip && sqlite3_strlike("%.zip",zName,0)==0 ){
4657 return SHELL_OPEN_ZIPFILE;
4658 }else{
4659 return SHELL_OPEN_NORMAL;
4660 }
drh1bf208c2018-03-09 21:54:01 +00004661 }
drh2b3c4af2018-10-30 14:36:21 +00004662 n = fread(zBuf, 16, 1, f);
4663 if( n==1 && memcmp(zBuf, "SQLite format 3", 16)==0 ){
4664 fclose(f);
4665 return SHELL_OPEN_NORMAL;
4666 }
drh1fa6d9f2018-01-06 21:46:01 +00004667 fseek(f, -25, SEEK_END);
4668 n = fread(zBuf, 25, 1, f);
4669 if( n==1 && memcmp(zBuf, "Start-Of-SQLite3-", 17)==0 ){
4670 rc = SHELL_OPEN_APPENDVFS;
4671 }else{
4672 fseek(f, -22, SEEK_END);
4673 n = fread(zBuf, 22, 1, f);
4674 if( n==1 && zBuf[0]==0x50 && zBuf[1]==0x4b && zBuf[2]==0x05
4675 && zBuf[3]==0x06 ){
4676 rc = SHELL_OPEN_ZIPFILE;
drh1bf208c2018-03-09 21:54:01 +00004677 }else if( n==0 && dfltZip && sqlite3_strlike("%.zip",zName,0)==0 ){
mistachkina3926f42018-05-14 12:23:04 +00004678 rc = SHELL_OPEN_ZIPFILE;
drh1fa6d9f2018-01-06 21:46:01 +00004679 }
4680 }
4681 fclose(f);
4682 return rc;
4683}
4684
drh8d889af2021-05-08 17:18:23 +00004685#ifndef SQLITE_OMIT_DESERIALIZE
drh33746482018-12-13 15:06:26 +00004686/*
4687** Reconstruct an in-memory database using the output from the "dbtotxt"
drh37407122021-07-23 18:43:58 +00004688** program. Read content from the file in p->aAuxDb[].zDbFilename.
4689** If p->aAuxDb[].zDbFilename is 0, then read from standard input.
drh33746482018-12-13 15:06:26 +00004690*/
4691static unsigned char *readHexDb(ShellState *p, int *pnData){
4692 unsigned char *a = 0;
drh2c8ee022018-12-13 18:59:30 +00004693 int nLine;
drh33746482018-12-13 15:06:26 +00004694 int n = 0;
4695 int pgsz = 0;
4696 int iOffset = 0;
4697 int j, k;
4698 int rc;
4699 FILE *in;
drh37407122021-07-23 18:43:58 +00004700 const char *zDbFilename = p->pAuxDb->zDbFilename;
drh3ea557e2019-04-23 15:30:58 +00004701 unsigned int x[16];
drh2c8ee022018-12-13 18:59:30 +00004702 char zLine[1000];
drh37407122021-07-23 18:43:58 +00004703 if( zDbFilename ){
4704 in = fopen(zDbFilename, "r");
drh33746482018-12-13 15:06:26 +00004705 if( in==0 ){
drh37407122021-07-23 18:43:58 +00004706 utf8_printf(stderr, "cannot open \"%s\" for reading\n", zDbFilename);
drh33746482018-12-13 15:06:26 +00004707 return 0;
4708 }
drh2c8ee022018-12-13 18:59:30 +00004709 nLine = 0;
drh33746482018-12-13 15:06:26 +00004710 }else{
drh60379d42018-12-13 18:30:01 +00004711 in = p->in;
drh2c8ee022018-12-13 18:59:30 +00004712 nLine = p->lineno;
drh5bf46442019-05-03 02:41:36 +00004713 if( in==0 ) in = stdin;
drh33746482018-12-13 15:06:26 +00004714 }
4715 *pnData = 0;
drh2c8ee022018-12-13 18:59:30 +00004716 nLine++;
drh33746482018-12-13 15:06:26 +00004717 if( fgets(zLine, sizeof(zLine), in)==0 ) goto readHexDb_error;
4718 rc = sscanf(zLine, "| size %d pagesize %d", &n, &pgsz);
4719 if( rc!=2 ) goto readHexDb_error;
drh68feae52019-05-09 11:18:41 +00004720 if( n<0 ) goto readHexDb_error;
drh09ea1252019-07-17 15:05:16 +00004721 if( pgsz<512 || pgsz>65536 || (pgsz&(pgsz-1))!=0 ) goto readHexDb_error;
4722 n = (n+pgsz-1)&~(pgsz-1); /* Round n up to the next multiple of pgsz */
drh68feae52019-05-09 11:18:41 +00004723 a = sqlite3_malloc( n ? n : 1 );
drhe3e25652021-12-16 13:29:28 +00004724 shell_check_oom(a);
drh33746482018-12-13 15:06:26 +00004725 memset(a, 0, n);
4726 if( pgsz<512 || pgsz>65536 || (pgsz & (pgsz-1))!=0 ){
4727 utf8_printf(stderr, "invalid pagesize\n");
4728 goto readHexDb_error;
4729 }
drh2c8ee022018-12-13 18:59:30 +00004730 for(nLine++; fgets(zLine, sizeof(zLine), in)!=0; nLine++){
drh33746482018-12-13 15:06:26 +00004731 rc = sscanf(zLine, "| page %d offset %d", &j, &k);
4732 if( rc==2 ){
4733 iOffset = k;
4734 continue;
4735 }
4736 if( strncmp(zLine, "| end ", 6)==0 ){
4737 break;
4738 }
drh3ea557e2019-04-23 15:30:58 +00004739 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 +00004740 &j, &x[0], &x[1], &x[2], &x[3], &x[4], &x[5], &x[6], &x[7],
4741 &x[8], &x[9], &x[10], &x[11], &x[12], &x[13], &x[14], &x[15]);
4742 if( rc==17 ){
4743 k = iOffset+j;
drh82978ac2021-10-01 17:06:44 +00004744 if( k+16<=n && k>=0 ){
drh3ea557e2019-04-23 15:30:58 +00004745 int ii;
4746 for(ii=0; ii<16; ii++) a[k+ii] = x[ii]&0xff;
drh33746482018-12-13 15:06:26 +00004747 }
drh33746482018-12-13 15:06:26 +00004748 }
4749 }
4750 *pnData = n;
drh2c8ee022018-12-13 18:59:30 +00004751 if( in!=p->in ){
4752 fclose(in);
4753 }else{
4754 p->lineno = nLine;
4755 }
drh33746482018-12-13 15:06:26 +00004756 return a;
4757
4758readHexDb_error:
drh68feae52019-05-09 11:18:41 +00004759 if( in!=p->in ){
drh33746482018-12-13 15:06:26 +00004760 fclose(in);
4761 }else{
drh60379d42018-12-13 18:30:01 +00004762 while( fgets(zLine, sizeof(zLine), p->in)!=0 ){
drh2c8ee022018-12-13 18:59:30 +00004763 nLine++;
drh33746482018-12-13 15:06:26 +00004764 if(strncmp(zLine, "| end ", 6)==0 ) break;
4765 }
drh2c8ee022018-12-13 18:59:30 +00004766 p->lineno = nLine;
drh33746482018-12-13 15:06:26 +00004767 }
4768 sqlite3_free(a);
4769 utf8_printf(stderr,"Error on line %d of --hexdb input\n", nLine);
4770 return 0;
4771}
drh8d889af2021-05-08 17:18:23 +00004772#endif /* SQLITE_OMIT_DESERIALIZE */
drh33746482018-12-13 15:06:26 +00004773
danb1825882019-04-23 20:48:32 +00004774/*
dan9c014f82019-04-25 19:23:15 +00004775** Scalar function "shell_int32". The first argument to this function
4776** must be a blob. The second a non-negative integer. This function
4777** reads and returns a 32-bit big-endian integer from byte
4778** offset (4*<arg2>) of the blob.
4779*/
4780static void shellInt32(
4781 sqlite3_context *context,
4782 int argc,
4783 sqlite3_value **argv
4784){
4785 const unsigned char *pBlob;
4786 int nBlob;
4787 int iInt;
drh9546c762019-05-10 17:50:33 +00004788
4789 UNUSED_PARAMETER(argc);
dan9c014f82019-04-25 19:23:15 +00004790 nBlob = sqlite3_value_bytes(argv[0]);
4791 pBlob = (const unsigned char*)sqlite3_value_blob(argv[0]);
4792 iInt = sqlite3_value_int(argv[1]);
4793
4794 if( iInt>=0 && (iInt+1)*4<=nBlob ){
4795 const unsigned char *a = &pBlob[iInt*4];
4796 sqlite3_int64 iVal = ((sqlite3_int64)a[0]<<24)
4797 + ((sqlite3_int64)a[1]<<16)
4798 + ((sqlite3_int64)a[2]<< 8)
4799 + ((sqlite3_int64)a[3]<< 0);
4800 sqlite3_result_int64(context, iVal);
4801 }
4802}
4803
4804/*
drha2de66c2019-08-06 20:26:17 +00004805** Scalar function "shell_idquote(X)" returns string X quoted as an identifier,
4806** using "..." with internal double-quote characters doubled.
4807*/
4808static void shellIdQuote(
4809 sqlite3_context *context,
4810 int argc,
4811 sqlite3_value **argv
4812){
4813 const char *zName = (const char*)sqlite3_value_text(argv[0]);
drh51755a72019-08-08 19:40:29 +00004814 UNUSED_PARAMETER(argc);
drha2de66c2019-08-06 20:26:17 +00004815 if( zName ){
4816 char *z = sqlite3_mprintf("\"%w\"", zName);
4817 sqlite3_result_text(context, z, -1, sqlite3_free);
4818 }
4819}
4820
4821/*
drhddcfe922020-09-15 12:29:35 +00004822** Scalar function "usleep(X)" invokes sqlite3_sleep(X) and returns X.
4823*/
4824static void shellUSleepFunc(
4825 sqlite3_context *context,
drhd36f5882020-11-25 16:28:04 +00004826 int argcUnused,
drhddcfe922020-09-15 12:29:35 +00004827 sqlite3_value **argv
4828){
4829 int sleep = sqlite3_value_int(argv[0]);
drhd36f5882020-11-25 16:28:04 +00004830 (void)argcUnused;
drhddcfe922020-09-15 12:29:35 +00004831 sqlite3_sleep(sleep/1000);
4832 sqlite3_result_int(context, sleep);
4833}
4834
4835/*
danb1825882019-04-23 20:48:32 +00004836** Scalar function "shell_escape_crnl" used by the .recover command.
4837** The argument passed to this function is the output of built-in
4838** function quote(). If the first character of the input is "'",
4839** indicating that the value passed to quote() was a text value,
4840** then this function searches the input for "\n" and "\r" characters
4841** and adds a wrapper similar to the following:
4842**
4843** replace(replace(<input>, '\n', char(10), '\r', char(13));
4844**
4845** Or, if the first character of the input is not "'", then a copy
4846** of the input is returned.
4847*/
4848static void shellEscapeCrnl(
4849 sqlite3_context *context,
4850 int argc,
4851 sqlite3_value **argv
4852){
4853 const char *zText = (const char*)sqlite3_value_text(argv[0]);
drh9546c762019-05-10 17:50:33 +00004854 UNUSED_PARAMETER(argc);
drh621a5e02021-12-16 17:35:27 +00004855 if( zText && zText[0]=='\'' ){
danb1825882019-04-23 20:48:32 +00004856 int nText = sqlite3_value_bytes(argv[0]);
4857 int i;
4858 char zBuf1[20];
4859 char zBuf2[20];
4860 const char *zNL = 0;
4861 const char *zCR = 0;
4862 int nCR = 0;
4863 int nNL = 0;
4864
4865 for(i=0; zText[i]; i++){
4866 if( zNL==0 && zText[i]=='\n' ){
4867 zNL = unused_string(zText, "\\n", "\\012", zBuf1);
4868 nNL = (int)strlen(zNL);
4869 }
4870 if( zCR==0 && zText[i]=='\r' ){
4871 zCR = unused_string(zText, "\\r", "\\015", zBuf2);
4872 nCR = (int)strlen(zCR);
4873 }
4874 }
4875
4876 if( zNL || zCR ){
4877 int iOut = 0;
4878 i64 nMax = (nNL > nCR) ? nNL : nCR;
dan51f5ffa2019-04-29 11:41:46 +00004879 i64 nAlloc = nMax * nText + (nMax+64)*2;
danb1825882019-04-23 20:48:32 +00004880 char *zOut = (char*)sqlite3_malloc64(nAlloc);
4881 if( zOut==0 ){
4882 sqlite3_result_error_nomem(context);
4883 return;
4884 }
4885
4886 if( zNL && zCR ){
4887 memcpy(&zOut[iOut], "replace(replace(", 16);
4888 iOut += 16;
4889 }else{
4890 memcpy(&zOut[iOut], "replace(", 8);
4891 iOut += 8;
4892 }
4893 for(i=0; zText[i]; i++){
4894 if( zText[i]=='\n' ){
4895 memcpy(&zOut[iOut], zNL, nNL);
4896 iOut += nNL;
4897 }else if( zText[i]=='\r' ){
4898 memcpy(&zOut[iOut], zCR, nCR);
4899 iOut += nCR;
4900 }else{
4901 zOut[iOut] = zText[i];
4902 iOut++;
4903 }
4904 }
4905
4906 if( zNL ){
4907 memcpy(&zOut[iOut], ",'", 2); iOut += 2;
4908 memcpy(&zOut[iOut], zNL, nNL); iOut += nNL;
4909 memcpy(&zOut[iOut], "', char(10))", 12); iOut += 12;
4910 }
4911 if( zCR ){
4912 memcpy(&zOut[iOut], ",'", 2); iOut += 2;
4913 memcpy(&zOut[iOut], zCR, nCR); iOut += nCR;
4914 memcpy(&zOut[iOut], "', char(13))", 12); iOut += 12;
4915 }
4916
4917 sqlite3_result_text(context, zOut, iOut, SQLITE_TRANSIENT);
4918 sqlite3_free(zOut);
4919 return;
4920 }
4921 }
4922
4923 sqlite3_result_value(context, argv[0]);
4924}
4925
drhbe4ccb22018-05-17 20:04:24 +00004926/* Flags for open_db().
4927**
4928** The default behavior of open_db() is to exit(1) if the database fails to
4929** open. The OPEN_DB_KEEPALIVE flag changes that so that it prints an error
4930** but still returns without calling exit.
4931**
4932** The OPEN_DB_ZIPFILE flag causes open_db() to prefer to open files as a
4933** ZIP archive if the file does not exist or is empty and its name matches
4934** the *.zip pattern.
4935*/
4936#define OPEN_DB_KEEPALIVE 0x001 /* Return after error if true */
4937#define OPEN_DB_ZIPFILE 0x002 /* Open as ZIP if name matches *.zip */
4938
drh1fa6d9f2018-01-06 21:46:01 +00004939/*
drh2ce15c32017-07-11 13:34:40 +00004940** Make sure the database is open. If it is not, then open it. If
4941** the database fails to open, print an error message and exit.
4942*/
drhbe4ccb22018-05-17 20:04:24 +00004943static void open_db(ShellState *p, int openFlags){
drh2ce15c32017-07-11 13:34:40 +00004944 if( p->db==0 ){
drh37407122021-07-23 18:43:58 +00004945 const char *zDbFilename = p->pAuxDb->zDbFilename;
drhf2072d12018-05-11 15:10:11 +00004946 if( p->openMode==SHELL_OPEN_UNSPEC ){
drh37407122021-07-23 18:43:58 +00004947 if( zDbFilename==0 || zDbFilename[0]==0 ){
drhf2072d12018-05-11 15:10:11 +00004948 p->openMode = SHELL_OPEN_NORMAL;
drhbe4ccb22018-05-17 20:04:24 +00004949 }else{
drh37407122021-07-23 18:43:58 +00004950 p->openMode = (u8)deduceDatabaseType(zDbFilename,
drhbe4ccb22018-05-17 20:04:24 +00004951 (openFlags & OPEN_DB_ZIPFILE)!=0);
drhf2072d12018-05-11 15:10:11 +00004952 }
drh1fa6d9f2018-01-06 21:46:01 +00004953 }
4954 switch( p->openMode ){
4955 case SHELL_OPEN_APPENDVFS: {
drh37407122021-07-23 18:43:58 +00004956 sqlite3_open_v2(zDbFilename, &p->db,
drh0933aad2019-11-18 17:46:38 +00004957 SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|p->openFlags, "apndvfs");
drh1fa6d9f2018-01-06 21:46:01 +00004958 break;
4959 }
drh33746482018-12-13 15:06:26 +00004960 case SHELL_OPEN_HEXDB:
drh60f34ae2018-10-30 13:19:49 +00004961 case SHELL_OPEN_DESERIALIZE: {
4962 sqlite3_open(0, &p->db);
4963 break;
4964 }
drh1fa6d9f2018-01-06 21:46:01 +00004965 case SHELL_OPEN_ZIPFILE: {
4966 sqlite3_open(":memory:", &p->db);
4967 break;
4968 }
drhee269a62018-02-14 23:27:43 +00004969 case SHELL_OPEN_READONLY: {
drh37407122021-07-23 18:43:58 +00004970 sqlite3_open_v2(zDbFilename, &p->db,
drh0933aad2019-11-18 17:46:38 +00004971 SQLITE_OPEN_READONLY|p->openFlags, 0);
drhee269a62018-02-14 23:27:43 +00004972 break;
4973 }
drh1fa6d9f2018-01-06 21:46:01 +00004974 case SHELL_OPEN_UNSPEC:
4975 case SHELL_OPEN_NORMAL: {
drh37407122021-07-23 18:43:58 +00004976 sqlite3_open_v2(zDbFilename, &p->db,
drh0933aad2019-11-18 17:46:38 +00004977 SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|p->openFlags, 0);
drh1fa6d9f2018-01-06 21:46:01 +00004978 break;
4979 }
4980 }
drh2ce15c32017-07-11 13:34:40 +00004981 globalDb = p->db;
4982 if( p->db==0 || SQLITE_OK!=sqlite3_errcode(p->db) ){
4983 utf8_printf(stderr,"Error: unable to open database \"%s\": %s\n",
drh37407122021-07-23 18:43:58 +00004984 zDbFilename, sqlite3_errmsg(p->db));
drhf25cc4f2019-01-04 14:29:21 +00004985 if( openFlags & OPEN_DB_KEEPALIVE ){
4986 sqlite3_open(":memory:", &p->db);
4987 return;
4988 }
drh2ce15c32017-07-11 13:34:40 +00004989 exit(1);
4990 }
4991#ifndef SQLITE_OMIT_LOAD_EXTENSION
4992 sqlite3_enable_load_extension(p->db, 1);
4993#endif
4994 sqlite3_fileio_init(p->db, 0, 0);
4995 sqlite3_shathree_init(p->db, 0, 0);
drh56eb09b2017-07-11 13:59:07 +00004996 sqlite3_completion_init(p->db, 0, 0);
drhf05dd032020-04-14 15:53:58 +00004997 sqlite3_uint_init(p->db, 0, 0);
drhbeb9def2020-06-22 19:12:23 +00004998 sqlite3_decimal_init(p->db, 0, 0);
drh64689902021-06-03 13:51:31 +00004999 sqlite3_regexp_init(p->db, 0, 0);
drh8cda77d2020-06-24 15:06:29 +00005000 sqlite3_ieee_init(p->db, 0, 0);
mistachkin72c38d82020-08-28 18:47:39 +00005001 sqlite3_series_init(p->db, 0, 0);
dan1b162162019-04-27 20:15:15 +00005002#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
dan68cb86e2019-04-20 20:57:28 +00005003 sqlite3_dbdata_init(p->db, 0, 0);
dan1b162162019-04-27 20:15:15 +00005004#endif
dan72afc3c2017-12-05 18:32:40 +00005005#ifdef SQLITE_HAVE_ZLIB
drh9198f5a2022-03-19 15:19:35 +00005006 if( !p->bSafeModePersist ){
5007 sqlite3_zipfile_init(p->db, 0, 0);
5008 sqlite3_sqlar_init(p->db, 0, 0);
5009 }
dan72afc3c2017-12-05 18:32:40 +00005010#endif
drhceba7922018-01-01 21:28:25 +00005011 sqlite3_create_function(p->db, "shell_add_schema", 3, SQLITE_UTF8, 0,
drh2ce15c32017-07-11 13:34:40 +00005012 shellAddSchemaName, 0, 0);
drh667a2a22018-01-02 00:04:37 +00005013 sqlite3_create_function(p->db, "shell_module_schema", 1, SQLITE_UTF8, 0,
5014 shellModuleSchema, 0, 0);
drh634c70f2018-01-10 16:50:18 +00005015 sqlite3_create_function(p->db, "shell_putsnl", 1, SQLITE_UTF8, p,
5016 shellPutsFunc, 0, 0);
danb1825882019-04-23 20:48:32 +00005017 sqlite3_create_function(p->db, "shell_escape_crnl", 1, SQLITE_UTF8, 0,
5018 shellEscapeCrnl, 0, 0);
dan9c014f82019-04-25 19:23:15 +00005019 sqlite3_create_function(p->db, "shell_int32", 2, SQLITE_UTF8, 0,
5020 shellInt32, 0, 0);
drha2de66c2019-08-06 20:26:17 +00005021 sqlite3_create_function(p->db, "shell_idquote", 1, SQLITE_UTF8, 0,
5022 shellIdQuote, 0, 0);
drhddcfe922020-09-15 12:29:35 +00005023 sqlite3_create_function(p->db, "usleep",1,SQLITE_UTF8,0,
5024 shellUSleepFunc, 0, 0);
drh04a28c32018-01-31 01:38:44 +00005025#ifndef SQLITE_NOHAVE_SYSTEM
drh97913132018-01-11 00:04:00 +00005026 sqlite3_create_function(p->db, "edit", 1, SQLITE_UTF8, 0,
5027 editFunc, 0, 0);
5028 sqlite3_create_function(p->db, "edit", 2, SQLITE_UTF8, 0,
5029 editFunc, 0, 0);
drh04a28c32018-01-31 01:38:44 +00005030#endif
drh1fa6d9f2018-01-06 21:46:01 +00005031 if( p->openMode==SHELL_OPEN_ZIPFILE ){
5032 char *zSql = sqlite3_mprintf(
drh37407122021-07-23 18:43:58 +00005033 "CREATE VIRTUAL TABLE zip USING zipfile(%Q);", zDbFilename);
drhe3e25652021-12-16 13:29:28 +00005034 shell_check_oom(zSql);
drh1fa6d9f2018-01-06 21:46:01 +00005035 sqlite3_exec(p->db, zSql, 0, 0, 0);
5036 sqlite3_free(zSql);
drha751f392018-10-30 15:31:22 +00005037 }
drh8d889af2021-05-08 17:18:23 +00005038#ifndef SQLITE_OMIT_DESERIALIZE
drh33746482018-12-13 15:06:26 +00005039 else
5040 if( p->openMode==SHELL_OPEN_DESERIALIZE || p->openMode==SHELL_OPEN_HEXDB ){
mistachkin99490932018-12-17 22:19:57 +00005041 int rc;
drh60f34ae2018-10-30 13:19:49 +00005042 int nData = 0;
drh33746482018-12-13 15:06:26 +00005043 unsigned char *aData;
5044 if( p->openMode==SHELL_OPEN_DESERIALIZE ){
drh37407122021-07-23 18:43:58 +00005045 aData = (unsigned char*)readFile(zDbFilename, &nData);
drh33746482018-12-13 15:06:26 +00005046 }else{
5047 aData = readHexDb(p, &nData);
5048 if( aData==0 ){
drh33746482018-12-13 15:06:26 +00005049 return;
5050 }
5051 }
mistachkin99490932018-12-17 22:19:57 +00005052 rc = sqlite3_deserialize(p->db, "main", aData, nData, nData,
drh60f34ae2018-10-30 13:19:49 +00005053 SQLITE_DESERIALIZE_RESIZEABLE |
5054 SQLITE_DESERIALIZE_FREEONCLOSE);
5055 if( rc ){
5056 utf8_printf(stderr, "Error: sqlite3_deserialize() returns %d\n", rc);
5057 }
drh6ca64482019-01-22 16:06:20 +00005058 if( p->szMax>0 ){
5059 sqlite3_file_control(p->db, "main", SQLITE_FCNTL_SIZE_LIMIT, &p->szMax);
5060 }
drh1fa6d9f2018-01-06 21:46:01 +00005061 }
drha751f392018-10-30 15:31:22 +00005062#endif
drh2ce15c32017-07-11 13:34:40 +00005063 }
drhb97e2ad2021-08-26 18:31:39 +00005064 if( p->bSafeModePersist && p->db!=0 ){
5065 sqlite3_set_authorizer(p->db, safeModeAuth, p);
5066 }
drh2ce15c32017-07-11 13:34:40 +00005067}
5068
drh9e804032018-05-18 17:11:50 +00005069/*
5070** Attempt to close the databaes connection. Report errors.
5071*/
5072void close_db(sqlite3 *db){
5073 int rc = sqlite3_close(db);
5074 if( rc ){
5075 utf8_printf(stderr, "Error: sqlite3_close() returns %d: %s\n",
5076 rc, sqlite3_errmsg(db));
5077 }
5078}
5079
drh56eb09b2017-07-11 13:59:07 +00005080#if HAVE_READLINE || HAVE_EDITLINE
5081/*
5082** Readline completion callbacks
5083*/
5084static char *readline_completion_generator(const char *text, int state){
5085 static sqlite3_stmt *pStmt = 0;
5086 char *zRet;
5087 if( state==0 ){
5088 char *zSql;
drh56eb09b2017-07-11 13:59:07 +00005089 sqlite3_finalize(pStmt);
5090 zSql = sqlite3_mprintf("SELECT DISTINCT candidate COLLATE nocase"
5091 " FROM completion(%Q) ORDER BY 1", text);
drhe3e25652021-12-16 13:29:28 +00005092 shell_check_oom(zSql);
drh56eb09b2017-07-11 13:59:07 +00005093 sqlite3_prepare_v2(globalDb, zSql, -1, &pStmt, 0);
5094 sqlite3_free(zSql);
5095 }
5096 if( sqlite3_step(pStmt)==SQLITE_ROW ){
drh621a5e02021-12-16 17:35:27 +00005097 const char *z = (const char*)sqlite3_column_text(pStmt,0);
5098 zRet = z ? strdup(z) : 0;
drh56eb09b2017-07-11 13:59:07 +00005099 }else{
5100 sqlite3_finalize(pStmt);
5101 pStmt = 0;
5102 zRet = 0;
5103 }
5104 return zRet;
5105}
5106static char **readline_completion(const char *zText, int iStart, int iEnd){
5107 rl_attempted_completion_over = 1;
5108 return rl_completion_matches(zText, readline_completion_generator);
5109}
5110
5111#elif HAVE_LINENOISE
5112/*
5113** Linenoise completion callback
5114*/
5115static void linenoise_completion(const char *zLine, linenoiseCompletions *lc){
drhaf2770f2018-01-05 14:55:43 +00005116 int nLine = strlen30(zLine);
drh56eb09b2017-07-11 13:59:07 +00005117 int i, iStart;
5118 sqlite3_stmt *pStmt = 0;
5119 char *zSql;
5120 char zBuf[1000];
5121
5122 if( nLine>sizeof(zBuf)-30 ) return;
drh1615c372018-05-12 23:56:22 +00005123 if( zLine[0]=='.' || zLine[0]=='#') return;
drh56eb09b2017-07-11 13:59:07 +00005124 for(i=nLine-1; i>=0 && (isalnum(zLine[i]) || zLine[i]=='_'); i--){}
5125 if( i==nLine-1 ) return;
5126 iStart = i+1;
5127 memcpy(zBuf, zLine, iStart);
5128 zSql = sqlite3_mprintf("SELECT DISTINCT candidate COLLATE nocase"
5129 " FROM completion(%Q,%Q) ORDER BY 1",
5130 &zLine[iStart], zLine);
drhe3e25652021-12-16 13:29:28 +00005131 shell_check_oom(zSql);
drh56eb09b2017-07-11 13:59:07 +00005132 sqlite3_prepare_v2(globalDb, zSql, -1, &pStmt, 0);
5133 sqlite3_free(zSql);
5134 sqlite3_exec(globalDb, "PRAGMA page_count", 0, 0, 0); /* Load the schema */
5135 while( sqlite3_step(pStmt)==SQLITE_ROW ){
5136 const char *zCompletion = (const char*)sqlite3_column_text(pStmt, 0);
5137 int nCompletion = sqlite3_column_bytes(pStmt, 0);
drh621a5e02021-12-16 17:35:27 +00005138 if( iStart+nCompletion < sizeof(zBuf)-1 && zCompletion ){
drh56eb09b2017-07-11 13:59:07 +00005139 memcpy(zBuf+iStart, zCompletion, nCompletion+1);
5140 linenoiseAddCompletion(lc, zBuf);
5141 }
5142 }
5143 sqlite3_finalize(pStmt);
5144}
5145#endif
5146
drh2ce15c32017-07-11 13:34:40 +00005147/*
5148** Do C-language style dequoting.
5149**
5150** \a -> alarm
5151** \b -> backspace
5152** \t -> tab
5153** \n -> newline
5154** \v -> vertical tab
5155** \f -> form feed
5156** \r -> carriage return
5157** \s -> space
5158** \" -> "
5159** \' -> '
5160** \\ -> backslash
5161** \NNN -> ascii character NNN in octal
5162*/
5163static void resolve_backslashes(char *z){
5164 int i, j;
5165 char c;
5166 while( *z && *z!='\\' ) z++;
5167 for(i=j=0; (c = z[i])!=0; i++, j++){
5168 if( c=='\\' && z[i+1]!=0 ){
5169 c = z[++i];
5170 if( c=='a' ){
5171 c = '\a';
5172 }else if( c=='b' ){
5173 c = '\b';
5174 }else if( c=='t' ){
5175 c = '\t';
5176 }else if( c=='n' ){
5177 c = '\n';
5178 }else if( c=='v' ){
5179 c = '\v';
5180 }else if( c=='f' ){
5181 c = '\f';
5182 }else if( c=='r' ){
5183 c = '\r';
5184 }else if( c=='"' ){
5185 c = '"';
5186 }else if( c=='\'' ){
5187 c = '\'';
5188 }else if( c=='\\' ){
5189 c = '\\';
5190 }else if( c>='0' && c<='7' ){
5191 c -= '0';
5192 if( z[i+1]>='0' && z[i+1]<='7' ){
5193 i++;
5194 c = (c<<3) + z[i] - '0';
5195 if( z[i+1]>='0' && z[i+1]<='7' ){
5196 i++;
5197 c = (c<<3) + z[i] - '0';
5198 }
5199 }
5200 }
5201 }
5202 z[j] = c;
5203 }
5204 if( j<i ) z[j] = 0;
5205}
5206
5207/*
drh2ce15c32017-07-11 13:34:40 +00005208** Interpret zArg as either an integer or a boolean value. Return 1 or 0
5209** for TRUE and FALSE. Return the integer value if appropriate.
5210*/
5211static int booleanValue(const char *zArg){
5212 int i;
5213 if( zArg[0]=='0' && zArg[1]=='x' ){
5214 for(i=2; hexDigitValue(zArg[i])>=0; i++){}
5215 }else{
5216 for(i=0; zArg[i]>='0' && zArg[i]<='9'; i++){}
5217 }
5218 if( i>0 && zArg[i]==0 ) return (int)(integerValue(zArg) & 0xffffffff);
5219 if( sqlite3_stricmp(zArg, "on")==0 || sqlite3_stricmp(zArg,"yes")==0 ){
5220 return 1;
5221 }
5222 if( sqlite3_stricmp(zArg, "off")==0 || sqlite3_stricmp(zArg,"no")==0 ){
5223 return 0;
5224 }
5225 utf8_printf(stderr, "ERROR: Not a boolean value: \"%s\". Assuming \"no\".\n",
5226 zArg);
5227 return 0;
5228}
5229
5230/*
5231** Set or clear a shell flag according to a boolean value.
5232*/
5233static void setOrClearFlag(ShellState *p, unsigned mFlag, const char *zArg){
5234 if( booleanValue(zArg) ){
5235 ShellSetFlag(p, mFlag);
5236 }else{
5237 ShellClearFlag(p, mFlag);
5238 }
5239}
5240
5241/*
5242** Close an output file, assuming it is not stderr or stdout
5243*/
5244static void output_file_close(FILE *f){
5245 if( f && f!=stdout && f!=stderr ) fclose(f);
5246}
5247
5248/*
5249** Try to open an output file. The names "stdout" and "stderr" are
5250** recognized and do the right thing. NULL is returned if the output
5251** filename is "off".
5252*/
drha92a01a2018-01-10 22:15:37 +00005253static FILE *output_file_open(const char *zFile, int bTextMode){
drh2ce15c32017-07-11 13:34:40 +00005254 FILE *f;
5255 if( strcmp(zFile,"stdout")==0 ){
5256 f = stdout;
5257 }else if( strcmp(zFile, "stderr")==0 ){
5258 f = stderr;
5259 }else if( strcmp(zFile, "off")==0 ){
5260 f = 0;
5261 }else{
drha92a01a2018-01-10 22:15:37 +00005262 f = fopen(zFile, bTextMode ? "w" : "wb");
drh2ce15c32017-07-11 13:34:40 +00005263 if( f==0 ){
5264 utf8_printf(stderr, "Error: cannot open \"%s\"\n", zFile);
5265 }
5266 }
5267 return f;
5268}
5269
drh707821f2018-12-05 13:39:06 +00005270#ifndef SQLITE_OMIT_TRACE
drh2ce15c32017-07-11 13:34:40 +00005271/*
5272** A routine for handling output from sqlite3_trace().
5273*/
5274static int sql_trace_callback(
drh707821f2018-12-05 13:39:06 +00005275 unsigned mType, /* The trace type */
5276 void *pArg, /* The ShellState pointer */
5277 void *pP, /* Usually a pointer to sqlite_stmt */
5278 void *pX /* Auxiliary output */
drh2ce15c32017-07-11 13:34:40 +00005279){
drh707821f2018-12-05 13:39:06 +00005280 ShellState *p = (ShellState*)pArg;
5281 sqlite3_stmt *pStmt;
5282 const char *zSql;
5283 int nSql;
5284 if( p->traceOut==0 ) return 0;
5285 if( mType==SQLITE_TRACE_CLOSE ){
5286 utf8_printf(p->traceOut, "-- closing database connection\n");
5287 return 0;
5288 }
5289 if( mType!=SQLITE_TRACE_ROW && ((const char*)pX)[0]=='-' ){
5290 zSql = (const char*)pX;
5291 }else{
5292 pStmt = (sqlite3_stmt*)pP;
5293 switch( p->eTraceType ){
5294 case SHELL_TRACE_EXPANDED: {
5295 zSql = sqlite3_expanded_sql(pStmt);
5296 break;
5297 }
5298#ifdef SQLITE_ENABLE_NORMALIZE
5299 case SHELL_TRACE_NORMALIZED: {
5300 zSql = sqlite3_normalized_sql(pStmt);
5301 break;
5302 }
5303#endif
5304 default: {
5305 zSql = sqlite3_sql(pStmt);
5306 break;
5307 }
5308 }
5309 }
5310 if( zSql==0 ) return 0;
5311 nSql = strlen30(zSql);
5312 while( nSql>0 && zSql[nSql-1]==';' ){ nSql--; }
5313 switch( mType ){
5314 case SQLITE_TRACE_ROW:
5315 case SQLITE_TRACE_STMT: {
5316 utf8_printf(p->traceOut, "%.*s;\n", nSql, zSql);
5317 break;
5318 }
5319 case SQLITE_TRACE_PROFILE: {
5320 sqlite3_int64 nNanosec = *(sqlite3_int64*)pX;
5321 utf8_printf(p->traceOut, "%.*s; -- %lld ns\n", nSql, zSql, nNanosec);
5322 break;
5323 }
drh2ce15c32017-07-11 13:34:40 +00005324 }
5325 return 0;
5326}
5327#endif
drh2ce15c32017-07-11 13:34:40 +00005328
5329/*
5330** A no-op routine that runs with the ".breakpoint" doc-command. This is
5331** a useful spot to set a debugger breakpoint.
5332*/
5333static void test_breakpoint(void){
5334 static int nCall = 0;
5335 nCall++;
5336}
5337
5338/*
5339** An object used to read a CSV and other files for import.
5340*/
5341typedef struct ImportCtx ImportCtx;
5342struct ImportCtx {
5343 const char *zFile; /* Name of the input file */
5344 FILE *in; /* Read the CSV text from this input stream */
drh97767842020-05-29 19:39:35 +00005345 int (SQLITE_CDECL *xCloser)(FILE*); /* Func to close in */
drh2ce15c32017-07-11 13:34:40 +00005346 char *z; /* Accumulated text for a field */
5347 int n; /* Number of bytes in z */
5348 int nAlloc; /* Space allocated for z[] */
5349 int nLine; /* Current line number */
drhccb37812020-03-09 15:39:39 +00005350 int nRow; /* Number of rows imported */
5351 int nErr; /* Number of errors encountered */
drh2ce15c32017-07-11 13:34:40 +00005352 int bNotFirst; /* True if one or more bytes already read */
5353 int cTerm; /* Character that terminated the most recent field */
5354 int cColSep; /* The column separator character. (Usually ",") */
5355 int cRowSep; /* The row separator character. (Usually "\n") */
5356};
5357
drh97767842020-05-29 19:39:35 +00005358/* Clean up resourced used by an ImportCtx */
5359static void import_cleanup(ImportCtx *p){
drh42c2a042020-05-29 20:16:19 +00005360 if( p->in!=0 && p->xCloser!=0 ){
drh97767842020-05-29 19:39:35 +00005361 p->xCloser(p->in);
5362 p->in = 0;
5363 }
5364 sqlite3_free(p->z);
5365 p->z = 0;
5366}
5367
drh2ce15c32017-07-11 13:34:40 +00005368/* Append a single byte to z[] */
5369static void import_append_char(ImportCtx *p, int c){
5370 if( p->n+1>=p->nAlloc ){
5371 p->nAlloc += p->nAlloc + 100;
5372 p->z = sqlite3_realloc64(p->z, p->nAlloc);
drhe3e25652021-12-16 13:29:28 +00005373 shell_check_oom(p->z);
drh2ce15c32017-07-11 13:34:40 +00005374 }
5375 p->z[p->n++] = (char)c;
5376}
5377
5378/* Read a single field of CSV text. Compatible with rfc4180 and extended
5379** with the option of having a separator other than ",".
5380**
5381** + Input comes from p->in.
5382** + Store results in p->z of length p->n. Space to hold p->z comes
5383** from sqlite3_malloc64().
5384** + Use p->cSep as the column separator. The default is ",".
5385** + Use p->rSep as the row separator. The default is "\n".
5386** + Keep track of the line number in p->nLine.
5387** + Store the character that terminates the field in p->cTerm. Store
5388** EOF on end-of-file.
5389** + Report syntax errors on stderr
5390*/
5391static char *SQLITE_CDECL csv_read_one_field(ImportCtx *p){
5392 int c;
5393 int cSep = p->cColSep;
5394 int rSep = p->cRowSep;
5395 p->n = 0;
5396 c = fgetc(p->in);
5397 if( c==EOF || seenInterrupt ){
5398 p->cTerm = EOF;
5399 return 0;
5400 }
5401 if( c=='"' ){
5402 int pc, ppc;
5403 int startLine = p->nLine;
5404 int cQuote = c;
5405 pc = ppc = 0;
5406 while( 1 ){
5407 c = fgetc(p->in);
5408 if( c==rSep ) p->nLine++;
5409 if( c==cQuote ){
5410 if( pc==cQuote ){
5411 pc = 0;
5412 continue;
5413 }
5414 }
5415 if( (c==cSep && pc==cQuote)
5416 || (c==rSep && pc==cQuote)
5417 || (c==rSep && pc=='\r' && ppc==cQuote)
5418 || (c==EOF && pc==cQuote)
5419 ){
5420 do{ p->n--; }while( p->z[p->n]!=cQuote );
5421 p->cTerm = c;
5422 break;
5423 }
5424 if( pc==cQuote && c!='\r' ){
5425 utf8_printf(stderr, "%s:%d: unescaped %c character\n",
5426 p->zFile, p->nLine, cQuote);
5427 }
5428 if( c==EOF ){
5429 utf8_printf(stderr, "%s:%d: unterminated %c-quoted field\n",
5430 p->zFile, startLine, cQuote);
5431 p->cTerm = c;
5432 break;
5433 }
5434 import_append_char(p, c);
5435 ppc = pc;
5436 pc = c;
5437 }
5438 }else{
5439 /* If this is the first field being parsed and it begins with the
5440 ** UTF-8 BOM (0xEF BB BF) then skip the BOM */
5441 if( (c&0xff)==0xef && p->bNotFirst==0 ){
5442 import_append_char(p, c);
5443 c = fgetc(p->in);
5444 if( (c&0xff)==0xbb ){
5445 import_append_char(p, c);
5446 c = fgetc(p->in);
5447 if( (c&0xff)==0xbf ){
5448 p->bNotFirst = 1;
5449 p->n = 0;
5450 return csv_read_one_field(p);
5451 }
5452 }
5453 }
5454 while( c!=EOF && c!=cSep && c!=rSep ){
5455 import_append_char(p, c);
5456 c = fgetc(p->in);
5457 }
5458 if( c==rSep ){
5459 p->nLine++;
5460 if( p->n>0 && p->z[p->n-1]=='\r' ) p->n--;
5461 }
5462 p->cTerm = c;
5463 }
5464 if( p->z ) p->z[p->n] = 0;
5465 p->bNotFirst = 1;
5466 return p->z;
5467}
5468
5469/* Read a single field of ASCII delimited text.
5470**
5471** + Input comes from p->in.
5472** + Store results in p->z of length p->n. Space to hold p->z comes
5473** from sqlite3_malloc64().
5474** + Use p->cSep as the column separator. The default is "\x1F".
5475** + Use p->rSep as the row separator. The default is "\x1E".
5476** + Keep track of the row number in p->nLine.
5477** + Store the character that terminates the field in p->cTerm. Store
5478** EOF on end-of-file.
5479** + Report syntax errors on stderr
5480*/
5481static char *SQLITE_CDECL ascii_read_one_field(ImportCtx *p){
5482 int c;
5483 int cSep = p->cColSep;
5484 int rSep = p->cRowSep;
5485 p->n = 0;
5486 c = fgetc(p->in);
5487 if( c==EOF || seenInterrupt ){
5488 p->cTerm = EOF;
5489 return 0;
5490 }
5491 while( c!=EOF && c!=cSep && c!=rSep ){
5492 import_append_char(p, c);
5493 c = fgetc(p->in);
5494 }
5495 if( c==rSep ){
5496 p->nLine++;
5497 }
5498 p->cTerm = c;
5499 if( p->z ) p->z[p->n] = 0;
5500 return p->z;
5501}
5502
5503/*
5504** Try to transfer data for table zTable. If an error is seen while
5505** moving forward, try to go backwards. The backwards movement won't
5506** work for WITHOUT ROWID tables.
5507*/
5508static void tryToCloneData(
5509 ShellState *p,
5510 sqlite3 *newDb,
5511 const char *zTable
5512){
5513 sqlite3_stmt *pQuery = 0;
5514 sqlite3_stmt *pInsert = 0;
5515 char *zQuery = 0;
5516 char *zInsert = 0;
5517 int rc;
5518 int i, j, n;
drhaf2770f2018-01-05 14:55:43 +00005519 int nTable = strlen30(zTable);
drh2ce15c32017-07-11 13:34:40 +00005520 int k = 0;
5521 int cnt = 0;
5522 const int spinRate = 10000;
5523
5524 zQuery = sqlite3_mprintf("SELECT * FROM \"%w\"", zTable);
drhe3e25652021-12-16 13:29:28 +00005525 shell_check_oom(zQuery);
drh2ce15c32017-07-11 13:34:40 +00005526 rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
5527 if( rc ){
5528 utf8_printf(stderr, "Error %d: %s on [%s]\n",
5529 sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db),
5530 zQuery);
5531 goto end_data_xfer;
5532 }
5533 n = sqlite3_column_count(pQuery);
5534 zInsert = sqlite3_malloc64(200 + nTable + n*3);
drhe3e25652021-12-16 13:29:28 +00005535 shell_check_oom(zInsert);
drh2ce15c32017-07-11 13:34:40 +00005536 sqlite3_snprintf(200+nTable,zInsert,
5537 "INSERT OR IGNORE INTO \"%s\" VALUES(?", zTable);
drhaf2770f2018-01-05 14:55:43 +00005538 i = strlen30(zInsert);
drh2ce15c32017-07-11 13:34:40 +00005539 for(j=1; j<n; j++){
5540 memcpy(zInsert+i, ",?", 2);
5541 i += 2;
5542 }
5543 memcpy(zInsert+i, ");", 3);
5544 rc = sqlite3_prepare_v2(newDb, zInsert, -1, &pInsert, 0);
5545 if( rc ){
5546 utf8_printf(stderr, "Error %d: %s on [%s]\n",
5547 sqlite3_extended_errcode(newDb), sqlite3_errmsg(newDb),
5548 zQuery);
5549 goto end_data_xfer;
5550 }
5551 for(k=0; k<2; k++){
5552 while( (rc = sqlite3_step(pQuery))==SQLITE_ROW ){
5553 for(i=0; i<n; i++){
5554 switch( sqlite3_column_type(pQuery, i) ){
5555 case SQLITE_NULL: {
5556 sqlite3_bind_null(pInsert, i+1);
5557 break;
5558 }
5559 case SQLITE_INTEGER: {
5560 sqlite3_bind_int64(pInsert, i+1, sqlite3_column_int64(pQuery,i));
5561 break;
5562 }
5563 case SQLITE_FLOAT: {
5564 sqlite3_bind_double(pInsert, i+1, sqlite3_column_double(pQuery,i));
5565 break;
5566 }
5567 case SQLITE_TEXT: {
5568 sqlite3_bind_text(pInsert, i+1,
5569 (const char*)sqlite3_column_text(pQuery,i),
5570 -1, SQLITE_STATIC);
5571 break;
5572 }
5573 case SQLITE_BLOB: {
5574 sqlite3_bind_blob(pInsert, i+1, sqlite3_column_blob(pQuery,i),
5575 sqlite3_column_bytes(pQuery,i),
5576 SQLITE_STATIC);
5577 break;
5578 }
5579 }
5580 } /* End for */
5581 rc = sqlite3_step(pInsert);
5582 if( rc!=SQLITE_OK && rc!=SQLITE_ROW && rc!=SQLITE_DONE ){
5583 utf8_printf(stderr, "Error %d: %s\n", sqlite3_extended_errcode(newDb),
5584 sqlite3_errmsg(newDb));
5585 }
5586 sqlite3_reset(pInsert);
5587 cnt++;
5588 if( (cnt%spinRate)==0 ){
5589 printf("%c\b", "|/-\\"[(cnt/spinRate)%4]);
5590 fflush(stdout);
5591 }
5592 } /* End while */
5593 if( rc==SQLITE_DONE ) break;
5594 sqlite3_finalize(pQuery);
5595 sqlite3_free(zQuery);
5596 zQuery = sqlite3_mprintf("SELECT * FROM \"%w\" ORDER BY rowid DESC;",
5597 zTable);
drhe3e25652021-12-16 13:29:28 +00005598 shell_check_oom(zQuery);
drh2ce15c32017-07-11 13:34:40 +00005599 rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
5600 if( rc ){
5601 utf8_printf(stderr, "Warning: cannot step \"%s\" backwards", zTable);
5602 break;
5603 }
5604 } /* End for(k=0...) */
5605
5606end_data_xfer:
5607 sqlite3_finalize(pQuery);
5608 sqlite3_finalize(pInsert);
5609 sqlite3_free(zQuery);
5610 sqlite3_free(zInsert);
5611}
5612
5613
5614/*
5615** Try to transfer all rows of the schema that match zWhere. For
5616** each row, invoke xForEach() on the object defined by that row.
5617** If an error is encountered while moving forward through the
drh067b92b2020-06-19 15:24:12 +00005618** sqlite_schema table, try again moving backwards.
drh2ce15c32017-07-11 13:34:40 +00005619*/
5620static void tryToCloneSchema(
5621 ShellState *p,
5622 sqlite3 *newDb,
5623 const char *zWhere,
5624 void (*xForEach)(ShellState*,sqlite3*,const char*)
5625){
5626 sqlite3_stmt *pQuery = 0;
5627 char *zQuery = 0;
5628 int rc;
5629 const unsigned char *zName;
5630 const unsigned char *zSql;
5631 char *zErrMsg = 0;
5632
drh067b92b2020-06-19 15:24:12 +00005633 zQuery = sqlite3_mprintf("SELECT name, sql FROM sqlite_schema"
drh2ce15c32017-07-11 13:34:40 +00005634 " WHERE %s", zWhere);
drhe3e25652021-12-16 13:29:28 +00005635 shell_check_oom(zQuery);
drh2ce15c32017-07-11 13:34:40 +00005636 rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
5637 if( rc ){
5638 utf8_printf(stderr, "Error: (%d) %s on [%s]\n",
5639 sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db),
5640 zQuery);
5641 goto end_schema_xfer;
5642 }
5643 while( (rc = sqlite3_step(pQuery))==SQLITE_ROW ){
5644 zName = sqlite3_column_text(pQuery, 0);
5645 zSql = sqlite3_column_text(pQuery, 1);
drh621a5e02021-12-16 17:35:27 +00005646 if( zName==0 || zSql==0 ) continue;
drh2ce15c32017-07-11 13:34:40 +00005647 printf("%s... ", zName); fflush(stdout);
5648 sqlite3_exec(newDb, (const char*)zSql, 0, 0, &zErrMsg);
5649 if( zErrMsg ){
5650 utf8_printf(stderr, "Error: %s\nSQL: [%s]\n", zErrMsg, zSql);
5651 sqlite3_free(zErrMsg);
5652 zErrMsg = 0;
5653 }
5654 if( xForEach ){
5655 xForEach(p, newDb, (const char*)zName);
5656 }
5657 printf("done\n");
5658 }
5659 if( rc!=SQLITE_DONE ){
5660 sqlite3_finalize(pQuery);
5661 sqlite3_free(zQuery);
drh067b92b2020-06-19 15:24:12 +00005662 zQuery = sqlite3_mprintf("SELECT name, sql FROM sqlite_schema"
drh2ce15c32017-07-11 13:34:40 +00005663 " WHERE %s ORDER BY rowid DESC", zWhere);
drhe3e25652021-12-16 13:29:28 +00005664 shell_check_oom(zQuery);
drh2ce15c32017-07-11 13:34:40 +00005665 rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
5666 if( rc ){
5667 utf8_printf(stderr, "Error: (%d) %s on [%s]\n",
5668 sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db),
5669 zQuery);
5670 goto end_schema_xfer;
5671 }
drh76fc88f2021-10-02 16:39:16 +00005672 while( sqlite3_step(pQuery)==SQLITE_ROW ){
drh2ce15c32017-07-11 13:34:40 +00005673 zName = sqlite3_column_text(pQuery, 0);
5674 zSql = sqlite3_column_text(pQuery, 1);
drh621a5e02021-12-16 17:35:27 +00005675 if( zName==0 || zSql==0 ) continue;
drh2ce15c32017-07-11 13:34:40 +00005676 printf("%s... ", zName); fflush(stdout);
5677 sqlite3_exec(newDb, (const char*)zSql, 0, 0, &zErrMsg);
5678 if( zErrMsg ){
5679 utf8_printf(stderr, "Error: %s\nSQL: [%s]\n", zErrMsg, zSql);
5680 sqlite3_free(zErrMsg);
5681 zErrMsg = 0;
5682 }
5683 if( xForEach ){
5684 xForEach(p, newDb, (const char*)zName);
5685 }
5686 printf("done\n");
5687 }
5688 }
5689end_schema_xfer:
5690 sqlite3_finalize(pQuery);
5691 sqlite3_free(zQuery);
5692}
5693
5694/*
5695** Open a new database file named "zNewDb". Try to recover as much information
5696** as possible out of the main database (which might be corrupt) and write it
5697** into zNewDb.
5698*/
5699static void tryToClone(ShellState *p, const char *zNewDb){
5700 int rc;
5701 sqlite3 *newDb = 0;
5702 if( access(zNewDb,0)==0 ){
5703 utf8_printf(stderr, "File \"%s\" already exists.\n", zNewDb);
5704 return;
5705 }
5706 rc = sqlite3_open(zNewDb, &newDb);
5707 if( rc ){
5708 utf8_printf(stderr, "Cannot create output database: %s\n",
5709 sqlite3_errmsg(newDb));
5710 }else{
5711 sqlite3_exec(p->db, "PRAGMA writable_schema=ON;", 0, 0, 0);
5712 sqlite3_exec(newDb, "BEGIN EXCLUSIVE;", 0, 0, 0);
5713 tryToCloneSchema(p, newDb, "type='table'", tryToCloneData);
5714 tryToCloneSchema(p, newDb, "type!='table'", 0);
5715 sqlite3_exec(newDb, "COMMIT;", 0, 0, 0);
5716 sqlite3_exec(p->db, "PRAGMA writable_schema=OFF;", 0, 0, 0);
5717 }
drh9e804032018-05-18 17:11:50 +00005718 close_db(newDb);
drh2ce15c32017-07-11 13:34:40 +00005719}
5720
5721/*
drh13c20932018-01-10 21:41:55 +00005722** Change the output file back to stdout.
5723**
5724** If the p->doXdgOpen flag is set, that means the output was being
5725** redirected to a temporary file named by p->zTempFile. In that case,
5726** launch start/open/xdg-open on that temporary file.
drh2ce15c32017-07-11 13:34:40 +00005727*/
5728static void output_reset(ShellState *p){
5729 if( p->outfile[0]=='|' ){
5730#ifndef SQLITE_OMIT_POPEN
5731 pclose(p->out);
5732#endif
5733 }else{
5734 output_file_close(p->out);
drh04a28c32018-01-31 01:38:44 +00005735#ifndef SQLITE_NOHAVE_SYSTEM
drh13c20932018-01-10 21:41:55 +00005736 if( p->doXdgOpen ){
5737 const char *zXdgOpenCmd =
5738#if defined(_WIN32)
5739 "start";
5740#elif defined(__APPLE__)
5741 "open";
5742#else
5743 "xdg-open";
5744#endif
5745 char *zCmd;
5746 zCmd = sqlite3_mprintf("%s %s", zXdgOpenCmd, p->zTempFile);
drha92a01a2018-01-10 22:15:37 +00005747 if( system(zCmd) ){
5748 utf8_printf(stderr, "Failed: [%s]\n", zCmd);
drh1d9ea272020-04-17 23:46:54 +00005749 }else{
5750 /* Give the start/open/xdg-open command some time to get
5751 ** going before we continue, and potential delete the
5752 ** p->zTempFile data file out from under it */
5753 sqlite3_sleep(2000);
drha92a01a2018-01-10 22:15:37 +00005754 }
drh13c20932018-01-10 21:41:55 +00005755 sqlite3_free(zCmd);
drh3c484e82018-01-10 22:27:21 +00005756 outputModePop(p);
drh13c20932018-01-10 21:41:55 +00005757 p->doXdgOpen = 0;
5758 }
drh04a28c32018-01-31 01:38:44 +00005759#endif /* !defined(SQLITE_NOHAVE_SYSTEM) */
drh2ce15c32017-07-11 13:34:40 +00005760 }
5761 p->outfile[0] = 0;
5762 p->out = stdout;
5763}
5764
5765/*
5766** Run an SQL command and return the single integer result.
5767*/
larrybr58a53d62022-02-10 03:21:48 +00005768static int db_int(sqlite3 *db, const char *zSql){
drh2ce15c32017-07-11 13:34:40 +00005769 sqlite3_stmt *pStmt;
5770 int res = 0;
larrybr58a53d62022-02-10 03:21:48 +00005771 sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
drh2ce15c32017-07-11 13:34:40 +00005772 if( pStmt && sqlite3_step(pStmt)==SQLITE_ROW ){
5773 res = sqlite3_column_int(pStmt,0);
5774 }
5775 sqlite3_finalize(pStmt);
5776 return res;
5777}
5778
5779/*
5780** Convert a 2-byte or 4-byte big-endian integer into a native integer
5781*/
5782static unsigned int get2byteInt(unsigned char *a){
5783 return (a[0]<<8) + a[1];
5784}
5785static unsigned int get4byteInt(unsigned char *a){
5786 return (a[0]<<24) + (a[1]<<16) + (a[2]<<8) + a[3];
5787}
5788
5789/*
drh76c12062020-01-14 13:13:19 +00005790** Implementation of the ".dbinfo" command.
drh2ce15c32017-07-11 13:34:40 +00005791**
5792** Return 1 on error, 2 to exit, and 0 otherwise.
5793*/
5794static int shell_dbinfo_command(ShellState *p, int nArg, char **azArg){
5795 static const struct { const char *zName; int ofst; } aField[] = {
5796 { "file change counter:", 24 },
5797 { "database page count:", 28 },
5798 { "freelist page count:", 36 },
5799 { "schema cookie:", 40 },
5800 { "schema format:", 44 },
5801 { "default cache size:", 48 },
5802 { "autovacuum top root:", 52 },
5803 { "incremental vacuum:", 64 },
5804 { "text encoding:", 56 },
5805 { "user version:", 60 },
5806 { "application id:", 68 },
5807 { "software version:", 96 },
5808 };
5809 static const struct { const char *zName; const char *zSql; } aQuery[] = {
5810 { "number of tables:",
5811 "SELECT count(*) FROM %s WHERE type='table'" },
5812 { "number of indexes:",
5813 "SELECT count(*) FROM %s WHERE type='index'" },
5814 { "number of triggers:",
5815 "SELECT count(*) FROM %s WHERE type='trigger'" },
5816 { "number of views:",
5817 "SELECT count(*) FROM %s WHERE type='view'" },
5818 { "schema size:",
5819 "SELECT total(length(sql)) FROM %s" },
5820 };
drh87c889c2019-03-20 18:22:51 +00005821 int i, rc;
drhea99a312018-07-18 19:09:07 +00005822 unsigned iDataVersion;
drh2ce15c32017-07-11 13:34:40 +00005823 char *zSchemaTab;
5824 char *zDb = nArg>=2 ? azArg[1] : "main";
drh512e6c32017-10-11 17:51:08 +00005825 sqlite3_stmt *pStmt = 0;
drh2ce15c32017-07-11 13:34:40 +00005826 unsigned char aHdr[100];
5827 open_db(p, 0);
5828 if( p->db==0 ) return 1;
drh87c889c2019-03-20 18:22:51 +00005829 rc = sqlite3_prepare_v2(p->db,
5830 "SELECT data FROM sqlite_dbpage(?1) WHERE pgno=1",
5831 -1, &pStmt, 0);
5832 if( rc ){
drh451f89a2020-04-28 23:09:56 +00005833 utf8_printf(stderr, "error: %s\n", sqlite3_errmsg(p->db));
drh87c889c2019-03-20 18:22:51 +00005834 sqlite3_finalize(pStmt);
5835 return 1;
5836 }
drh512e6c32017-10-11 17:51:08 +00005837 sqlite3_bind_text(pStmt, 1, zDb, -1, SQLITE_STATIC);
5838 if( sqlite3_step(pStmt)==SQLITE_ROW
5839 && sqlite3_column_bytes(pStmt,0)>100
5840 ){
5841 memcpy(aHdr, sqlite3_column_blob(pStmt,0), 100);
5842 sqlite3_finalize(pStmt);
5843 }else{
drh2ce15c32017-07-11 13:34:40 +00005844 raw_printf(stderr, "unable to read database header\n");
drh512e6c32017-10-11 17:51:08 +00005845 sqlite3_finalize(pStmt);
drh2ce15c32017-07-11 13:34:40 +00005846 return 1;
5847 }
5848 i = get2byteInt(aHdr+16);
5849 if( i==1 ) i = 65536;
5850 utf8_printf(p->out, "%-20s %d\n", "database page size:", i);
5851 utf8_printf(p->out, "%-20s %d\n", "write format:", aHdr[18]);
5852 utf8_printf(p->out, "%-20s %d\n", "read format:", aHdr[19]);
5853 utf8_printf(p->out, "%-20s %d\n", "reserved bytes:", aHdr[20]);
5854 for(i=0; i<ArraySize(aField); i++){
5855 int ofst = aField[i].ofst;
5856 unsigned int val = get4byteInt(aHdr + ofst);
5857 utf8_printf(p->out, "%-20s %u", aField[i].zName, val);
5858 switch( ofst ){
5859 case 56: {
5860 if( val==1 ) raw_printf(p->out, " (utf8)");
5861 if( val==2 ) raw_printf(p->out, " (utf16le)");
5862 if( val==3 ) raw_printf(p->out, " (utf16be)");
5863 }
5864 }
5865 raw_printf(p->out, "\n");
5866 }
5867 if( zDb==0 ){
drh067b92b2020-06-19 15:24:12 +00005868 zSchemaTab = sqlite3_mprintf("main.sqlite_schema");
drh2ce15c32017-07-11 13:34:40 +00005869 }else if( strcmp(zDb,"temp")==0 ){
drh067b92b2020-06-19 15:24:12 +00005870 zSchemaTab = sqlite3_mprintf("%s", "sqlite_temp_schema");
drh2ce15c32017-07-11 13:34:40 +00005871 }else{
drh067b92b2020-06-19 15:24:12 +00005872 zSchemaTab = sqlite3_mprintf("\"%w\".sqlite_schema", zDb);
drh2ce15c32017-07-11 13:34:40 +00005873 }
5874 for(i=0; i<ArraySize(aQuery); i++){
5875 char *zSql = sqlite3_mprintf(aQuery[i].zSql, zSchemaTab);
larrybr58a53d62022-02-10 03:21:48 +00005876 int val = db_int(p->db, zSql);
drh2ce15c32017-07-11 13:34:40 +00005877 sqlite3_free(zSql);
5878 utf8_printf(p->out, "%-20s %d\n", aQuery[i].zName, val);
5879 }
5880 sqlite3_free(zSchemaTab);
drhea99a312018-07-18 19:09:07 +00005881 sqlite3_file_control(p->db, zDb, SQLITE_FCNTL_DATA_VERSION, &iDataVersion);
5882 utf8_printf(p->out, "%-20s %u\n", "data version", iDataVersion);
drh2ce15c32017-07-11 13:34:40 +00005883 return 0;
5884}
5885
5886/*
5887** Print the current sqlite3_errmsg() value to stderr and return 1.
5888*/
5889static int shellDatabaseError(sqlite3 *db){
5890 const char *zErr = sqlite3_errmsg(db);
5891 utf8_printf(stderr, "Error: %s\n", zErr);
5892 return 1;
5893}
5894
5895/*
drh2ce15c32017-07-11 13:34:40 +00005896** Compare the pattern in zGlob[] against the text in z[]. Return TRUE
5897** if they match and FALSE (0) if they do not match.
5898**
5899** Globbing rules:
5900**
5901** '*' Matches any sequence of zero or more characters.
5902**
5903** '?' Matches exactly one character.
5904**
5905** [...] Matches one character from the enclosed list of
5906** characters.
5907**
5908** [^...] Matches one character not in the enclosed list.
5909**
5910** '#' Matches any sequence of one or more digits with an
5911** optional + or - sign in front
5912**
5913** ' ' Any span of whitespace matches any other span of
5914** whitespace.
5915**
5916** Extra whitespace at the end of z[] is ignored.
5917*/
5918static int testcase_glob(const char *zGlob, const char *z){
5919 int c, c2;
5920 int invert;
5921 int seen;
5922
5923 while( (c = (*(zGlob++)))!=0 ){
5924 if( IsSpace(c) ){
5925 if( !IsSpace(*z) ) return 0;
5926 while( IsSpace(*zGlob) ) zGlob++;
5927 while( IsSpace(*z) ) z++;
5928 }else if( c=='*' ){
5929 while( (c=(*(zGlob++))) == '*' || c=='?' ){
5930 if( c=='?' && (*(z++))==0 ) return 0;
5931 }
5932 if( c==0 ){
5933 return 1;
5934 }else if( c=='[' ){
5935 while( *z && testcase_glob(zGlob-1,z)==0 ){
5936 z++;
5937 }
5938 return (*z)!=0;
5939 }
5940 while( (c2 = (*(z++)))!=0 ){
5941 while( c2!=c ){
5942 c2 = *(z++);
5943 if( c2==0 ) return 0;
5944 }
5945 if( testcase_glob(zGlob,z) ) return 1;
5946 }
5947 return 0;
5948 }else if( c=='?' ){
5949 if( (*(z++))==0 ) return 0;
5950 }else if( c=='[' ){
5951 int prior_c = 0;
5952 seen = 0;
5953 invert = 0;
5954 c = *(z++);
5955 if( c==0 ) return 0;
5956 c2 = *(zGlob++);
5957 if( c2=='^' ){
5958 invert = 1;
5959 c2 = *(zGlob++);
5960 }
5961 if( c2==']' ){
5962 if( c==']' ) seen = 1;
5963 c2 = *(zGlob++);
5964 }
5965 while( c2 && c2!=']' ){
5966 if( c2=='-' && zGlob[0]!=']' && zGlob[0]!=0 && prior_c>0 ){
5967 c2 = *(zGlob++);
5968 if( c>=prior_c && c<=c2 ) seen = 1;
5969 prior_c = 0;
5970 }else{
5971 if( c==c2 ){
5972 seen = 1;
5973 }
5974 prior_c = c2;
5975 }
5976 c2 = *(zGlob++);
5977 }
5978 if( c2==0 || (seen ^ invert)==0 ) return 0;
5979 }else if( c=='#' ){
5980 if( (z[0]=='-' || z[0]=='+') && IsDigit(z[1]) ) z++;
5981 if( !IsDigit(z[0]) ) return 0;
5982 z++;
5983 while( IsDigit(z[0]) ){ z++; }
5984 }else{
5985 if( c!=(*(z++)) ) return 0;
5986 }
5987 }
5988 while( IsSpace(*z) ){ z++; }
5989 return *z==0;
5990}
5991
5992
5993/*
5994** Compare the string as a command-line option with either one or two
5995** initial "-" characters.
5996*/
5997static int optionMatch(const char *zStr, const char *zOpt){
5998 if( zStr[0]!='-' ) return 0;
5999 zStr++;
6000 if( zStr[0]=='-' ) zStr++;
6001 return strcmp(zStr, zOpt)==0;
6002}
6003
6004/*
6005** Delete a file.
6006*/
6007int shellDeleteFile(const char *zFilename){
6008 int rc;
6009#ifdef _WIN32
6010 wchar_t *z = sqlite3_win32_utf8_to_unicode(zFilename);
6011 rc = _wunlink(z);
6012 sqlite3_free(z);
6013#else
6014 rc = unlink(zFilename);
6015#endif
6016 return rc;
6017}
6018
drh13c20932018-01-10 21:41:55 +00006019/*
6020** Try to delete the temporary file (if there is one) and free the
6021** memory used to hold the name of the temp file.
6022*/
6023static void clearTempFile(ShellState *p){
6024 if( p->zTempFile==0 ) return;
drh536c3452018-01-11 00:38:39 +00006025 if( p->doXdgOpen ) return;
drh13c20932018-01-10 21:41:55 +00006026 if( shellDeleteFile(p->zTempFile) ) return;
6027 sqlite3_free(p->zTempFile);
6028 p->zTempFile = 0;
6029}
6030
6031/*
6032** Create a new temp file name with the given suffix.
6033*/
6034static void newTempFile(ShellState *p, const char *zSuffix){
6035 clearTempFile(p);
6036 sqlite3_free(p->zTempFile);
6037 p->zTempFile = 0;
drh7f3bf8a2018-01-10 21:50:08 +00006038 if( p->db ){
6039 sqlite3_file_control(p->db, 0, SQLITE_FCNTL_TEMPFILENAME, &p->zTempFile);
6040 }
drh13c20932018-01-10 21:41:55 +00006041 if( p->zTempFile==0 ){
drh1d9ea272020-04-17 23:46:54 +00006042 /* If p->db is an in-memory database then the TEMPFILENAME file-control
6043 ** will not work and we will need to fallback to guessing */
6044 char *zTemp;
drh13c20932018-01-10 21:41:55 +00006045 sqlite3_uint64 r;
6046 sqlite3_randomness(sizeof(r), &r);
drh1d9ea272020-04-17 23:46:54 +00006047 zTemp = getenv("TEMP");
6048 if( zTemp==0 ) zTemp = getenv("TMP");
6049 if( zTemp==0 ){
6050#ifdef _WIN32
6051 zTemp = "\\tmp";
6052#else
6053 zTemp = "/tmp";
6054#endif
6055 }
6056 p->zTempFile = sqlite3_mprintf("%s/temp%llx.%s", zTemp, r, zSuffix);
drh13c20932018-01-10 21:41:55 +00006057 }else{
6058 p->zTempFile = sqlite3_mprintf("%z.%s", p->zTempFile, zSuffix);
6059 }
drhe3e25652021-12-16 13:29:28 +00006060 shell_check_oom(p->zTempFile);
drh13c20932018-01-10 21:41:55 +00006061}
6062
drh2ce15c32017-07-11 13:34:40 +00006063
6064/*
6065** The implementation of SQL scalar function fkey_collate_clause(), used
6066** by the ".lint fkey-indexes" command. This scalar function is always
6067** called with four arguments - the parent table name, the parent column name,
6068** the child table name and the child column name.
6069**
6070** fkey_collate_clause('parent-tab', 'parent-col', 'child-tab', 'child-col')
6071**
6072** If either of the named tables or columns do not exist, this function
6073** returns an empty string. An empty string is also returned if both tables
6074** and columns exist but have the same default collation sequence. Or,
6075** if both exist but the default collation sequences are different, this
6076** function returns the string " COLLATE <parent-collation>", where
6077** <parent-collation> is the default collation sequence of the parent column.
6078*/
6079static void shellFkeyCollateClause(
6080 sqlite3_context *pCtx,
6081 int nVal,
6082 sqlite3_value **apVal
6083){
6084 sqlite3 *db = sqlite3_context_db_handle(pCtx);
6085 const char *zParent;
6086 const char *zParentCol;
6087 const char *zParentSeq;
6088 const char *zChild;
6089 const char *zChildCol;
6090 const char *zChildSeq = 0; /* Initialize to avoid false-positive warning */
6091 int rc;
6092
6093 assert( nVal==4 );
6094 zParent = (const char*)sqlite3_value_text(apVal[0]);
6095 zParentCol = (const char*)sqlite3_value_text(apVal[1]);
6096 zChild = (const char*)sqlite3_value_text(apVal[2]);
6097 zChildCol = (const char*)sqlite3_value_text(apVal[3]);
6098
6099 sqlite3_result_text(pCtx, "", -1, SQLITE_STATIC);
6100 rc = sqlite3_table_column_metadata(
6101 db, "main", zParent, zParentCol, 0, &zParentSeq, 0, 0, 0
6102 );
6103 if( rc==SQLITE_OK ){
6104 rc = sqlite3_table_column_metadata(
6105 db, "main", zChild, zChildCol, 0, &zChildSeq, 0, 0, 0
6106 );
6107 }
6108
6109 if( rc==SQLITE_OK && sqlite3_stricmp(zParentSeq, zChildSeq) ){
6110 char *z = sqlite3_mprintf(" COLLATE %s", zParentSeq);
6111 sqlite3_result_text(pCtx, z, -1, SQLITE_TRANSIENT);
6112 sqlite3_free(z);
6113 }
6114}
6115
6116
6117/*
6118** The implementation of dot-command ".lint fkey-indexes".
6119*/
6120static int lintFkeyIndexes(
6121 ShellState *pState, /* Current shell tool state */
6122 char **azArg, /* Array of arguments passed to dot command */
6123 int nArg /* Number of entries in azArg[] */
6124){
6125 sqlite3 *db = pState->db; /* Database handle to query "main" db of */
6126 FILE *out = pState->out; /* Stream to write non-error output to */
6127 int bVerbose = 0; /* If -verbose is present */
6128 int bGroupByParent = 0; /* If -groupbyparent is present */
6129 int i; /* To iterate through azArg[] */
6130 const char *zIndent = ""; /* How much to indent CREATE INDEX by */
6131 int rc; /* Return code */
6132 sqlite3_stmt *pSql = 0; /* Compiled version of SQL statement below */
6133
6134 /*
6135 ** This SELECT statement returns one row for each foreign key constraint
6136 ** in the schema of the main database. The column values are:
6137 **
6138 ** 0. The text of an SQL statement similar to:
6139 **
danf9679312017-12-01 18:40:18 +00006140 ** "EXPLAIN QUERY PLAN SELECT 1 FROM child_table WHERE child_key=?"
drh2ce15c32017-07-11 13:34:40 +00006141 **
danf9679312017-12-01 18:40:18 +00006142 ** This SELECT is similar to the one that the foreign keys implementation
6143 ** needs to run internally on child tables. If there is an index that can
drh2ce15c32017-07-11 13:34:40 +00006144 ** be used to optimize this query, then it can also be used by the FK
6145 ** implementation to optimize DELETE or UPDATE statements on the parent
6146 ** table.
6147 **
6148 ** 1. A GLOB pattern suitable for sqlite3_strglob(). If the plan output by
6149 ** the EXPLAIN QUERY PLAN command matches this pattern, then the schema
6150 ** contains an index that can be used to optimize the query.
6151 **
6152 ** 2. Human readable text that describes the child table and columns. e.g.
6153 **
6154 ** "child_table(child_key1, child_key2)"
6155 **
6156 ** 3. Human readable text that describes the parent table and columns. e.g.
6157 **
6158 ** "parent_table(parent_key1, parent_key2)"
6159 **
6160 ** 4. A full CREATE INDEX statement for an index that could be used to
6161 ** optimize DELETE or UPDATE statements on the parent table. e.g.
6162 **
6163 ** "CREATE INDEX child_table_child_key ON child_table(child_key)"
6164 **
6165 ** 5. The name of the parent table.
6166 **
6167 ** These six values are used by the C logic below to generate the report.
6168 */
6169 const char *zSql =
6170 "SELECT "
danf9679312017-12-01 18:40:18 +00006171 " 'EXPLAIN QUERY PLAN SELECT 1 FROM ' || quote(s.name) || ' WHERE '"
drh2ce15c32017-07-11 13:34:40 +00006172 " || group_concat(quote(s.name) || '.' || quote(f.[from]) || '=?' "
6173 " || fkey_collate_clause("
6174 " f.[table], COALESCE(f.[to], p.[name]), s.name, f.[from]),' AND ')"
6175 ", "
drh82102332021-03-20 15:11:29 +00006176 " 'SEARCH ' || s.name || ' USING COVERING INDEX*('"
drh2ce15c32017-07-11 13:34:40 +00006177 " || group_concat('*=?', ' AND ') || ')'"
6178 ", "
6179 " s.name || '(' || group_concat(f.[from], ', ') || ')'"
6180 ", "
6181 " f.[table] || '(' || group_concat(COALESCE(f.[to], p.[name])) || ')'"
6182 ", "
6183 " 'CREATE INDEX ' || quote(s.name ||'_'|| group_concat(f.[from], '_'))"
6184 " || ' ON ' || quote(s.name) || '('"
6185 " || group_concat(quote(f.[from]) ||"
6186 " fkey_collate_clause("
6187 " f.[table], COALESCE(f.[to], p.[name]), s.name, f.[from]), ', ')"
6188 " || ');'"
6189 ", "
6190 " f.[table] "
drh067b92b2020-06-19 15:24:12 +00006191 "FROM sqlite_schema AS s, pragma_foreign_key_list(s.name) AS f "
drh2ce15c32017-07-11 13:34:40 +00006192 "LEFT JOIN pragma_table_info AS p ON (pk-1=seq AND p.arg=f.[table]) "
6193 "GROUP BY s.name, f.id "
6194 "ORDER BY (CASE WHEN ? THEN f.[table] ELSE s.name END)"
6195 ;
drh82102332021-03-20 15:11:29 +00006196 const char *zGlobIPK = "SEARCH * USING INTEGER PRIMARY KEY (rowid=?)";
drh2ce15c32017-07-11 13:34:40 +00006197
6198 for(i=2; i<nArg; i++){
drhaf2770f2018-01-05 14:55:43 +00006199 int n = strlen30(azArg[i]);
drh2ce15c32017-07-11 13:34:40 +00006200 if( n>1 && sqlite3_strnicmp("-verbose", azArg[i], n)==0 ){
6201 bVerbose = 1;
6202 }
6203 else if( n>1 && sqlite3_strnicmp("-groupbyparent", azArg[i], n)==0 ){
6204 bGroupByParent = 1;
6205 zIndent = " ";
6206 }
6207 else{
6208 raw_printf(stderr, "Usage: %s %s ?-verbose? ?-groupbyparent?\n",
6209 azArg[0], azArg[1]
6210 );
6211 return SQLITE_ERROR;
6212 }
6213 }
6214
6215 /* Register the fkey_collate_clause() SQL function */
6216 rc = sqlite3_create_function(db, "fkey_collate_clause", 4, SQLITE_UTF8,
6217 0, shellFkeyCollateClause, 0, 0
6218 );
6219
6220
6221 if( rc==SQLITE_OK ){
6222 rc = sqlite3_prepare_v2(db, zSql, -1, &pSql, 0);
6223 }
6224 if( rc==SQLITE_OK ){
6225 sqlite3_bind_int(pSql, 1, bGroupByParent);
6226 }
6227
6228 if( rc==SQLITE_OK ){
6229 int rc2;
6230 char *zPrev = 0;
6231 while( SQLITE_ROW==sqlite3_step(pSql) ){
6232 int res = -1;
6233 sqlite3_stmt *pExplain = 0;
6234 const char *zEQP = (const char*)sqlite3_column_text(pSql, 0);
6235 const char *zGlob = (const char*)sqlite3_column_text(pSql, 1);
6236 const char *zFrom = (const char*)sqlite3_column_text(pSql, 2);
6237 const char *zTarget = (const char*)sqlite3_column_text(pSql, 3);
6238 const char *zCI = (const char*)sqlite3_column_text(pSql, 4);
6239 const char *zParent = (const char*)sqlite3_column_text(pSql, 5);
6240
drh621a5e02021-12-16 17:35:27 +00006241 if( zEQP==0 ) continue;
6242 if( zGlob==0 ) continue;
drh2ce15c32017-07-11 13:34:40 +00006243 rc = sqlite3_prepare_v2(db, zEQP, -1, &pExplain, 0);
6244 if( rc!=SQLITE_OK ) break;
6245 if( SQLITE_ROW==sqlite3_step(pExplain) ){
6246 const char *zPlan = (const char*)sqlite3_column_text(pExplain, 3);
drh621a5e02021-12-16 17:35:27 +00006247 res = zPlan!=0 && ( 0==sqlite3_strglob(zGlob, zPlan)
6248 || 0==sqlite3_strglob(zGlobIPK, zPlan));
drh2ce15c32017-07-11 13:34:40 +00006249 }
6250 rc = sqlite3_finalize(pExplain);
6251 if( rc!=SQLITE_OK ) break;
6252
6253 if( res<0 ){
6254 raw_printf(stderr, "Error: internal error");
6255 break;
6256 }else{
6257 if( bGroupByParent
6258 && (bVerbose || res==0)
6259 && (zPrev==0 || sqlite3_stricmp(zParent, zPrev))
6260 ){
6261 raw_printf(out, "-- Parent table %s\n", zParent);
6262 sqlite3_free(zPrev);
6263 zPrev = sqlite3_mprintf("%s", zParent);
6264 }
6265
6266 if( res==0 ){
6267 raw_printf(out, "%s%s --> %s\n", zIndent, zCI, zTarget);
6268 }else if( bVerbose ){
6269 raw_printf(out, "%s/* no extra indexes required for %s -> %s */\n",
6270 zIndent, zFrom, zTarget
6271 );
6272 }
6273 }
6274 }
6275 sqlite3_free(zPrev);
6276
6277 if( rc!=SQLITE_OK ){
6278 raw_printf(stderr, "%s\n", sqlite3_errmsg(db));
6279 }
6280
6281 rc2 = sqlite3_finalize(pSql);
6282 if( rc==SQLITE_OK && rc2!=SQLITE_OK ){
6283 rc = rc2;
6284 raw_printf(stderr, "%s\n", sqlite3_errmsg(db));
6285 }
6286 }else{
6287 raw_printf(stderr, "%s\n", sqlite3_errmsg(db));
6288 }
6289
6290 return rc;
6291}
6292
6293/*
6294** Implementation of ".lint" dot command.
6295*/
6296static int lintDotCommand(
6297 ShellState *pState, /* Current shell tool state */
6298 char **azArg, /* Array of arguments passed to dot command */
6299 int nArg /* Number of entries in azArg[] */
6300){
6301 int n;
drhaf2770f2018-01-05 14:55:43 +00006302 n = (nArg>=2 ? strlen30(azArg[1]) : 0);
drh2ce15c32017-07-11 13:34:40 +00006303 if( n<1 || sqlite3_strnicmp(azArg[1], "fkey-indexes", n) ) goto usage;
6304 return lintFkeyIndexes(pState, azArg, nArg);
6305
6306 usage:
6307 raw_printf(stderr, "Usage %s sub-command ?switches...?\n", azArg[0]);
6308 raw_printf(stderr, "Where sub-commands are:\n");
6309 raw_printf(stderr, " fkey-indexes\n");
6310 return SQLITE_ERROR;
6311}
6312
dan1b162162019-04-27 20:15:15 +00006313#if !defined SQLITE_OMIT_VIRTUALTABLE
danfd0245d2017-12-07 15:44:29 +00006314static void shellPrepare(
dand4b56e52017-12-12 20:04:59 +00006315 sqlite3 *db,
danfd0245d2017-12-07 15:44:29 +00006316 int *pRc,
6317 const char *zSql,
6318 sqlite3_stmt **ppStmt
6319){
6320 *ppStmt = 0;
6321 if( *pRc==SQLITE_OK ){
dand4b56e52017-12-12 20:04:59 +00006322 int rc = sqlite3_prepare_v2(db, zSql, -1, ppStmt, 0);
danfd0245d2017-12-07 15:44:29 +00006323 if( rc!=SQLITE_OK ){
6324 raw_printf(stderr, "sql error: %s (%d)\n",
dand4b56e52017-12-12 20:04:59 +00006325 sqlite3_errmsg(db), sqlite3_errcode(db)
danfd0245d2017-12-07 15:44:29 +00006326 );
6327 *pRc = rc;
6328 }
6329 }
6330}
6331
drh9546c762019-05-10 17:50:33 +00006332/*
6333** Create a prepared statement using printf-style arguments for the SQL.
6334**
6335** This routine is could be marked "static". But it is not always used,
6336** depending on compile-time options. By omitting the "static", we avoid
6337** nuisance compiler warnings about "defined but not used".
6338*/
6339void shellPreparePrintf(
dan3f67ddf2017-12-13 20:04:53 +00006340 sqlite3 *db,
6341 int *pRc,
danac15e2d2017-12-14 19:15:07 +00006342 sqlite3_stmt **ppStmt,
6343 const char *zFmt,
6344 ...
dan3f67ddf2017-12-13 20:04:53 +00006345){
danac15e2d2017-12-14 19:15:07 +00006346 *ppStmt = 0;
6347 if( *pRc==SQLITE_OK ){
6348 va_list ap;
6349 char *z;
6350 va_start(ap, zFmt);
6351 z = sqlite3_vmprintf(zFmt, ap);
drh1dbb1472018-10-11 10:37:24 +00006352 va_end(ap);
dan3f67ddf2017-12-13 20:04:53 +00006353 if( z==0 ){
6354 *pRc = SQLITE_NOMEM;
6355 }else{
6356 shellPrepare(db, pRc, z, ppStmt);
6357 sqlite3_free(z);
6358 }
dan3f67ddf2017-12-13 20:04:53 +00006359 }
6360}
6361
drh9546c762019-05-10 17:50:33 +00006362/* Finalize the prepared statement created using shellPreparePrintf().
6363**
6364** This routine is could be marked "static". But it is not always used,
6365** depending on compile-time options. By omitting the "static", we avoid
6366** nuisance compiler warnings about "defined but not used".
6367*/
6368void shellFinalize(
danfd0245d2017-12-07 15:44:29 +00006369 int *pRc,
6370 sqlite3_stmt *pStmt
6371){
dan25c12182017-12-07 21:03:33 +00006372 if( pStmt ){
6373 sqlite3 *db = sqlite3_db_handle(pStmt);
6374 int rc = sqlite3_finalize(pStmt);
6375 if( *pRc==SQLITE_OK ){
6376 if( rc!=SQLITE_OK ){
6377 raw_printf(stderr, "SQL error: %s\n", sqlite3_errmsg(db));
6378 }
6379 *pRc = rc;
6380 }
6381 }
danfd0245d2017-12-07 15:44:29 +00006382}
6383
drh9546c762019-05-10 17:50:33 +00006384/* Reset the prepared statement created using shellPreparePrintf().
6385**
6386** This routine is could be marked "static". But it is not always used,
6387** depending on compile-time options. By omitting the "static", we avoid
6388** nuisance compiler warnings about "defined but not used".
6389*/
6390void shellReset(
danfd0245d2017-12-07 15:44:29 +00006391 int *pRc,
6392 sqlite3_stmt *pStmt
6393){
6394 int rc = sqlite3_reset(pStmt);
dan5a78b812017-12-27 18:54:11 +00006395 if( *pRc==SQLITE_OK ){
6396 if( rc!=SQLITE_OK ){
6397 sqlite3 *db = sqlite3_db_handle(pStmt);
6398 raw_printf(stderr, "SQL error: %s\n", sqlite3_errmsg(db));
6399 }
6400 *pRc = rc;
6401 }
danfd0245d2017-12-07 15:44:29 +00006402}
dan1b162162019-04-27 20:15:15 +00006403#endif /* !defined SQLITE_OMIT_VIRTUALTABLE */
6404
6405#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
drhe2754c12019-08-26 12:50:01 +00006406/******************************************************************************
dan1b162162019-04-27 20:15:15 +00006407** The ".archive" or ".ar" command.
6408*/
drhe37c0e12018-01-06 19:19:50 +00006409/*
dan88be0202017-12-09 17:58:02 +00006410** Structure representing a single ".ar" command.
6411*/
6412typedef struct ArCommand ArCommand;
6413struct ArCommand {
drhb376b3d2018-01-10 13:11:51 +00006414 u8 eCmd; /* An AR_CMD_* value */
6415 u8 bVerbose; /* True if --verbose */
drha5676c42018-01-10 15:17:34 +00006416 u8 bZip; /* True if the archive is a ZIP */
drhb376b3d2018-01-10 13:11:51 +00006417 u8 bDryRun; /* True if --dry-run */
drha5676c42018-01-10 15:17:34 +00006418 u8 bAppend; /* True if --append */
larrybr8f09f4b2021-11-02 00:18:11 +00006419 u8 bGlob; /* True if --glob */
drhd0f9cdc2018-05-17 14:09:06 +00006420 u8 fromCmdLine; /* Run from -A instead of .archive */
drhb376b3d2018-01-10 13:11:51 +00006421 int nArg; /* Number of command arguments */
drha5676c42018-01-10 15:17:34 +00006422 char *zSrcTable; /* "sqlar", "zipfile($file)" or "zip" */
dan88be0202017-12-09 17:58:02 +00006423 const char *zFile; /* --file argument, or NULL */
6424 const char *zDir; /* --directory argument, or NULL */
dan88be0202017-12-09 17:58:02 +00006425 char **azArg; /* Array of command arguments */
drhb376b3d2018-01-10 13:11:51 +00006426 ShellState *p; /* Shell state */
6427 sqlite3 *db; /* Database containing the archive */
dan88be0202017-12-09 17:58:02 +00006428};
6429
6430/*
6431** Print a usage message for the .ar command to stderr and return SQLITE_ERROR.
6432*/
dan0d0547f2017-12-14 15:40:42 +00006433static int arUsage(FILE *f){
drh98aa2ab2018-09-26 16:53:51 +00006434 showHelp(f,"archive");
dan0d0547f2017-12-14 15:40:42 +00006435 return SQLITE_ERROR;
6436}
6437
6438/*
6439** Print an error message for the .ar command to stderr and return
6440** SQLITE_ERROR.
6441*/
drhd0f9cdc2018-05-17 14:09:06 +00006442static int arErrorMsg(ArCommand *pAr, const char *zFmt, ...){
dan0d0547f2017-12-14 15:40:42 +00006443 va_list ap;
6444 char *z;
6445 va_start(ap, zFmt);
6446 z = sqlite3_vmprintf(zFmt, ap);
6447 va_end(ap);
drhd0f9cdc2018-05-17 14:09:06 +00006448 utf8_printf(stderr, "Error: %s\n", z);
6449 if( pAr->fromCmdLine ){
6450 utf8_printf(stderr, "Use \"-A\" for more help\n");
6451 }else{
6452 utf8_printf(stderr, "Use \".archive --help\" for more help\n");
6453 }
dan0d0547f2017-12-14 15:40:42 +00006454 sqlite3_free(z);
dan88be0202017-12-09 17:58:02 +00006455 return SQLITE_ERROR;
6456}
6457
6458/*
6459** Values for ArCommand.eCmd.
6460*/
dand4b56e52017-12-12 20:04:59 +00006461#define AR_CMD_CREATE 1
drhb17ea912019-03-25 14:24:19 +00006462#define AR_CMD_UPDATE 2
6463#define AR_CMD_INSERT 3
6464#define AR_CMD_EXTRACT 4
6465#define AR_CMD_LIST 5
6466#define AR_CMD_HELP 6
larrybr47061b92021-11-01 17:22:52 +00006467#define AR_CMD_REMOVE 7
dand4b56e52017-12-12 20:04:59 +00006468
6469/*
6470** Other (non-command) switches.
6471*/
larrybr47061b92021-11-01 17:22:52 +00006472#define AR_SWITCH_VERBOSE 8
6473#define AR_SWITCH_FILE 9
6474#define AR_SWITCH_DIRECTORY 10
6475#define AR_SWITCH_APPEND 11
larrybr719506f2021-11-01 22:33:20 +00006476#define AR_SWITCH_DRYRUN 12
larrybr8f09f4b2021-11-02 00:18:11 +00006477#define AR_SWITCH_GLOB 13
dand4b56e52017-12-12 20:04:59 +00006478
6479static int arProcessSwitch(ArCommand *pAr, int eSwitch, const char *zArg){
6480 switch( eSwitch ){
6481 case AR_CMD_CREATE:
6482 case AR_CMD_EXTRACT:
6483 case AR_CMD_LIST:
larrybr47061b92021-11-01 17:22:52 +00006484 case AR_CMD_REMOVE:
dand4b56e52017-12-12 20:04:59 +00006485 case AR_CMD_UPDATE:
drhb17ea912019-03-25 14:24:19 +00006486 case AR_CMD_INSERT:
dan0d0547f2017-12-14 15:40:42 +00006487 case AR_CMD_HELP:
6488 if( pAr->eCmd ){
drhd0f9cdc2018-05-17 14:09:06 +00006489 return arErrorMsg(pAr, "multiple command options");
dan0d0547f2017-12-14 15:40:42 +00006490 }
dand4b56e52017-12-12 20:04:59 +00006491 pAr->eCmd = eSwitch;
6492 break;
6493
drhb376b3d2018-01-10 13:11:51 +00006494 case AR_SWITCH_DRYRUN:
6495 pAr->bDryRun = 1;
6496 break;
larrybr8f09f4b2021-11-02 00:18:11 +00006497 case AR_SWITCH_GLOB:
6498 pAr->bGlob = 1;
6499 break;
dand4b56e52017-12-12 20:04:59 +00006500 case AR_SWITCH_VERBOSE:
6501 pAr->bVerbose = 1;
6502 break;
drha5676c42018-01-10 15:17:34 +00006503 case AR_SWITCH_APPEND:
6504 pAr->bAppend = 1;
drhca7733b2018-01-10 18:09:20 +00006505 /* Fall thru into --file */
dand4b56e52017-12-12 20:04:59 +00006506 case AR_SWITCH_FILE:
6507 pAr->zFile = zArg;
6508 break;
6509 case AR_SWITCH_DIRECTORY:
6510 pAr->zDir = zArg;
6511 break;
6512 }
6513
6514 return SQLITE_OK;
6515}
dan88be0202017-12-09 17:58:02 +00006516
6517/*
6518** Parse the command line for an ".ar" command. The results are written into
6519** structure (*pAr). SQLITE_OK is returned if the command line is parsed
6520** successfully, otherwise an error message is written to stderr and
6521** SQLITE_ERROR returned.
6522*/
6523static int arParseCommand(
6524 char **azArg, /* Array of arguments passed to dot command */
6525 int nArg, /* Number of entries in azArg[] */
6526 ArCommand *pAr /* Populate this object */
6527){
dand4b56e52017-12-12 20:04:59 +00006528 struct ArSwitch {
dand4b56e52017-12-12 20:04:59 +00006529 const char *zLong;
drhb376b3d2018-01-10 13:11:51 +00006530 char cShort;
6531 u8 eSwitch;
6532 u8 bArg;
dand4b56e52017-12-12 20:04:59 +00006533 } aSwitch[] = {
drhb376b3d2018-01-10 13:11:51 +00006534 { "create", 'c', AR_CMD_CREATE, 0 },
6535 { "extract", 'x', AR_CMD_EXTRACT, 0 },
drhb17ea912019-03-25 14:24:19 +00006536 { "insert", 'i', AR_CMD_INSERT, 0 },
drhb376b3d2018-01-10 13:11:51 +00006537 { "list", 't', AR_CMD_LIST, 0 },
larrybr47061b92021-11-01 17:22:52 +00006538 { "remove", 'r', AR_CMD_REMOVE, 0 },
drhb376b3d2018-01-10 13:11:51 +00006539 { "update", 'u', AR_CMD_UPDATE, 0 },
6540 { "help", 'h', AR_CMD_HELP, 0 },
6541 { "verbose", 'v', AR_SWITCH_VERBOSE, 0 },
6542 { "file", 'f', AR_SWITCH_FILE, 1 },
drhca7733b2018-01-10 18:09:20 +00006543 { "append", 'a', AR_SWITCH_APPEND, 1 },
drhb376b3d2018-01-10 13:11:51 +00006544 { "directory", 'C', AR_SWITCH_DIRECTORY, 1 },
drhb376b3d2018-01-10 13:11:51 +00006545 { "dryrun", 'n', AR_SWITCH_DRYRUN, 0 },
larrybr8f09f4b2021-11-02 00:18:11 +00006546 { "glob", 'g', AR_SWITCH_GLOB, 0 },
dand4b56e52017-12-12 20:04:59 +00006547 };
6548 int nSwitch = sizeof(aSwitch) / sizeof(struct ArSwitch);
6549 struct ArSwitch *pEnd = &aSwitch[nSwitch];
6550
dan88be0202017-12-09 17:58:02 +00006551 if( nArg<=1 ){
drh98aa2ab2018-09-26 16:53:51 +00006552 utf8_printf(stderr, "Wrong number of arguments. Usage:\n");
dan0d0547f2017-12-14 15:40:42 +00006553 return arUsage(stderr);
dan88be0202017-12-09 17:58:02 +00006554 }else{
6555 char *z = azArg[1];
dan88be0202017-12-09 17:58:02 +00006556 if( z[0]!='-' ){
6557 /* Traditional style [tar] invocation */
6558 int i;
6559 int iArg = 2;
6560 for(i=0; z[i]; i++){
dand4b56e52017-12-12 20:04:59 +00006561 const char *zArg = 0;
6562 struct ArSwitch *pOpt;
6563 for(pOpt=&aSwitch[0]; pOpt<pEnd; pOpt++){
6564 if( z[i]==pOpt->cShort ) break;
dan88be0202017-12-09 17:58:02 +00006565 }
dan0d0547f2017-12-14 15:40:42 +00006566 if( pOpt==pEnd ){
drhd0f9cdc2018-05-17 14:09:06 +00006567 return arErrorMsg(pAr, "unrecognized option: %c", z[i]);
dan0d0547f2017-12-14 15:40:42 +00006568 }
dand4b56e52017-12-12 20:04:59 +00006569 if( pOpt->bArg ){
dan0d0547f2017-12-14 15:40:42 +00006570 if( iArg>=nArg ){
drhd0f9cdc2018-05-17 14:09:06 +00006571 return arErrorMsg(pAr, "option requires an argument: %c",z[i]);
dan0d0547f2017-12-14 15:40:42 +00006572 }
dand4b56e52017-12-12 20:04:59 +00006573 zArg = azArg[iArg++];
6574 }
6575 if( arProcessSwitch(pAr, pOpt->eSwitch, zArg) ) return SQLITE_ERROR;
dan88be0202017-12-09 17:58:02 +00006576 }
dan88be0202017-12-09 17:58:02 +00006577 pAr->nArg = nArg-iArg;
6578 if( pAr->nArg>0 ){
6579 pAr->azArg = &azArg[iArg];
6580 }
dand4b56e52017-12-12 20:04:59 +00006581 }else{
6582 /* Non-traditional invocation */
6583 int iArg;
6584 for(iArg=1; iArg<nArg; iArg++){
6585 int n;
6586 z = azArg[iArg];
6587 if( z[0]!='-' ){
6588 /* All remaining command line words are command arguments. */
6589 pAr->azArg = &azArg[iArg];
6590 pAr->nArg = nArg-iArg;
6591 break;
6592 }
drhaf2770f2018-01-05 14:55:43 +00006593 n = strlen30(z);
dand4b56e52017-12-12 20:04:59 +00006594
6595 if( z[1]!='-' ){
6596 int i;
6597 /* One or more short options */
6598 for(i=1; i<n; i++){
6599 const char *zArg = 0;
6600 struct ArSwitch *pOpt;
6601 for(pOpt=&aSwitch[0]; pOpt<pEnd; pOpt++){
6602 if( z[i]==pOpt->cShort ) break;
6603 }
dan0d0547f2017-12-14 15:40:42 +00006604 if( pOpt==pEnd ){
drhd0f9cdc2018-05-17 14:09:06 +00006605 return arErrorMsg(pAr, "unrecognized option: %c", z[i]);
dan0d0547f2017-12-14 15:40:42 +00006606 }
dand4b56e52017-12-12 20:04:59 +00006607 if( pOpt->bArg ){
6608 if( i<(n-1) ){
6609 zArg = &z[i+1];
6610 i = n;
6611 }else{
dan0d0547f2017-12-14 15:40:42 +00006612 if( iArg>=(nArg-1) ){
drhe2754c12019-08-26 12:50:01 +00006613 return arErrorMsg(pAr, "option requires an argument: %c",
6614 z[i]);
dan0d0547f2017-12-14 15:40:42 +00006615 }
dand4b56e52017-12-12 20:04:59 +00006616 zArg = azArg[++iArg];
6617 }
6618 }
6619 if( arProcessSwitch(pAr, pOpt->eSwitch, zArg) ) return SQLITE_ERROR;
6620 }
6621 }else if( z[2]=='\0' ){
6622 /* A -- option, indicating that all remaining command line words
6623 ** are command arguments. */
6624 pAr->azArg = &azArg[iArg+1];
6625 pAr->nArg = nArg-iArg-1;
6626 break;
6627 }else{
6628 /* A long option */
6629 const char *zArg = 0; /* Argument for option, if any */
6630 struct ArSwitch *pMatch = 0; /* Matching option */
6631 struct ArSwitch *pOpt; /* Iterator */
6632 for(pOpt=&aSwitch[0]; pOpt<pEnd; pOpt++){
6633 const char *zLong = pOpt->zLong;
drhaf2770f2018-01-05 14:55:43 +00006634 if( (n-2)<=strlen30(zLong) && 0==memcmp(&z[2], zLong, n-2) ){
dand4b56e52017-12-12 20:04:59 +00006635 if( pMatch ){
drhd0f9cdc2018-05-17 14:09:06 +00006636 return arErrorMsg(pAr, "ambiguous option: %s",z);
dand4b56e52017-12-12 20:04:59 +00006637 }else{
6638 pMatch = pOpt;
6639 }
6640 }
6641 }
6642
6643 if( pMatch==0 ){
drhd0f9cdc2018-05-17 14:09:06 +00006644 return arErrorMsg(pAr, "unrecognized option: %s", z);
dand4b56e52017-12-12 20:04:59 +00006645 }
6646 if( pMatch->bArg ){
dan0d0547f2017-12-14 15:40:42 +00006647 if( iArg>=(nArg-1) ){
drhd0f9cdc2018-05-17 14:09:06 +00006648 return arErrorMsg(pAr, "option requires an argument: %s", z);
dan0d0547f2017-12-14 15:40:42 +00006649 }
dand4b56e52017-12-12 20:04:59 +00006650 zArg = azArg[++iArg];
6651 }
6652 if( arProcessSwitch(pAr, pMatch->eSwitch, zArg) ) return SQLITE_ERROR;
6653 }
6654 }
dan88be0202017-12-09 17:58:02 +00006655 }
6656 }
6657
6658 return SQLITE_OK;
6659}
6660
6661/*
dan3f67ddf2017-12-13 20:04:53 +00006662** This function assumes that all arguments within the ArCommand.azArg[]
larrybr47061b92021-11-01 17:22:52 +00006663** array refer to archive members, as for the --extract, --list or --remove
larrybr8f09f4b2021-11-02 00:18:11 +00006664** commands. It checks that each of them are "present". If any specified
6665** file is not present in the archive, an error is printed to stderr and an
larrybr47061b92021-11-01 17:22:52 +00006666** error code returned. Otherwise, if all specified arguments are present
larrybr8f09f4b2021-11-02 00:18:11 +00006667** in the archive, SQLITE_OK is returned. Here, "present" means either an
6668** exact equality when pAr->bGlob is false or a "name GLOB pattern" match
drh0c0fb9c2021-11-02 10:54:39 +00006669** when pAr->bGlob is true.
dan3f67ddf2017-12-13 20:04:53 +00006670**
6671** This function strips any trailing '/' characters from each argument.
6672** This is consistent with the way the [tar] command seems to work on
6673** Linux.
6674*/
drhb376b3d2018-01-10 13:11:51 +00006675static int arCheckEntries(ArCommand *pAr){
dan3f67ddf2017-12-13 20:04:53 +00006676 int rc = SQLITE_OK;
6677 if( pAr->nArg ){
drhb376b3d2018-01-10 13:11:51 +00006678 int i, j;
dan3f67ddf2017-12-13 20:04:53 +00006679 sqlite3_stmt *pTest = 0;
larrybr8f09f4b2021-11-02 00:18:11 +00006680 const char *zSel = (pAr->bGlob)
6681 ? "SELECT name FROM %s WHERE glob($name,name)"
6682 : "SELECT name FROM %s WHERE name=$name";
dan3f67ddf2017-12-13 20:04:53 +00006683
larrybr8f09f4b2021-11-02 00:18:11 +00006684 shellPreparePrintf(pAr->db, &rc, &pTest, zSel, pAr->zSrcTable);
drhb376b3d2018-01-10 13:11:51 +00006685 j = sqlite3_bind_parameter_index(pTest, "$name");
dan3f67ddf2017-12-13 20:04:53 +00006686 for(i=0; i<pAr->nArg && rc==SQLITE_OK; i++){
6687 char *z = pAr->azArg[i];
drhaf2770f2018-01-05 14:55:43 +00006688 int n = strlen30(z);
dan3f67ddf2017-12-13 20:04:53 +00006689 int bOk = 0;
6690 while( n>0 && z[n-1]=='/' ) n--;
6691 z[n] = '\0';
drhb376b3d2018-01-10 13:11:51 +00006692 sqlite3_bind_text(pTest, j, z, -1, SQLITE_STATIC);
dan3f67ddf2017-12-13 20:04:53 +00006693 if( SQLITE_ROW==sqlite3_step(pTest) ){
6694 bOk = 1;
6695 }
6696 shellReset(&rc, pTest);
6697 if( rc==SQLITE_OK && bOk==0 ){
drhb376b3d2018-01-10 13:11:51 +00006698 utf8_printf(stderr, "not found in archive: %s\n", z);
dan3f67ddf2017-12-13 20:04:53 +00006699 rc = SQLITE_ERROR;
6700 }
6701 }
6702 shellFinalize(&rc, pTest);
6703 }
dan3f67ddf2017-12-13 20:04:53 +00006704 return rc;
6705}
6706
6707/*
6708** Format a WHERE clause that can be used against the "sqlar" table to
6709** identify all archive members that match the command arguments held
6710** in (*pAr). Leave this WHERE clause in (*pzWhere) before returning.
6711** The caller is responsible for eventually calling sqlite3_free() on
larrybr8f09f4b2021-11-02 00:18:11 +00006712** any non-NULL (*pzWhere) value. Here, "match" means strict equality
6713** when pAr->bGlob is false and GLOB match when pAr->bGlob is true.
dan3f67ddf2017-12-13 20:04:53 +00006714*/
6715static void arWhereClause(
6716 int *pRc,
larrybr8f09f4b2021-11-02 00:18:11 +00006717 ArCommand *pAr,
danac15e2d2017-12-14 19:15:07 +00006718 char **pzWhere /* OUT: New WHERE clause */
dan3f67ddf2017-12-13 20:04:53 +00006719){
6720 char *zWhere = 0;
larrybr8f09f4b2021-11-02 00:18:11 +00006721 const char *zSameOp = (pAr->bGlob)? "GLOB" : "=";
dan3f67ddf2017-12-13 20:04:53 +00006722 if( *pRc==SQLITE_OK ){
danac15e2d2017-12-14 19:15:07 +00006723 if( pAr->nArg==0 ){
6724 zWhere = sqlite3_mprintf("1");
6725 }else{
6726 int i;
6727 const char *zSep = "";
6728 for(i=0; i<pAr->nArg; i++){
6729 const char *z = pAr->azArg[i];
6730 zWhere = sqlite3_mprintf(
larrybr8f09f4b2021-11-02 00:18:11 +00006731 "%z%s name %s '%q' OR substr(name,1,%d) %s '%q/'",
6732 zWhere, zSep, zSameOp, z, strlen30(z)+1, zSameOp, z
drhb376b3d2018-01-10 13:11:51 +00006733 );
danac15e2d2017-12-14 19:15:07 +00006734 if( zWhere==0 ){
6735 *pRc = SQLITE_NOMEM;
6736 break;
6737 }
6738 zSep = " OR ";
dan3f67ddf2017-12-13 20:04:53 +00006739 }
dan3f67ddf2017-12-13 20:04:53 +00006740 }
6741 }
6742 *pzWhere = zWhere;
6743}
6744
6745/*
dan88be0202017-12-09 17:58:02 +00006746** Implementation of .ar "lisT" command.
6747*/
drhb376b3d2018-01-10 13:11:51 +00006748static int arListCommand(ArCommand *pAr){
danb5090e42017-12-27 21:13:21 +00006749 const char *zSql = "SELECT %s FROM %s WHERE %s";
danb5090e42017-12-27 21:13:21 +00006750 const char *azCols[] = {
6751 "name",
drh410cad92018-01-10 17:19:16 +00006752 "lsmode(mode), sz, datetime(mtime, 'unixepoch'), name"
danb5090e42017-12-27 21:13:21 +00006753 };
dan5a78b812017-12-27 18:54:11 +00006754
dan3f67ddf2017-12-13 20:04:53 +00006755 char *zWhere = 0;
6756 sqlite3_stmt *pSql = 0;
6757 int rc;
6758
drhb376b3d2018-01-10 13:11:51 +00006759 rc = arCheckEntries(pAr);
dan3f67ddf2017-12-13 20:04:53 +00006760 arWhereClause(&rc, pAr, &zWhere);
6761
drhb376b3d2018-01-10 13:11:51 +00006762 shellPreparePrintf(pAr->db, &rc, &pSql, zSql, azCols[pAr->bVerbose],
6763 pAr->zSrcTable, zWhere);
drhb376b3d2018-01-10 13:11:51 +00006764 if( pAr->bDryRun ){
6765 utf8_printf(pAr->p->out, "%s\n", sqlite3_sql(pSql));
6766 }else{
6767 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){
6768 if( pAr->bVerbose ){
drh410cad92018-01-10 17:19:16 +00006769 utf8_printf(pAr->p->out, "%s % 10d %s %s\n",
6770 sqlite3_column_text(pSql, 0),
drhb376b3d2018-01-10 13:11:51 +00006771 sqlite3_column_int(pSql, 1),
6772 sqlite3_column_text(pSql, 2),
6773 sqlite3_column_text(pSql, 3)
6774 );
6775 }else{
6776 utf8_printf(pAr->p->out, "%s\n", sqlite3_column_text(pSql, 0));
6777 }
danb5090e42017-12-27 21:13:21 +00006778 }
dan3f67ddf2017-12-13 20:04:53 +00006779 }
dan5a78b812017-12-27 18:54:11 +00006780 shellFinalize(&rc, pSql);
drhd0f9cdc2018-05-17 14:09:06 +00006781 sqlite3_free(zWhere);
dan3f67ddf2017-12-13 20:04:53 +00006782 return rc;
dan88be0202017-12-09 17:58:02 +00006783}
6784
6785
danfd0245d2017-12-07 15:44:29 +00006786/*
larrybr47061b92021-11-01 17:22:52 +00006787** Implementation of .ar "Remove" command.
6788*/
6789static int arRemoveCommand(ArCommand *pAr){
larrybr7774fc02021-11-01 22:30:24 +00006790 int rc = 0;
larrybr47061b92021-11-01 17:22:52 +00006791 char *zSql = 0;
6792 char *zWhere = 0;
6793
6794 if( pAr->nArg ){
6795 /* Verify that args actually exist within the archive before proceeding.
6796 ** And formulate a WHERE clause to match them. */
6797 rc = arCheckEntries(pAr);
6798 arWhereClause(&rc, pAr, &zWhere);
6799 }
6800 if( rc==SQLITE_OK ){
6801 zSql = sqlite3_mprintf("DELETE FROM %s WHERE %s;",
6802 pAr->zSrcTable, zWhere);
6803 if( pAr->bDryRun ){
6804 utf8_printf(pAr->p->out, "%s\n", zSql);
6805 }else{
6806 char *zErr = 0;
6807 rc = sqlite3_exec(pAr->db, "SAVEPOINT ar;", 0, 0, 0);
6808 if( rc==SQLITE_OK ){
6809 rc = sqlite3_exec(pAr->db, zSql, 0, 0, &zErr);
6810 if( rc!=SQLITE_OK ){
6811 sqlite3_exec(pAr->db, "ROLLBACK TO ar; RELEASE ar;", 0, 0, 0);
6812 }else{
6813 rc = sqlite3_exec(pAr->db, "RELEASE ar;", 0, 0, 0);
6814 }
6815 }
6816 if( zErr ){
6817 utf8_printf(stdout, "ERROR: %s\n", zErr);
6818 sqlite3_free(zErr);
6819 }
6820 }
6821 }
6822 sqlite3_free(zWhere);
6823 sqlite3_free(zSql);
6824 return rc;
6825}
6826
6827/*
danfd0245d2017-12-07 15:44:29 +00006828** Implementation of .ar "eXtract" command.
6829*/
drhb376b3d2018-01-10 13:11:51 +00006830static int arExtractCommand(ArCommand *pAr){
dan25c12182017-12-07 21:03:33 +00006831 const char *zSql1 =
dand1b51d42017-12-16 19:11:26 +00006832 "SELECT "
drhb376b3d2018-01-10 13:11:51 +00006833 " ($dir || name),"
6834 " writefile(($dir || name), %s, mode, mtime) "
drh0cfd46a2018-06-06 01:18:01 +00006835 "FROM %s WHERE (%s) AND (data IS NULL OR $dirOnly = 0)"
6836 " AND name NOT GLOB '*..[/\\]*'";
dan5a78b812017-12-27 18:54:11 +00006837
6838 const char *azExtraArg[] = {
6839 "sqlar_uncompress(data, sz)",
dan7c15ac12018-01-08 19:59:59 +00006840 "data"
dan5a78b812017-12-27 18:54:11 +00006841 };
dan5a78b812017-12-27 18:54:11 +00006842
danfd0245d2017-12-07 15:44:29 +00006843 sqlite3_stmt *pSql = 0;
6844 int rc = SQLITE_OK;
dan2ad09492017-12-09 18:28:22 +00006845 char *zDir = 0;
dan3f67ddf2017-12-13 20:04:53 +00006846 char *zWhere = 0;
drhb376b3d2018-01-10 13:11:51 +00006847 int i, j;
dan2ad09492017-12-09 18:28:22 +00006848
dan3f67ddf2017-12-13 20:04:53 +00006849 /* If arguments are specified, check that they actually exist within
6850 ** the archive before proceeding. And formulate a WHERE clause to
6851 ** match them. */
drhb376b3d2018-01-10 13:11:51 +00006852 rc = arCheckEntries(pAr);
dan3f67ddf2017-12-13 20:04:53 +00006853 arWhereClause(&rc, pAr, &zWhere);
6854
6855 if( rc==SQLITE_OK ){
6856 if( pAr->zDir ){
6857 zDir = sqlite3_mprintf("%s/", pAr->zDir);
6858 }else{
6859 zDir = sqlite3_mprintf("");
6860 }
6861 if( zDir==0 ) rc = SQLITE_NOMEM;
dan2ad09492017-12-09 18:28:22 +00006862 }
danfd0245d2017-12-07 15:44:29 +00006863
drhb376b3d2018-01-10 13:11:51 +00006864 shellPreparePrintf(pAr->db, &rc, &pSql, zSql1,
6865 azExtraArg[pAr->bZip], pAr->zSrcTable, zWhere
dan5a78b812017-12-27 18:54:11 +00006866 );
6867
dan2ad09492017-12-09 18:28:22 +00006868 if( rc==SQLITE_OK ){
drhb376b3d2018-01-10 13:11:51 +00006869 j = sqlite3_bind_parameter_index(pSql, "$dir");
6870 sqlite3_bind_text(pSql, j, zDir, -1, SQLITE_STATIC);
dan25c12182017-12-07 21:03:33 +00006871
danac15e2d2017-12-14 19:15:07 +00006872 /* Run the SELECT statement twice. The first time, writefile() is called
6873 ** for all archive members that should be extracted. The second time,
6874 ** only for the directories. This is because the timestamps for
6875 ** extracted directories must be reset after they are populated (as
6876 ** populating them changes the timestamp). */
6877 for(i=0; i<2; i++){
drhb376b3d2018-01-10 13:11:51 +00006878 j = sqlite3_bind_parameter_index(pSql, "$dirOnly");
6879 sqlite3_bind_int(pSql, j, i);
6880 if( pAr->bDryRun ){
6881 utf8_printf(pAr->p->out, "%s\n", sqlite3_sql(pSql));
6882 }else{
6883 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){
6884 if( i==0 && pAr->bVerbose ){
6885 utf8_printf(pAr->p->out, "%s\n", sqlite3_column_text(pSql, 0));
6886 }
danac15e2d2017-12-14 19:15:07 +00006887 }
6888 }
6889 shellReset(&rc, pSql);
dan25c12182017-12-07 21:03:33 +00006890 }
danac15e2d2017-12-14 19:15:07 +00006891 shellFinalize(&rc, pSql);
dan25c12182017-12-07 21:03:33 +00006892 }
dan25c12182017-12-07 21:03:33 +00006893
dan2ad09492017-12-09 18:28:22 +00006894 sqlite3_free(zDir);
dan3f67ddf2017-12-13 20:04:53 +00006895 sqlite3_free(zWhere);
danfd0245d2017-12-07 15:44:29 +00006896 return rc;
6897}
6898
drhb376b3d2018-01-10 13:11:51 +00006899/*
6900** Run the SQL statement in zSql. Or if doing a --dryrun, merely print it out.
6901*/
6902static int arExecSql(ArCommand *pAr, const char *zSql){
6903 int rc;
6904 if( pAr->bDryRun ){
6905 utf8_printf(pAr->p->out, "%s\n", zSql);
6906 rc = SQLITE_OK;
6907 }else{
drh410cad92018-01-10 17:19:16 +00006908 char *zErr = 0;
6909 rc = sqlite3_exec(pAr->db, zSql, 0, 0, &zErr);
6910 if( zErr ){
6911 utf8_printf(stdout, "ERROR: %s\n", zErr);
6912 sqlite3_free(zErr);
6913 }
drhb376b3d2018-01-10 13:11:51 +00006914 }
6915 return rc;
6916}
6917
dan1ad3f612017-12-11 20:22:02 +00006918
danfd0245d2017-12-07 15:44:29 +00006919/*
drhb17ea912019-03-25 14:24:19 +00006920** Implementation of .ar "create", "insert", and "update" commands.
6921**
6922** create -> Create a new SQL archive
6923** insert -> Insert or reinsert all files listed
6924** update -> Insert files that have changed or that were not
6925** previously in the archive
danfd0245d2017-12-07 15:44:29 +00006926**
6927** Create the "sqlar" table in the database if it does not already exist.
6928** Then add each file in the azFile[] array to the archive. Directories
6929** are added recursively. If argument bVerbose is non-zero, a message is
6930** printed on stdout for each file archived.
dan06741a32017-12-13 20:17:18 +00006931**
6932** The create command is the same as update, except that it drops
drhb17ea912019-03-25 14:24:19 +00006933** any existing "sqlar" table before beginning. The "insert" command
6934** always overwrites every file named on the command-line, where as
6935** "update" only overwrites if the size or mtime or mode has changed.
danfd0245d2017-12-07 15:44:29 +00006936*/
drhb376b3d2018-01-10 13:11:51 +00006937static int arCreateOrUpdateCommand(
dan06741a32017-12-13 20:17:18 +00006938 ArCommand *pAr, /* Command arguments and options */
drhb17ea912019-03-25 14:24:19 +00006939 int bUpdate, /* true for a --create. */
6940 int bOnlyIfChanged /* Only update if file has changed */
danfd0245d2017-12-07 15:44:29 +00006941){
dand4b56e52017-12-12 20:04:59 +00006942 const char *zCreate =
drhafba1802018-01-06 15:49:57 +00006943 "CREATE TABLE IF NOT EXISTS sqlar(\n"
6944 " name TEXT PRIMARY KEY, -- name of the file\n"
6945 " mode INT, -- access permissions\n"
6946 " mtime INT, -- last modification time\n"
6947 " sz INT, -- original file size\n"
6948 " data BLOB -- compressed content\n"
6949 ")";
dand4b56e52017-12-12 20:04:59 +00006950 const char *zDrop = "DROP TABLE IF EXISTS sqlar";
drh1bf208c2018-03-09 21:54:01 +00006951 const char *zInsertFmt[2] = {
6952 "REPLACE INTO %s(name,mode,mtime,sz,data)\n"
drh634c70f2018-01-10 16:50:18 +00006953 " SELECT\n"
6954 " %s,\n"
6955 " mode,\n"
6956 " mtime,\n"
drh410cad92018-01-10 17:19:16 +00006957 " CASE substr(lsmode(mode),1,1)\n"
6958 " WHEN '-' THEN length(data)\n"
6959 " WHEN 'd' THEN 0\n"
drh634c70f2018-01-10 16:50:18 +00006960 " ELSE -1 END,\n"
drh69d2d352018-03-09 22:18:53 +00006961 " sqlar_compress(data)\n"
drhb17ea912019-03-25 14:24:19 +00006962 " FROM fsdir(%Q,%Q) AS disk\n"
6963 " WHERE lsmode(mode) NOT LIKE '?%%'%s;"
6964 ,
drh1bf208c2018-03-09 21:54:01 +00006965 "REPLACE INTO %s(name,mode,mtime,data)\n"
6966 " SELECT\n"
6967 " %s,\n"
6968 " mode,\n"
6969 " mtime,\n"
6970 " data\n"
drhb17ea912019-03-25 14:24:19 +00006971 " FROM fsdir(%Q,%Q) AS disk\n"
6972 " WHERE lsmode(mode) NOT LIKE '?%%'%s;"
drh1bf208c2018-03-09 21:54:01 +00006973 };
danfd0245d2017-12-07 15:44:29 +00006974 int i; /* For iterating through azFile[] */
6975 int rc; /* Return code */
drh1bf208c2018-03-09 21:54:01 +00006976 const char *zTab = 0; /* SQL table into which to insert */
6977 char *zSql;
6978 char zTemp[50];
drhb17ea912019-03-25 14:24:19 +00006979 char *zExists = 0;
danfd0245d2017-12-07 15:44:29 +00006980
drh1bf208c2018-03-09 21:54:01 +00006981 arExecSql(pAr, "PRAGMA page_size=512");
drhb376b3d2018-01-10 13:11:51 +00006982 rc = arExecSql(pAr, "SAVEPOINT ar;");
danfd0245d2017-12-07 15:44:29 +00006983 if( rc!=SQLITE_OK ) return rc;
drh1bf208c2018-03-09 21:54:01 +00006984 zTemp[0] = 0;
6985 if( pAr->bZip ){
6986 /* Initialize the zipfile virtual table, if necessary */
6987 if( pAr->zFile ){
6988 sqlite3_uint64 r;
6989 sqlite3_randomness(sizeof(r),&r);
6990 sqlite3_snprintf(sizeof(zTemp),zTemp,"zip%016llx",r);
6991 zTab = zTemp;
6992 zSql = sqlite3_mprintf(
6993 "CREATE VIRTUAL TABLE temp.%s USING zipfile(%Q)",
6994 zTab, pAr->zFile
6995 );
6996 rc = arExecSql(pAr, zSql);
6997 sqlite3_free(zSql);
6998 }else{
6999 zTab = "zip";
7000 }
7001 }else{
7002 /* Initialize the table for an SQLAR */
7003 zTab = "sqlar";
7004 if( bUpdate==0 ){
7005 rc = arExecSql(pAr, zDrop);
7006 if( rc!=SQLITE_OK ) goto end_ar_transaction;
7007 }
7008 rc = arExecSql(pAr, zCreate);
dan06741a32017-12-13 20:17:18 +00007009 }
drhb17ea912019-03-25 14:24:19 +00007010 if( bOnlyIfChanged ){
7011 zExists = sqlite3_mprintf(
7012 " AND NOT EXISTS("
7013 "SELECT 1 FROM %s AS mem"
7014 " WHERE mem.name=disk.name"
7015 " AND mem.mtime=disk.mtime"
7016 " AND mem.mode=disk.mode)", zTab);
7017 }else{
7018 zExists = sqlite3_mprintf("");
7019 }
7020 if( zExists==0 ) rc = SQLITE_NOMEM;
dan88be0202017-12-09 17:58:02 +00007021 for(i=0; i<pAr->nArg && rc==SQLITE_OK; i++){
mistachkince2052b2018-03-23 00:31:53 +00007022 char *zSql2 = sqlite3_mprintf(zInsertFmt[pAr->bZip], zTab,
drh634c70f2018-01-10 16:50:18 +00007023 pAr->bVerbose ? "shell_putsnl(name)" : "name",
drhb17ea912019-03-25 14:24:19 +00007024 pAr->azArg[i], pAr->zDir, zExists);
mistachkince2052b2018-03-23 00:31:53 +00007025 rc = arExecSql(pAr, zSql2);
7026 sqlite3_free(zSql2);
danfd0245d2017-12-07 15:44:29 +00007027 }
drh1bf208c2018-03-09 21:54:01 +00007028end_ar_transaction:
danfd0245d2017-12-07 15:44:29 +00007029 if( rc!=SQLITE_OK ){
drh2bd207f2019-01-11 17:19:59 +00007030 sqlite3_exec(pAr->db, "ROLLBACK TO ar; RELEASE ar;", 0, 0, 0);
danfd0245d2017-12-07 15:44:29 +00007031 }else{
drhb376b3d2018-01-10 13:11:51 +00007032 rc = arExecSql(pAr, "RELEASE ar;");
drh1bf208c2018-03-09 21:54:01 +00007033 if( pAr->bZip && pAr->zFile ){
7034 zSql = sqlite3_mprintf("DROP TABLE %s", zTemp);
7035 arExecSql(pAr, zSql);
7036 sqlite3_free(zSql);
7037 }
danfd0245d2017-12-07 15:44:29 +00007038 }
drhb17ea912019-03-25 14:24:19 +00007039 sqlite3_free(zExists);
danfd0245d2017-12-07 15:44:29 +00007040 return rc;
7041}
7042
7043/*
7044** Implementation of ".ar" dot command.
7045*/
7046static int arDotCommand(
drhe2754c12019-08-26 12:50:01 +00007047 ShellState *pState, /* Current shell tool state */
7048 int fromCmdLine, /* True if -A command-line option, not .ar cmd */
7049 char **azArg, /* Array of arguments passed to dot command */
7050 int nArg /* Number of entries in azArg[] */
danfd0245d2017-12-07 15:44:29 +00007051){
dan88be0202017-12-09 17:58:02 +00007052 ArCommand cmd;
7053 int rc;
drh34660642018-01-10 17:39:54 +00007054 memset(&cmd, 0, sizeof(cmd));
drhd0f9cdc2018-05-17 14:09:06 +00007055 cmd.fromCmdLine = fromCmdLine;
dan88be0202017-12-09 17:58:02 +00007056 rc = arParseCommand(azArg, nArg, &cmd);
7057 if( rc==SQLITE_OK ){
drha5676c42018-01-10 15:17:34 +00007058 int eDbType = SHELL_OPEN_UNSPEC;
drhb376b3d2018-01-10 13:11:51 +00007059 cmd.p = pState;
7060 cmd.db = pState->db;
drha5676c42018-01-10 15:17:34 +00007061 if( cmd.zFile ){
drh1bf208c2018-03-09 21:54:01 +00007062 eDbType = deduceDatabaseType(cmd.zFile, 1);
drha5676c42018-01-10 15:17:34 +00007063 }else{
7064 eDbType = pState->openMode;
7065 }
7066 if( eDbType==SHELL_OPEN_ZIPFILE ){
drh1bf208c2018-03-09 21:54:01 +00007067 if( cmd.eCmd==AR_CMD_EXTRACT || cmd.eCmd==AR_CMD_LIST ){
7068 if( cmd.zFile==0 ){
7069 cmd.zSrcTable = sqlite3_mprintf("zip");
7070 }else{
7071 cmd.zSrcTable = sqlite3_mprintf("zipfile(%Q)", cmd.zFile);
7072 }
dan5a78b812017-12-27 18:54:11 +00007073 }
drha5676c42018-01-10 15:17:34 +00007074 cmd.bZip = 1;
dan5a78b812017-12-27 18:54:11 +00007075 }else if( cmd.zFile ){
dand4b56e52017-12-12 20:04:59 +00007076 int flags;
drha5676c42018-01-10 15:17:34 +00007077 if( cmd.bAppend ) eDbType = SHELL_OPEN_APPENDVFS;
drhb17ea912019-03-25 14:24:19 +00007078 if( cmd.eCmd==AR_CMD_CREATE || cmd.eCmd==AR_CMD_INSERT
larrybr47061b92021-11-01 17:22:52 +00007079 || cmd.eCmd==AR_CMD_REMOVE || cmd.eCmd==AR_CMD_UPDATE ){
dand4b56e52017-12-12 20:04:59 +00007080 flags = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE;
7081 }else{
7082 flags = SQLITE_OPEN_READONLY;
7083 }
drha82c95b2018-01-10 14:00:00 +00007084 cmd.db = 0;
drha5676c42018-01-10 15:17:34 +00007085 if( cmd.bDryRun ){
7086 utf8_printf(pState->out, "-- open database '%s'%s\n", cmd.zFile,
7087 eDbType==SHELL_OPEN_APPENDVFS ? " using 'apndvfs'" : "");
7088 }
7089 rc = sqlite3_open_v2(cmd.zFile, &cmd.db, flags,
7090 eDbType==SHELL_OPEN_APPENDVFS ? "apndvfs" : 0);
dand4b56e52017-12-12 20:04:59 +00007091 if( rc!=SQLITE_OK ){
drhb376b3d2018-01-10 13:11:51 +00007092 utf8_printf(stderr, "cannot open file: %s (%s)\n",
7093 cmd.zFile, sqlite3_errmsg(cmd.db)
dand4b56e52017-12-12 20:04:59 +00007094 );
drha5676c42018-01-10 15:17:34 +00007095 goto end_ar_command;
dand4b56e52017-12-12 20:04:59 +00007096 }
drhb376b3d2018-01-10 13:11:51 +00007097 sqlite3_fileio_init(cmd.db, 0, 0);
drhb376b3d2018-01-10 13:11:51 +00007098 sqlite3_sqlar_init(cmd.db, 0, 0);
drh34660642018-01-10 17:39:54 +00007099 sqlite3_create_function(cmd.db, "shell_putsnl", 1, SQLITE_UTF8, cmd.p,
7100 shellPutsFunc, 0, 0);
7101
dand4b56e52017-12-12 20:04:59 +00007102 }
drhd0f9cdc2018-05-17 14:09:06 +00007103 if( cmd.zSrcTable==0 && cmd.bZip==0 && cmd.eCmd!=AR_CMD_HELP ){
drh634c70f2018-01-10 16:50:18 +00007104 if( cmd.eCmd!=AR_CMD_CREATE
7105 && sqlite3_table_column_metadata(cmd.db,0,"sqlar","name",0,0,0,0,0)
7106 ){
drha5676c42018-01-10 15:17:34 +00007107 utf8_printf(stderr, "database does not contain an 'sqlar' table\n");
7108 rc = SQLITE_ERROR;
7109 goto end_ar_command;
7110 }
7111 cmd.zSrcTable = sqlite3_mprintf("sqlar");
7112 }
dand4b56e52017-12-12 20:04:59 +00007113
dan88be0202017-12-09 17:58:02 +00007114 switch( cmd.eCmd ){
7115 case AR_CMD_CREATE:
drhb17ea912019-03-25 14:24:19 +00007116 rc = arCreateOrUpdateCommand(&cmd, 0, 0);
dan88be0202017-12-09 17:58:02 +00007117 break;
danfd0245d2017-12-07 15:44:29 +00007118
dan88be0202017-12-09 17:58:02 +00007119 case AR_CMD_EXTRACT:
drhb376b3d2018-01-10 13:11:51 +00007120 rc = arExtractCommand(&cmd);
dan88be0202017-12-09 17:58:02 +00007121 break;
7122
7123 case AR_CMD_LIST:
drhb376b3d2018-01-10 13:11:51 +00007124 rc = arListCommand(&cmd);
dan88be0202017-12-09 17:58:02 +00007125 break;
7126
dan0d0547f2017-12-14 15:40:42 +00007127 case AR_CMD_HELP:
7128 arUsage(pState->out);
7129 break;
7130
drhb17ea912019-03-25 14:24:19 +00007131 case AR_CMD_INSERT:
7132 rc = arCreateOrUpdateCommand(&cmd, 1, 0);
7133 break;
7134
larrybr47061b92021-11-01 17:22:52 +00007135 case AR_CMD_REMOVE:
7136 rc = arRemoveCommand(&cmd);
7137 break;
7138
dan88be0202017-12-09 17:58:02 +00007139 default:
7140 assert( cmd.eCmd==AR_CMD_UPDATE );
drhb17ea912019-03-25 14:24:19 +00007141 rc = arCreateOrUpdateCommand(&cmd, 1, 1);
dan88be0202017-12-09 17:58:02 +00007142 break;
danfd0245d2017-12-07 15:44:29 +00007143 }
7144 }
drha5676c42018-01-10 15:17:34 +00007145end_ar_command:
7146 if( cmd.db!=pState->db ){
drh9e804032018-05-18 17:11:50 +00007147 close_db(cmd.db);
drha5676c42018-01-10 15:17:34 +00007148 }
7149 sqlite3_free(cmd.zSrcTable);
danfd0245d2017-12-07 15:44:29 +00007150
dan88be0202017-12-09 17:58:02 +00007151 return rc;
danfd0245d2017-12-07 15:44:29 +00007152}
drhe37c0e12018-01-06 19:19:50 +00007153/* End of the ".archive" or ".ar" command logic
drhe2754c12019-08-26 12:50:01 +00007154*******************************************************************************/
drhe37c0e12018-01-06 19:19:50 +00007155#endif /* !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB) */
danfd0245d2017-12-07 15:44:29 +00007156
dan1b162162019-04-27 20:15:15 +00007157#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
dan42ebb012019-04-27 18:47:03 +00007158/*
7159** If (*pRc) is not SQLITE_OK when this function is called, it is a no-op.
7160** Otherwise, the SQL statement or statements in zSql are executed using
7161** database connection db and the error code written to *pRc before
7162** this function returns.
7163*/
dan68cb86e2019-04-20 20:57:28 +00007164static void shellExec(sqlite3 *db, int *pRc, const char *zSql){
7165 int rc = *pRc;
7166 if( rc==SQLITE_OK ){
7167 char *zErr = 0;
7168 rc = sqlite3_exec(db, zSql, 0, 0, &zErr);
7169 if( rc!=SQLITE_OK ){
7170 raw_printf(stderr, "SQL error: %s\n", zErr);
7171 }
drhf83d5012021-05-03 13:35:00 +00007172 sqlite3_free(zErr);
dan68cb86e2019-04-20 20:57:28 +00007173 *pRc = rc;
7174 }
7175}
7176
dan42ebb012019-04-27 18:47:03 +00007177/*
7178** Like shellExec(), except that zFmt is a printf() style format string.
7179*/
danc0b42432019-04-26 15:14:53 +00007180static void shellExecPrintf(sqlite3 *db, int *pRc, const char *zFmt, ...){
7181 char *z = 0;
7182 if( *pRc==SQLITE_OK ){
7183 va_list ap;
7184 va_start(ap, zFmt);
7185 z = sqlite3_vmprintf(zFmt, ap);
7186 va_end(ap);
7187 if( z==0 ){
7188 *pRc = SQLITE_NOMEM;
7189 }else{
7190 shellExec(db, pRc, z);
7191 }
7192 sqlite3_free(z);
7193 }
7194}
7195
dan42ebb012019-04-27 18:47:03 +00007196/*
7197** If *pRc is not SQLITE_OK when this function is called, it is a no-op.
7198** Otherwise, an attempt is made to allocate, zero and return a pointer
7199** to a buffer nByte bytes in size. If an OOM error occurs, *pRc is set
7200** to SQLITE_NOMEM and NULL returned.
7201*/
dan68cb86e2019-04-20 20:57:28 +00007202static void *shellMalloc(int *pRc, sqlite3_int64 nByte){
7203 void *pRet = 0;
7204 if( *pRc==SQLITE_OK ){
7205 pRet = sqlite3_malloc64(nByte);
7206 if( pRet==0 ){
7207 *pRc = SQLITE_NOMEM;
7208 }else{
7209 memset(pRet, 0, nByte);
7210 }
7211 }
7212 return pRet;
7213}
7214
dan42ebb012019-04-27 18:47:03 +00007215/*
7216** If *pRc is not SQLITE_OK when this function is called, it is a no-op.
7217** Otherwise, zFmt is treated as a printf() style string. The result of
7218** formatting it along with any trailing arguments is written into a
7219** buffer obtained from sqlite3_malloc(), and pointer to which is returned.
7220** It is the responsibility of the caller to eventually free this buffer
7221** using a call to sqlite3_free().
7222**
7223** If an OOM error occurs, (*pRc) is set to SQLITE_NOMEM and a NULL
7224** pointer returned.
7225*/
dan68cb86e2019-04-20 20:57:28 +00007226static char *shellMPrintf(int *pRc, const char *zFmt, ...){
7227 char *z = 0;
7228 if( *pRc==SQLITE_OK ){
7229 va_list ap;
7230 va_start(ap, zFmt);
7231 z = sqlite3_vmprintf(zFmt, ap);
7232 va_end(ap);
7233 if( z==0 ){
7234 *pRc = SQLITE_NOMEM;
7235 }
7236 }
7237 return z;
7238}
7239
larrybr58a53d62022-02-10 03:21:48 +00007240
dan42ebb012019-04-27 18:47:03 +00007241/*
7242** When running the ".recover" command, each output table, and the special
7243** orphaned row table if it is required, is represented by an instance
7244** of the following struct.
7245*/
dan68cb86e2019-04-20 20:57:28 +00007246typedef struct RecoverTable RecoverTable;
7247struct RecoverTable {
dan42ebb012019-04-27 18:47:03 +00007248 char *zQuoted; /* Quoted version of table name */
dan68cb86e2019-04-20 20:57:28 +00007249 int nCol; /* Number of columns in table */
7250 char **azlCol; /* Array of column lists */
dan42ebb012019-04-27 18:47:03 +00007251 int iPk; /* Index of IPK column */
dan68cb86e2019-04-20 20:57:28 +00007252};
7253
7254/*
dan42ebb012019-04-27 18:47:03 +00007255** Free a RecoverTable object allocated by recoverFindTable() or
7256** recoverOrphanTable().
dan68cb86e2019-04-20 20:57:28 +00007257*/
7258static void recoverFreeTable(RecoverTable *pTab){
7259 if( pTab ){
dan68cb86e2019-04-20 20:57:28 +00007260 sqlite3_free(pTab->zQuoted);
dan68cb86e2019-04-20 20:57:28 +00007261 if( pTab->azlCol ){
7262 int i;
dan98c5ad32019-04-26 21:11:37 +00007263 for(i=0; i<=pTab->nCol; i++){
dan68cb86e2019-04-20 20:57:28 +00007264 sqlite3_free(pTab->azlCol[i]);
7265 }
7266 sqlite3_free(pTab->azlCol);
7267 }
7268 sqlite3_free(pTab);
7269 }
7270}
7271
dan42ebb012019-04-27 18:47:03 +00007272/*
7273** This function is a no-op if (*pRc) is not SQLITE_OK when it is called.
7274** Otherwise, it allocates and returns a RecoverTable object based on the
7275** final four arguments passed to this function. It is the responsibility
7276** of the caller to eventually free the returned object using
7277** recoverFreeTable().
7278*/
7279static RecoverTable *recoverNewTable(
danb40af492019-04-22 20:52:12 +00007280 int *pRc, /* IN/OUT: Error code */
danb40af492019-04-22 20:52:12 +00007281 const char *zName, /* Name of table */
7282 const char *zSql, /* CREATE TABLE statement */
7283 int bIntkey,
7284 int nCol
7285){
7286 sqlite3 *dbtmp = 0; /* sqlite3 handle for testing CREATE TABLE */
7287 int rc = *pRc;
dan98c5ad32019-04-26 21:11:37 +00007288 RecoverTable *pTab = 0;
danb40af492019-04-22 20:52:12 +00007289
dan98c5ad32019-04-26 21:11:37 +00007290 pTab = (RecoverTable*)shellMalloc(&rc, sizeof(RecoverTable));
danb40af492019-04-22 20:52:12 +00007291 if( rc==SQLITE_OK ){
7292 int nSqlCol = 0;
7293 int bSqlIntkey = 0;
7294 sqlite3_stmt *pStmt = 0;
dan98c5ad32019-04-26 21:11:37 +00007295
danb40af492019-04-22 20:52:12 +00007296 rc = sqlite3_open("", &dbtmp);
7297 if( rc==SQLITE_OK ){
drha2de66c2019-08-06 20:26:17 +00007298 sqlite3_create_function(dbtmp, "shell_idquote", 1, SQLITE_UTF8, 0,
7299 shellIdQuote, 0, 0);
7300 }
7301 if( rc==SQLITE_OK ){
dan38f9c712019-04-23 18:03:02 +00007302 rc = sqlite3_exec(dbtmp, "PRAGMA writable_schema = on", 0, 0, 0);
7303 }
7304 if( rc==SQLITE_OK ){
danb40af492019-04-22 20:52:12 +00007305 rc = sqlite3_exec(dbtmp, zSql, 0, 0, 0);
7306 if( rc==SQLITE_ERROR ){
7307 rc = SQLITE_OK;
7308 goto finished;
7309 }
7310 }
7311 shellPreparePrintf(dbtmp, &rc, &pStmt,
7312 "SELECT count(*) FROM pragma_table_info(%Q)", zName
7313 );
7314 if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
7315 nSqlCol = sqlite3_column_int(pStmt, 0);
7316 }
7317 shellFinalize(&rc, pStmt);
7318
7319 if( rc!=SQLITE_OK || nSqlCol<nCol ){
7320 goto finished;
7321 }
7322
7323 shellPreparePrintf(dbtmp, &rc, &pStmt,
7324 "SELECT ("
7325 " SELECT substr(data,1,1)==X'0D' FROM sqlite_dbpage WHERE pgno=rootpage"
drh067b92b2020-06-19 15:24:12 +00007326 ") FROM sqlite_schema WHERE name = %Q", zName
danb40af492019-04-22 20:52:12 +00007327 );
7328 if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
7329 bSqlIntkey = sqlite3_column_int(pStmt, 0);
7330 }
7331 shellFinalize(&rc, pStmt);
7332
7333 if( bIntkey==bSqlIntkey ){
dan98c5ad32019-04-26 21:11:37 +00007334 int i;
danb40af492019-04-22 20:52:12 +00007335 const char *zPk = "_rowid_";
7336 sqlite3_stmt *pPkFinder = 0;
7337
danf57bea32019-04-27 15:35:45 +00007338 /* If this is an intkey table and there is an INTEGER PRIMARY KEY,
7339 ** set zPk to the name of the PK column, and pTab->iPk to the index
7340 ** of the column, where columns are 0-numbered from left to right.
7341 ** Or, if this is a WITHOUT ROWID table or if there is no IPK column,
7342 ** leave zPk as "_rowid_" and pTab->iPk at -2. */
dan98c5ad32019-04-26 21:11:37 +00007343 pTab->iPk = -2;
7344 if( bIntkey ){
7345 shellPreparePrintf(dbtmp, &rc, &pPkFinder,
danb40af492019-04-22 20:52:12 +00007346 "SELECT cid, name FROM pragma_table_info(%Q) "
7347 " WHERE pk=1 AND type='integer' COLLATE nocase"
dan98c5ad32019-04-26 21:11:37 +00007348 " AND NOT EXISTS (SELECT cid FROM pragma_table_info(%Q) WHERE pk=2)"
7349 , zName, zName
7350 );
7351 if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pPkFinder) ){
7352 pTab->iPk = sqlite3_column_int(pPkFinder, 0);
7353 zPk = (const char*)sqlite3_column_text(pPkFinder, 1);
drh621a5e02021-12-16 17:35:27 +00007354 if( zPk==0 ){ zPk = "_"; /* Defensive. Should never happen */ }
dan98c5ad32019-04-26 21:11:37 +00007355 }
danb40af492019-04-22 20:52:12 +00007356 }
7357
drha2de66c2019-08-06 20:26:17 +00007358 pTab->zQuoted = shellMPrintf(&rc, "\"%w\"", zName);
dan98c5ad32019-04-26 21:11:37 +00007359 pTab->azlCol = (char**)shellMalloc(&rc, sizeof(char*) * (nSqlCol+1));
danb40af492019-04-22 20:52:12 +00007360 pTab->nCol = nSqlCol;
7361
dan98c5ad32019-04-26 21:11:37 +00007362 if( bIntkey ){
drha2de66c2019-08-06 20:26:17 +00007363 pTab->azlCol[0] = shellMPrintf(&rc, "\"%w\"", zPk);
danb40af492019-04-22 20:52:12 +00007364 }else{
dan98c5ad32019-04-26 21:11:37 +00007365 pTab->azlCol[0] = shellMPrintf(&rc, "");
danb40af492019-04-22 20:52:12 +00007366 }
dan98c5ad32019-04-26 21:11:37 +00007367 i = 1;
7368 shellPreparePrintf(dbtmp, &rc, &pStmt,
drha2de66c2019-08-06 20:26:17 +00007369 "SELECT %Q || group_concat(shell_idquote(name), ', ') "
danf57bea32019-04-27 15:35:45 +00007370 " FILTER (WHERE cid!=%d) OVER (ORDER BY %s cid) "
dan98c5ad32019-04-26 21:11:37 +00007371 "FROM pragma_table_info(%Q)",
danf57bea32019-04-27 15:35:45 +00007372 bIntkey ? ", " : "", pTab->iPk,
7373 bIntkey ? "" : "(CASE WHEN pk=0 THEN 1000000 ELSE pk END), ",
7374 zName
dan98c5ad32019-04-26 21:11:37 +00007375 );
7376 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
7377 const char *zText = (const char*)sqlite3_column_text(pStmt, 0);
7378 pTab->azlCol[i] = shellMPrintf(&rc, "%s%s", pTab->azlCol[0], zText);
7379 i++;
7380 }
7381 shellFinalize(&rc, pStmt);
7382
danb40af492019-04-22 20:52:12 +00007383 shellFinalize(&rc, pPkFinder);
7384 }
7385 }
7386
7387 finished:
7388 sqlite3_close(dbtmp);
7389 *pRc = rc;
dan98779652019-05-09 14:15:19 +00007390 if( rc!=SQLITE_OK || (pTab && pTab->zQuoted==0) ){
dan98c5ad32019-04-26 21:11:37 +00007391 recoverFreeTable(pTab);
7392 pTab = 0;
7393 }
7394 return pTab;
danb40af492019-04-22 20:52:12 +00007395}
7396
dan0aa01ee2019-04-27 19:36:49 +00007397/*
7398** This function is called to search the schema recovered from the
drh067b92b2020-06-19 15:24:12 +00007399** sqlite_schema table of the (possibly) corrupt database as part
dan0aa01ee2019-04-27 19:36:49 +00007400** of a ".recover" command. Specifically, for a table with root page
7401** iRoot and at least nCol columns. Additionally, if bIntkey is 0, the
7402** table must be a WITHOUT ROWID table, or if non-zero, not one of
7403** those.
7404**
7405** If a table is found, a (RecoverTable*) object is returned. Or, if
7406** no such table is found, but bIntkey is false and iRoot is the
7407** root page of an index in the recovered schema, then (*pbNoop) is
7408** set to true and NULL returned. Or, if there is no such table or
7409** index, NULL is returned and (*pbNoop) set to 0, indicating that
7410** the caller should write data to the orphans table.
7411*/
dan42ebb012019-04-27 18:47:03 +00007412static RecoverTable *recoverFindTable(
dan0aa01ee2019-04-27 19:36:49 +00007413 ShellState *pState, /* Shell state object */
7414 int *pRc, /* IN/OUT: Error code */
7415 int iRoot, /* Root page of table */
7416 int bIntkey, /* True for an intkey table */
7417 int nCol, /* Number of columns in table */
7418 int *pbNoop /* OUT: True if iRoot is root of index */
dan68cb86e2019-04-20 20:57:28 +00007419){
danb40af492019-04-22 20:52:12 +00007420 sqlite3_stmt *pStmt = 0;
dan68cb86e2019-04-20 20:57:28 +00007421 RecoverTable *pRet = 0;
danb40af492019-04-22 20:52:12 +00007422 int bNoop = 0;
7423 const char *zSql = 0;
7424 const char *zName = 0;
dan68cb86e2019-04-20 20:57:28 +00007425
danb40af492019-04-22 20:52:12 +00007426 /* Search the recovered schema for an object with root page iRoot. */
7427 shellPreparePrintf(pState->db, pRc, &pStmt,
7428 "SELECT type, name, sql FROM recovery.schema WHERE rootpage=%d", iRoot
7429 );
7430 while( *pRc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
7431 const char *zType = (const char*)sqlite3_column_text(pStmt, 0);
7432 if( bIntkey==0 && sqlite3_stricmp(zType, "index")==0 ){
7433 bNoop = 1;
7434 break;
7435 }
7436 if( sqlite3_stricmp(zType, "table")==0 ){
7437 zName = (const char*)sqlite3_column_text(pStmt, 1);
7438 zSql = (const char*)sqlite3_column_text(pStmt, 2);
drh621a5e02021-12-16 17:35:27 +00007439 if( zName!=0 && zSql!=0 ){
7440 pRet = recoverNewTable(pRc, zName, zSql, bIntkey, nCol);
7441 break;
7442 }
danb40af492019-04-22 20:52:12 +00007443 }
7444 }
dan98c5ad32019-04-26 21:11:37 +00007445
danb40af492019-04-22 20:52:12 +00007446 shellFinalize(pRc, pStmt);
dan98c5ad32019-04-26 21:11:37 +00007447 *pbNoop = bNoop;
7448 return pRet;
7449}
danb40af492019-04-22 20:52:12 +00007450
dan0aa01ee2019-04-27 19:36:49 +00007451/*
7452** Return a RecoverTable object representing the orphans table.
7453*/
dan98c5ad32019-04-26 21:11:37 +00007454static RecoverTable *recoverOrphanTable(
dan0aa01ee2019-04-27 19:36:49 +00007455 ShellState *pState, /* Shell state object */
7456 int *pRc, /* IN/OUT: Error code */
7457 const char *zLostAndFound, /* Base name for orphans table */
7458 int nCol /* Number of user data columns */
dan98c5ad32019-04-26 21:11:37 +00007459){
7460 RecoverTable *pTab = 0;
7461 if( nCol>=0 && *pRc==SQLITE_OK ){
7462 int i;
dan42ebb012019-04-27 18:47:03 +00007463
7464 /* This block determines the name of the orphan table. The prefered
7465 ** name is zLostAndFound. But if that clashes with another name
7466 ** in the recovered schema, try zLostAndFound_0, zLostAndFound_1
7467 ** and so on until a non-clashing name is found. */
7468 int iTab = 0;
7469 char *zTab = shellMPrintf(pRc, "%s", zLostAndFound);
7470 sqlite3_stmt *pTest = 0;
7471 shellPrepare(pState->db, pRc,
7472 "SELECT 1 FROM recovery.schema WHERE name=?", &pTest
dan68cb86e2019-04-20 20:57:28 +00007473 );
dan42ebb012019-04-27 18:47:03 +00007474 if( pTest ) sqlite3_bind_text(pTest, 1, zTab, -1, SQLITE_TRANSIENT);
7475 while( *pRc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pTest) ){
7476 shellReset(pRc, pTest);
7477 sqlite3_free(zTab);
7478 zTab = shellMPrintf(pRc, "%s_%d", zLostAndFound, iTab++);
7479 sqlite3_bind_text(pTest, 1, zTab, -1, SQLITE_TRANSIENT);
dan68cb86e2019-04-20 20:57:28 +00007480 }
dan42ebb012019-04-27 18:47:03 +00007481 shellFinalize(pRc, pTest);
dan68cb86e2019-04-20 20:57:28 +00007482
dan98c5ad32019-04-26 21:11:37 +00007483 pTab = (RecoverTable*)shellMalloc(pRc, sizeof(RecoverTable));
7484 if( pTab ){
drha2de66c2019-08-06 20:26:17 +00007485 pTab->zQuoted = shellMPrintf(pRc, "\"%w\"", zTab);
dan98c5ad32019-04-26 21:11:37 +00007486 pTab->nCol = nCol;
7487 pTab->iPk = -2;
7488 if( nCol>0 ){
7489 pTab->azlCol = (char**)shellMalloc(pRc, sizeof(char*) * (nCol+1));
7490 if( pTab->azlCol ){
7491 pTab->azlCol[nCol] = shellMPrintf(pRc, "");
7492 for(i=nCol-1; i>=0; i--){
7493 pTab->azlCol[i] = shellMPrintf(pRc, "%s, NULL", pTab->azlCol[i+1]);
7494 }
7495 }
danb40af492019-04-22 20:52:12 +00007496 }
dan68cb86e2019-04-20 20:57:28 +00007497
dan42ebb012019-04-27 18:47:03 +00007498 if( *pRc!=SQLITE_OK ){
7499 recoverFreeTable(pTab);
7500 pTab = 0;
7501 }else{
7502 raw_printf(pState->out,
7503 "CREATE TABLE %s(rootpgno INTEGER, "
7504 "pgno INTEGER, nfield INTEGER, id INTEGER", pTab->zQuoted
7505 );
7506 for(i=0; i<nCol; i++){
7507 raw_printf(pState->out, ", c%d", i);
7508 }
7509 raw_printf(pState->out, ");\n");
7510 }
dan98c5ad32019-04-26 21:11:37 +00007511 }
dan42ebb012019-04-27 18:47:03 +00007512 sqlite3_free(zTab);
dan68cb86e2019-04-20 20:57:28 +00007513 }
dan98c5ad32019-04-26 21:11:37 +00007514 return pTab;
dan68cb86e2019-04-20 20:57:28 +00007515}
7516
7517/*
7518** This function is called to recover data from the database. A script
7519** to construct a new database containing all recovered data is output
7520** on stream pState->out.
7521*/
danb9b71db2019-04-25 16:20:40 +00007522static int recoverDatabaseCmd(ShellState *pState, int nArg, char **azArg){
dan68cb86e2019-04-20 20:57:28 +00007523 int rc = SQLITE_OK;
7524 sqlite3_stmt *pLoop = 0; /* Loop through all root pages */
danefa363b2019-04-24 20:48:55 +00007525 sqlite3_stmt *pPages = 0; /* Loop through all pages in a group */
7526 sqlite3_stmt *pCells = 0; /* Loop through all cells in a page */
danc0b42432019-04-26 15:14:53 +00007527 const char *zRecoveryDb = ""; /* Name of "recovery" database */
dan42ebb012019-04-27 18:47:03 +00007528 const char *zLostAndFound = "lost_and_found";
dan9c014f82019-04-25 19:23:15 +00007529 int i;
dan98c5ad32019-04-26 21:11:37 +00007530 int nOrphan = -1;
7531 RecoverTable *pOrphan = 0;
dan9c014f82019-04-25 19:23:15 +00007532
7533 int bFreelist = 1; /* 0 if --freelist-corrupt is specified */
dan8cce6b82019-09-14 16:44:51 +00007534 int bRowids = 1; /* 0 if --no-rowids */
dan9c014f82019-04-25 19:23:15 +00007535 for(i=1; i<nArg; i++){
7536 char *z = azArg[i];
7537 int n;
7538 if( z[0]=='-' && z[1]=='-' ) z++;
drh4245e042019-06-13 13:52:46 +00007539 n = strlen30(z);
dan9c014f82019-04-25 19:23:15 +00007540 if( n<=17 && memcmp("-freelist-corrupt", z, n)==0 ){
7541 bFreelist = 0;
dan42ebb012019-04-27 18:47:03 +00007542 }else
danc0b42432019-04-26 15:14:53 +00007543 if( n<=12 && memcmp("-recovery-db", z, n)==0 && i<(nArg-1) ){
7544 i++;
7545 zRecoveryDb = azArg[i];
dan42ebb012019-04-27 18:47:03 +00007546 }else
7547 if( n<=15 && memcmp("-lost-and-found", z, n)==0 && i<(nArg-1) ){
7548 i++;
7549 zLostAndFound = azArg[i];
dan8cce6b82019-09-14 16:44:51 +00007550 }else
7551 if( n<=10 && memcmp("-no-rowids", z, n)==0 ){
7552 bRowids = 0;
danc0b42432019-04-26 15:14:53 +00007553 }
dan9c014f82019-04-25 19:23:15 +00007554 else{
drhe2754c12019-08-26 12:50:01 +00007555 utf8_printf(stderr, "unexpected option: %s\n", azArg[i]);
7556 showHelp(pState->out, azArg[0]);
dan9c014f82019-04-25 19:23:15 +00007557 return 1;
7558 }
7559 }
dan68cb86e2019-04-20 20:57:28 +00007560
danc0b42432019-04-26 15:14:53 +00007561 shellExecPrintf(pState->db, &rc,
dan68cb86e2019-04-20 20:57:28 +00007562 /* Attach an in-memory database named 'recovery'. Create an indexed
7563 ** cache of the sqlite_dbptr virtual table. */
dan01c08bc2019-07-24 19:20:30 +00007564 "PRAGMA writable_schema = on;"
danc0b42432019-04-26 15:14:53 +00007565 "ATTACH %Q AS recovery;"
7566 "DROP TABLE IF EXISTS recovery.dbptr;"
7567 "DROP TABLE IF EXISTS recovery.freelist;"
7568 "DROP TABLE IF EXISTS recovery.map;"
7569 "DROP TABLE IF EXISTS recovery.schema;"
danc0b42432019-04-26 15:14:53 +00007570 "CREATE TABLE recovery.freelist(pgno INTEGER PRIMARY KEY);", zRecoveryDb
dan9c014f82019-04-25 19:23:15 +00007571 );
7572
7573 if( bFreelist ){
7574 shellExec(pState->db, &rc,
7575 "WITH trunk(pgno) AS ("
7576 " SELECT shell_int32("
7577 " (SELECT data FROM sqlite_dbpage WHERE pgno=1), 8) AS x "
7578 " WHERE x>0"
7579 " UNION"
7580 " SELECT shell_int32("
7581 " (SELECT data FROM sqlite_dbpage WHERE pgno=trunk.pgno), 0) AS x "
7582 " FROM trunk WHERE x>0"
7583 "),"
7584 "freelist(data, n, freepgno) AS ("
danf6099e92019-05-09 16:57:39 +00007585 " SELECT data, min(16384, shell_int32(data, 1)-1), t.pgno "
dan9c014f82019-04-25 19:23:15 +00007586 " FROM trunk t, sqlite_dbpage s WHERE s.pgno=t.pgno"
7587 " UNION ALL"
7588 " SELECT data, n-1, shell_int32(data, 2+n) "
7589 " FROM freelist WHERE n>=0"
7590 ")"
7591 "REPLACE INTO recovery.freelist SELECT freepgno FROM freelist;"
7592 );
7593 }
7594
dan95063c22019-07-24 08:15:09 +00007595 /* If this is an auto-vacuum database, add all pointer-map pages to
7596 ** the freelist table. Do this regardless of whether or not
7597 ** --freelist-corrupt was specified. */
7598 shellExec(pState->db, &rc,
7599 "WITH ptrmap(pgno) AS ("
7600 " SELECT 2 WHERE shell_int32("
7601 " (SELECT data FROM sqlite_dbpage WHERE pgno=1), 13"
7602 " )"
7603 " UNION ALL "
7604 " SELECT pgno+1+(SELECT page_size FROM pragma_page_size)/5 AS pp "
7605 " FROM ptrmap WHERE pp<=(SELECT page_count FROM pragma_page_count)"
7606 ")"
7607 "REPLACE INTO recovery.freelist SELECT pgno FROM ptrmap"
7608 );
7609
dan9c014f82019-04-25 19:23:15 +00007610 shellExec(pState->db, &rc,
danca424382019-04-26 15:40:27 +00007611 "CREATE TABLE recovery.dbptr("
7612 " pgno, child, PRIMARY KEY(child, pgno)"
7613 ") WITHOUT ROWID;"
7614 "INSERT OR IGNORE INTO recovery.dbptr(pgno, child) "
7615 " SELECT * FROM sqlite_dbptr"
7616 " WHERE pgno NOT IN freelist AND child NOT IN freelist;"
7617
7618 /* Delete any pointer to page 1. This ensures that page 1 is considered
7619 ** a root page, regardless of how corrupt the db is. */
7620 "DELETE FROM recovery.dbptr WHERE child = 1;"
7621
7622 /* Delete all pointers to any pages that have more than one pointer
7623 ** to them. Such pages will be treated as root pages when recovering
7624 ** data. */
7625 "DELETE FROM recovery.dbptr WHERE child IN ("
7626 " SELECT child FROM recovery.dbptr GROUP BY child HAVING count(*)>1"
7627 ");"
7628
dan68cb86e2019-04-20 20:57:28 +00007629 /* Create the "map" table that will (eventually) contain instructions
7630 ** for dealing with each page in the db that contains one or more
7631 ** records. */
danb40af492019-04-22 20:52:12 +00007632 "CREATE TABLE recovery.map("
7633 "pgno INTEGER PRIMARY KEY, maxlen INT, intkey, root INT"
7634 ");"
dan68cb86e2019-04-20 20:57:28 +00007635
7636 /* Populate table [map]. If there are circular loops of pages in the
7637 ** database, the following adds all pages in such a loop to the map
7638 ** as individual root pages. This could be handled better. */
7639 "WITH pages(i, maxlen) AS ("
danb9b71db2019-04-25 16:20:40 +00007640 " SELECT page_count, ("
7641 " SELECT max(field+1) FROM sqlite_dbdata WHERE pgno=page_count"
dan13b87672019-05-09 11:45:21 +00007642 " ) FROM pragma_page_count WHERE page_count>0"
dan68cb86e2019-04-20 20:57:28 +00007643 " UNION ALL"
danb40af492019-04-22 20:52:12 +00007644 " SELECT i-1, ("
7645 " SELECT max(field+1) FROM sqlite_dbdata WHERE pgno=i-1"
7646 " ) FROM pages WHERE i>=2"
dan68cb86e2019-04-20 20:57:28 +00007647 ")"
danb40af492019-04-22 20:52:12 +00007648 "INSERT INTO recovery.map(pgno, maxlen, intkey, root) "
7649 " SELECT i, maxlen, NULL, ("
dan68cb86e2019-04-20 20:57:28 +00007650 " WITH p(orig, pgno, parent) AS ("
7651 " SELECT 0, i, (SELECT pgno FROM recovery.dbptr WHERE child=i)"
dan39e04f82019-05-09 18:33:32 +00007652 " UNION "
dan68cb86e2019-04-20 20:57:28 +00007653 " SELECT i, p.parent, "
7654 " (SELECT pgno FROM recovery.dbptr WHERE child=p.parent) FROM p"
7655 " )"
7656 " SELECT pgno FROM p WHERE (parent IS NULL OR pgno = orig)"
7657 ") "
dand790c9a2019-08-26 14:57:58 +00007658 "FROM pages WHERE maxlen IS NOT NULL AND i NOT IN freelist;"
danb40af492019-04-22 20:52:12 +00007659 "UPDATE recovery.map AS o SET intkey = ("
7660 " SELECT substr(data, 1, 1)==X'0D' FROM sqlite_dbpage WHERE pgno=o.pgno"
7661 ");"
dan68cb86e2019-04-20 20:57:28 +00007662
7663 /* Extract data from page 1 and any linked pages into table
drh067b92b2020-06-19 15:24:12 +00007664 ** recovery.schema. With the same schema as an sqlite_schema table. */
dan68cb86e2019-04-20 20:57:28 +00007665 "CREATE TABLE recovery.schema(type, name, tbl_name, rootpage, sql);"
7666 "INSERT INTO recovery.schema SELECT "
7667 " max(CASE WHEN field=0 THEN value ELSE NULL END),"
7668 " max(CASE WHEN field=1 THEN value ELSE NULL END),"
7669 " max(CASE WHEN field=2 THEN value ELSE NULL END),"
7670 " max(CASE WHEN field=3 THEN value ELSE NULL END),"
7671 " max(CASE WHEN field=4 THEN value ELSE NULL END)"
7672 "FROM sqlite_dbdata WHERE pgno IN ("
7673 " SELECT pgno FROM recovery.map WHERE root=1"
7674 ")"
7675 "GROUP BY pgno, cell;"
dan98c5ad32019-04-26 21:11:37 +00007676 "CREATE INDEX recovery.schema_rootpage ON schema(rootpage);"
dan68cb86e2019-04-20 20:57:28 +00007677 );
7678
danb40af492019-04-22 20:52:12 +00007679 /* Open a transaction, then print out all non-virtual, non-"sqlite_%"
7680 ** CREATE TABLE statements that extracted from the existing schema. */
7681 if( rc==SQLITE_OK ){
7682 sqlite3_stmt *pStmt = 0;
danf3210572019-08-06 18:40:36 +00007683 /* ".recover" might output content in an order which causes immediate
7684 ** foreign key constraints to be violated. So disable foreign-key
7685 ** constraint enforcement to prevent problems when running the output
7686 ** script. */
7687 raw_printf(pState->out, "PRAGMA foreign_keys=OFF;\n");
danb40af492019-04-22 20:52:12 +00007688 raw_printf(pState->out, "BEGIN;\n");
dan38f9c712019-04-23 18:03:02 +00007689 raw_printf(pState->out, "PRAGMA writable_schema = on;\n");
7690 shellPrepare(pState->db, &rc,
danb40af492019-04-22 20:52:12 +00007691 "SELECT sql FROM recovery.schema "
dan38f9c712019-04-23 18:03:02 +00007692 "WHERE type='table' AND sql LIKE 'create table%'", &pStmt
danb40af492019-04-22 20:52:12 +00007693 );
7694 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
7695 const char *zCreateTable = (const char*)sqlite3_column_text(pStmt, 0);
dan38f9c712019-04-23 18:03:02 +00007696 raw_printf(pState->out, "CREATE TABLE IF NOT EXISTS %s;\n",
7697 &zCreateTable[12]
7698 );
danb40af492019-04-22 20:52:12 +00007699 }
7700 shellFinalize(&rc, pStmt);
7701 }
7702
dan98c5ad32019-04-26 21:11:37 +00007703 /* Figure out if an orphan table will be required. And if so, how many
7704 ** user columns it should contain */
7705 shellPrepare(pState->db, &rc,
dan98779652019-05-09 14:15:19 +00007706 "SELECT coalesce(max(maxlen), -2) FROM recovery.map WHERE root>1"
dan98c5ad32019-04-26 21:11:37 +00007707 , &pLoop
7708 );
7709 if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pLoop) ){
7710 nOrphan = sqlite3_column_int(pLoop, 0);
7711 }
7712 shellFinalize(&rc, pLoop);
7713 pLoop = 0;
dan98c5ad32019-04-26 21:11:37 +00007714
danefa363b2019-04-24 20:48:55 +00007715 shellPrepare(pState->db, &rc,
7716 "SELECT pgno FROM recovery.map WHERE root=?", &pPages
7717 );
dan8cce6b82019-09-14 16:44:51 +00007718
danefa363b2019-04-24 20:48:55 +00007719 shellPrepare(pState->db, &rc,
dan8cce6b82019-09-14 16:44:51 +00007720 "SELECT max(field), group_concat(shell_escape_crnl(quote"
7721 "(case when (? AND field<0) then NULL else value end)"
7722 "), ', ')"
dan9443dbc2019-07-24 20:10:27 +00007723 ", min(field) "
danefa363b2019-04-24 20:48:55 +00007724 "FROM sqlite_dbdata WHERE pgno = ? AND field != ?"
7725 "GROUP BY cell", &pCells
7726 );
7727
dan68cb86e2019-04-20 20:57:28 +00007728 /* Loop through each root page. */
danb40af492019-04-22 20:52:12 +00007729 shellPrepare(pState->db, &rc,
7730 "SELECT root, intkey, max(maxlen) FROM recovery.map"
dan38f9c712019-04-23 18:03:02 +00007731 " WHERE root>1 GROUP BY root, intkey ORDER BY root=("
7732 " SELECT rootpage FROM recovery.schema WHERE name='sqlite_sequence'"
7733 ")", &pLoop
danb40af492019-04-22 20:52:12 +00007734 );
dan68cb86e2019-04-20 20:57:28 +00007735 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pLoop) ){
7736 int iRoot = sqlite3_column_int(pLoop, 0);
danb40af492019-04-22 20:52:12 +00007737 int bIntkey = sqlite3_column_int(pLoop, 1);
7738 int nCol = sqlite3_column_int(pLoop, 2);
dan98c5ad32019-04-26 21:11:37 +00007739 int bNoop = 0;
dan68cb86e2019-04-20 20:57:28 +00007740 RecoverTable *pTab;
7741
dan9443dbc2019-07-24 20:10:27 +00007742 assert( bIntkey==0 || bIntkey==1 );
dan42ebb012019-04-27 18:47:03 +00007743 pTab = recoverFindTable(pState, &rc, iRoot, bIntkey, nCol, &bNoop);
dan98c5ad32019-04-26 21:11:37 +00007744 if( bNoop || rc ) continue;
dan98779652019-05-09 14:15:19 +00007745 if( pTab==0 ){
7746 if( pOrphan==0 ){
7747 pOrphan = recoverOrphanTable(pState, &rc, zLostAndFound, nOrphan);
7748 }
7749 pTab = pOrphan;
7750 if( pTab==0 ) break;
7751 }
dan98c5ad32019-04-26 21:11:37 +00007752
drha2de66c2019-08-06 20:26:17 +00007753 if( 0==sqlite3_stricmp(pTab->zQuoted, "\"sqlite_sequence\"") ){
dan98c5ad32019-04-26 21:11:37 +00007754 raw_printf(pState->out, "DELETE FROM sqlite_sequence;\n");
7755 }
7756 sqlite3_bind_int(pPages, 1, iRoot);
dan8cce6b82019-09-14 16:44:51 +00007757 if( bRowids==0 && pTab->iPk<0 ){
7758 sqlite3_bind_int(pCells, 1, 1);
7759 }else{
7760 sqlite3_bind_int(pCells, 1, 0);
7761 }
7762 sqlite3_bind_int(pCells, 3, pTab->iPk);
dan98c5ad32019-04-26 21:11:37 +00007763
7764 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pPages) ){
7765 int iPgno = sqlite3_column_int(pPages, 0);
dan8cce6b82019-09-14 16:44:51 +00007766 sqlite3_bind_int(pCells, 2, iPgno);
dan98c5ad32019-04-26 21:11:37 +00007767 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pCells) ){
7768 int nField = sqlite3_column_int(pCells, 0);
dan9443dbc2019-07-24 20:10:27 +00007769 int iMin = sqlite3_column_int(pCells, 2);
dan98c5ad32019-04-26 21:11:37 +00007770 const char *zVal = (const char*)sqlite3_column_text(pCells, 1);
7771
dan9443dbc2019-07-24 20:10:27 +00007772 RecoverTable *pTab2 = pTab;
7773 if( pTab!=pOrphan && (iMin<0)!=bIntkey ){
7774 if( pOrphan==0 ){
7775 pOrphan = recoverOrphanTable(pState, &rc, zLostAndFound, nOrphan);
7776 }
7777 pTab2 = pOrphan;
7778 if( pTab2==0 ) break;
7779 }
7780
dan98c5ad32019-04-26 21:11:37 +00007781 nField = nField+1;
dan9443dbc2019-07-24 20:10:27 +00007782 if( pTab2==pOrphan ){
dan98c5ad32019-04-26 21:11:37 +00007783 raw_printf(pState->out,
7784 "INSERT INTO %s VALUES(%d, %d, %d, %s%s%s);\n",
dan9443dbc2019-07-24 20:10:27 +00007785 pTab2->zQuoted, iRoot, iPgno, nField,
7786 iMin<0 ? "" : "NULL, ", zVal, pTab2->azlCol[nField]
dan98c5ad32019-04-26 21:11:37 +00007787 );
7788 }else{
danefa363b2019-04-24 20:48:55 +00007789 raw_printf(pState->out, "INSERT INTO %s(%s) VALUES( %s );\n",
dan9443dbc2019-07-24 20:10:27 +00007790 pTab2->zQuoted, pTab2->azlCol[nField], zVal
danefa363b2019-04-24 20:48:55 +00007791 );
7792 }
dan68cb86e2019-04-20 20:57:28 +00007793 }
dan98c5ad32019-04-26 21:11:37 +00007794 shellReset(&rc, pCells);
dan68cb86e2019-04-20 20:57:28 +00007795 }
dan98c5ad32019-04-26 21:11:37 +00007796 shellReset(&rc, pPages);
7797 if( pTab!=pOrphan ) recoverFreeTable(pTab);
dan68cb86e2019-04-20 20:57:28 +00007798 }
7799 shellFinalize(&rc, pLoop);
danefa363b2019-04-24 20:48:55 +00007800 shellFinalize(&rc, pPages);
7801 shellFinalize(&rc, pCells);
dan98c5ad32019-04-26 21:11:37 +00007802 recoverFreeTable(pOrphan);
dan68cb86e2019-04-20 20:57:28 +00007803
dan38f9c712019-04-23 18:03:02 +00007804 /* The rest of the schema */
danb40af492019-04-22 20:52:12 +00007805 if( rc==SQLITE_OK ){
dan38f9c712019-04-23 18:03:02 +00007806 sqlite3_stmt *pStmt = 0;
7807 shellPrepare(pState->db, &rc,
7808 "SELECT sql, name FROM recovery.schema "
danb1825882019-04-23 20:48:32 +00007809 "WHERE sql NOT LIKE 'create table%'", &pStmt
dan38f9c712019-04-23 18:03:02 +00007810 );
7811 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
7812 const char *zSql = (const char*)sqlite3_column_text(pStmt, 0);
7813 if( sqlite3_strnicmp(zSql, "create virt", 11)==0 ){
7814 const char *zName = (const char*)sqlite3_column_text(pStmt, 1);
7815 char *zPrint = shellMPrintf(&rc,
drh067b92b2020-06-19 15:24:12 +00007816 "INSERT INTO sqlite_schema VALUES('table', %Q, %Q, 0, %Q)",
dan38f9c712019-04-23 18:03:02 +00007817 zName, zName, zSql
7818 );
7819 raw_printf(pState->out, "%s;\n", zPrint);
7820 sqlite3_free(zPrint);
7821 }else{
7822 raw_printf(pState->out, "%s;\n", zSql);
7823 }
7824 }
7825 shellFinalize(&rc, pStmt);
7826 }
7827
7828 if( rc==SQLITE_OK ){
7829 raw_printf(pState->out, "PRAGMA writable_schema = off;\n");
danb40af492019-04-22 20:52:12 +00007830 raw_printf(pState->out, "COMMIT;\n");
7831 }
dan68cb86e2019-04-20 20:57:28 +00007832 sqlite3_exec(pState->db, "DETACH recovery", 0, 0, 0);
7833 return rc;
7834}
dan1b162162019-04-27 20:15:15 +00007835#endif /* !(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB) */
dan68cb86e2019-04-20 20:57:28 +00007836
larrybr42de1c52022-02-13 22:18:22 +00007837
larrybr2d27d362022-04-16 17:53:25 +00007838/*
larrybr42de1c52022-02-13 22:18:22 +00007839 * zAutoColumn(zCol, &db, ?) => Maybe init db, add column zCol to it.
7840 * zAutoColumn(0, &db, ?) => (db!=0) Form columns spec for CREATE TABLE,
7841 * close db and set it to 0, and return the columns spec, to later
7842 * be sqlite3_free()'ed by the caller.
7843 * The return is 0 when either:
7844 * (a) The db was not initialized and zCol==0 (There are no columns.)
7845 * (b) zCol!=0 (Column was added, db initialized as needed.)
7846 * The 3rd argument, pRenamed, references an out parameter. If the
larrybr33633862022-02-14 01:12:46 +00007847 * pointer is non-zero, its referent will be set to a summary of renames
7848 * done if renaming was necessary, or set to 0 if none was done. The out
7849 * string (if any) must be sqlite3_free()'ed by the caller.
larrybr42de1c52022-02-13 22:18:22 +00007850 */
7851#ifdef SHELL_DEBUG
7852#define rc_err_oom_die(rc) \
7853 if( rc==SQLITE_NOMEM ) shell_check_oom(0); \
7854 else if(!(rc==SQLITE_OK||rc==SQLITE_DONE)) \
7855 fprintf(stderr,"E:%d\n",rc), assert(0)
7856#else
7857static void rc_err_oom_die(int rc){
7858 if( rc==SQLITE_NOMEM ) shell_check_oom(0);
7859 assert(rc==SQLITE_OK||rc==SQLITE_DONE);
7860}
7861#endif
7862
7863#ifdef SHELL_COLFIX_DB /* If this is set, the DB can be in a file. */
7864static char zCOL_DB[] = SHELL_STRINGIFY(SHELL_COLFIX_DB);
7865#else /* Otherwise, memory is faster/better for the transient DB. */
7866static const char *zCOL_DB = ":memory:";
7867#endif
7868
7869/* Define character (as C string) to separate generated column ordinal
7870 * from protected part of incoming column names. This defaults to "_"
7871 * so that incoming column identifiers that did not need not be quoted
7872 * remain usable without being quoted. It must be one character.
7873 */
7874#ifndef SHELL_AUTOCOLUMN_SEP
7875# define AUTOCOLUMN_SEP "_"
7876#else
7877# define AUTOCOLUMN_SEP SHELL_STRINGIFY(SHELL_AUTOCOLUMN_SEP)
7878#endif
7879
larrybr33633862022-02-14 01:12:46 +00007880static char *zAutoColumn(const char *zColNew, sqlite3 **pDb, char **pzRenamed){
larrybr42de1c52022-02-13 22:18:22 +00007881 /* Queries and D{D,M}L used here */
7882 static const char * const zTabMake = "\
7883CREATE TABLE ColNames(\
7884 cpos INTEGER PRIMARY KEY,\
larrybr33633862022-02-14 01:12:46 +00007885 name TEXT, nlen INT, chop INT, reps INT, suff TEXT);\
7886CREATE VIEW RepeatedNames AS \
7887SELECT DISTINCT t.name FROM ColNames t \
7888WHERE t.name COLLATE NOCASE IN (\
7889 SELECT o.name FROM ColNames o WHERE o.cpos<>t.cpos\
7890);\
larrybr42de1c52022-02-13 22:18:22 +00007891";
7892 static const char * const zTabFill = "\
7893INSERT INTO ColNames(name,nlen,chop,reps,suff)\
7894 VALUES(iif(length(?1)>0,?1,'?'),max(length(?1),1),0,0,'')\
7895";
7896 static const char * const zHasDupes = "\
7897SELECT count(DISTINCT (substring(name,1,nlen-chop)||suff) COLLATE NOCASE)\
7898 <count(name) FROM ColNames\
7899";
larrybr33633862022-02-14 01:12:46 +00007900#ifdef SHELL_COLUMN_RENAME_CLEAN
larrybr42de1c52022-02-13 22:18:22 +00007901 static const char * const zDedoctor = "\
7902UPDATE ColNames SET chop=iif(\
7903 (substring(name,nlen,1) BETWEEN '0' AND '9')\
7904 AND (rtrim(name,'0123456790') glob '*"AUTOCOLUMN_SEP"'),\
7905 nlen-length(rtrim(name, '"AUTOCOLUMN_SEP"0123456789')),\
7906 0\
7907)\
7908";
larrybr33633862022-02-14 01:12:46 +00007909#endif
larrybr42de1c52022-02-13 22:18:22 +00007910 static const char * const zSetReps = "\
7911UPDATE ColNames AS t SET reps=\
7912(SELECT count(*) FROM ColNames d \
7913 WHERE substring(t.name,1,t.nlen-t.chop)=substring(d.name,1,d.nlen-d.chop)\
7914 COLLATE NOCASE\
7915)\
7916";
7917#ifdef SQLITE_ENABLE_MATH_FUNCTIONS
7918 static const char * const zColDigits = "\
7919SELECT CAST(ceil(log(count(*)+0.5)) AS INT) FROM ColNames \
7920";
larrybr2d27d362022-04-16 17:53:25 +00007921#else
7922 /* Counting on SQLITE_MAX_COLUMN < 100,000 here. (32767 is the hard limit.) */
7923 static const char * const zColDigits = "\
7924SELECT CASE WHEN (nc < 10) THEN 1 WHEN (nc < 100) THEN 2 \
7925 WHEN (nc < 1000) THEN 3 WHEN (nc < 10000) THEN 4 \
7926 ELSE 5 FROM (SELECT count(*) AS nc FROM ColNames) \
7927";
larrybr42de1c52022-02-13 22:18:22 +00007928#endif
7929 static const char * const zRenameRank =
larrybr33633862022-02-14 01:12:46 +00007930#ifdef SHELL_COLUMN_RENAME_CLEAN
larrybr42de1c52022-02-13 22:18:22 +00007931 "UPDATE ColNames AS t SET suff="
7932 "iif(reps>1, printf('%c%0*d', '"AUTOCOLUMN_SEP"', $1, cpos), '')"
larrybr33633862022-02-14 01:12:46 +00007933#else /* ...RENAME_MINIMAL_ONE_PASS */
7934"WITH Lzn(nlz) AS (" /* Find minimum extraneous leading 0's for uniqueness */
7935" SELECT 0 AS nlz"
7936" UNION"
7937" SELECT nlz+1 AS nlz FROM Lzn"
7938" WHERE EXISTS("
7939" SELECT 1"
7940" FROM ColNames t, ColNames o"
7941" WHERE"
7942" iif(t.name IN (SELECT * FROM RepeatedNames),"
7943" printf('%s"AUTOCOLUMN_SEP"%s',"
7944" t.name, substring(printf('%.*c%0.*d',nlz+1,'0',$1,t.cpos),2)),"
7945" t.name"
7946" )"
7947" ="
7948" iif(o.name IN (SELECT * FROM RepeatedNames),"
7949" printf('%s"AUTOCOLUMN_SEP"%s',"
7950" o.name, substring(printf('%.*c%0.*d',nlz+1,'0',$1,o.cpos),2)),"
7951" o.name"
7952" )"
7953" COLLATE NOCASE"
7954" AND o.cpos<>t.cpos"
7955" GROUP BY t.cpos"
7956" )"
7957") UPDATE Colnames AS t SET"
7958" chop = 0," /* No chopping, never touch incoming names. */
7959" suff = iif(name IN (SELECT * FROM RepeatedNames),"
7960" printf('"AUTOCOLUMN_SEP"%s', substring("
7961" printf('%.*c%0.*d',(SELECT max(nlz) FROM Lzn)+1,'0',1,t.cpos),2)),"
7962" ''"
7963" )"
larrybr42de1c52022-02-13 22:18:22 +00007964#endif
7965 ;
7966 static const char * const zCollectVar = "\
7967SELECT\
7968 '('||x'0a'\
7969 || group_concat(\
7970 cname||' TEXT',\
7971 ','||iif((cpos-1)%4>0, ' ', x'0a'||' '))\
7972 ||')' AS ColsSpec \
7973FROM (\
larrybr039132b2022-04-09 18:51:49 +00007974 SELECT cpos, printf('\"%w\"',printf('%!.*s%s', nlen-chop,name,suff)) AS cname \
larrybr42de1c52022-02-13 22:18:22 +00007975 FROM ColNames ORDER BY cpos\
7976)";
larrybr33633862022-02-14 01:12:46 +00007977 static const char * const zRenamesDone =
7978 "SELECT group_concat("
larrybr039132b2022-04-09 18:51:49 +00007979 " printf('\"%w\" to \"%w\"',name,printf('%!.*s%s', nlen-chop, name, suff)),"
larrybr33633862022-02-14 01:12:46 +00007980 " ','||x'0a')"
7981 "FROM ColNames WHERE suff<>'' OR chop!=0"
7982 ;
larrybr42de1c52022-02-13 22:18:22 +00007983 int rc;
7984 sqlite3_stmt *pStmt = 0;
7985 assert(pDb!=0);
7986 if( zColNew ){
7987 /* Add initial or additional column. Init db if necessary. */
7988 if( *pDb==0 ){
7989 if( SQLITE_OK!=sqlite3_open(zCOL_DB, pDb) ) return 0;
7990#ifdef SHELL_COLFIX_DB
7991 if(*zCOL_DB!=':')
larrybr33633862022-02-14 01:12:46 +00007992 sqlite3_exec(*pDb,"drop table if exists ColNames;"
7993 "drop view if exists RepeatedNames;",0,0,0);
larrybr42de1c52022-02-13 22:18:22 +00007994#endif
7995 rc = sqlite3_exec(*pDb, zTabMake, 0, 0, 0);
7996 rc_err_oom_die(rc);
7997 }
7998 assert(*pDb!=0);
7999 rc = sqlite3_prepare_v2(*pDb, zTabFill, -1, &pStmt, 0);
8000 rc_err_oom_die(rc);
8001 rc = sqlite3_bind_text(pStmt, 1, zColNew, -1, 0);
8002 rc_err_oom_die(rc);
8003 rc = sqlite3_step(pStmt);
8004 rc_err_oom_die(rc);
8005 sqlite3_finalize(pStmt);
8006 return 0;
8007 }else if( *pDb==0 ){
8008 return 0;
8009 }else{
8010 /* Formulate the columns spec, close the DB, zero *pDb. */
8011 char *zColsSpec = 0;
8012 int hasDupes = db_int(*pDb, zHasDupes);
larrybr42de1c52022-02-13 22:18:22 +00008013 int nDigits = (hasDupes)? db_int(*pDb, zColDigits) : 0;
larrybr42de1c52022-02-13 22:18:22 +00008014 if( hasDupes ){
larrybr33633862022-02-14 01:12:46 +00008015#ifdef SHELL_COLUMN_RENAME_CLEAN
larrybr42de1c52022-02-13 22:18:22 +00008016 rc = sqlite3_exec(*pDb, zDedoctor, 0, 0, 0);
8017 rc_err_oom_die(rc);
larrybr33633862022-02-14 01:12:46 +00008018#endif
larrybr42de1c52022-02-13 22:18:22 +00008019 rc = sqlite3_exec(*pDb, zSetReps, 0, 0, 0);
8020 rc_err_oom_die(rc);
8021 rc = sqlite3_prepare_v2(*pDb, zRenameRank, -1, &pStmt, 0);
8022 rc_err_oom_die(rc);
8023 sqlite3_bind_int(pStmt, 1, nDigits);
8024 rc = sqlite3_step(pStmt);
8025 sqlite3_finalize(pStmt);
8026 assert(rc==SQLITE_DONE);
8027 }
8028 assert(db_int(*pDb, zHasDupes)==0); /* Consider: remove this */
8029 rc = sqlite3_prepare_v2(*pDb, zCollectVar, -1, &pStmt, 0);
8030 rc_err_oom_die(rc);
8031 rc = sqlite3_step(pStmt);
8032 if( rc==SQLITE_ROW ){
8033 zColsSpec = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 0));
8034 }else{
8035 zColsSpec = 0;
8036 }
larrybr33633862022-02-14 01:12:46 +00008037 if( pzRenamed!=0 ){
8038 if( !hasDupes ) *pzRenamed = 0;
8039 else{
8040 sqlite3_finalize(pStmt);
8041 if( SQLITE_OK==sqlite3_prepare_v2(*pDb, zRenamesDone, -1, &pStmt, 0)
8042 && SQLITE_ROW==sqlite3_step(pStmt) ){
8043 *pzRenamed = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 0));
8044 }else
8045 *pzRenamed = 0;
8046 }
8047 }
larrybr42de1c52022-02-13 22:18:22 +00008048 sqlite3_finalize(pStmt);
8049 sqlite3_close(*pDb);
8050 *pDb = 0;
8051 return zColsSpec;
8052 }
8053}
8054
drh2ce15c32017-07-11 13:34:40 +00008055/*
8056** If an input line begins with "." then invoke this routine to
8057** process that line.
8058**
8059** Return 1 on error, 2 to exit, and 0 otherwise.
8060*/
8061static int do_meta_command(char *zLine, ShellState *p){
8062 int h = 1;
8063 int nArg = 0;
8064 int n, c;
8065 int rc = 0;
drh5df84282019-08-17 19:45:25 +00008066 char *azArg[52];
drh2ce15c32017-07-11 13:34:40 +00008067
dan6b046be2018-01-09 15:25:55 +00008068#ifndef SQLITE_OMIT_VIRTUALTABLE
dan43efc182017-12-19 17:42:13 +00008069 if( p->expert.pExpert ){
8070 expertFinish(p, 1, 0);
8071 }
dan6b046be2018-01-09 15:25:55 +00008072#endif
dan43efc182017-12-19 17:42:13 +00008073
drh2ce15c32017-07-11 13:34:40 +00008074 /* Parse the input line into tokens.
8075 */
drh5df84282019-08-17 19:45:25 +00008076 while( zLine[h] && nArg<ArraySize(azArg)-1 ){
drh2ce15c32017-07-11 13:34:40 +00008077 while( IsSpace(zLine[h]) ){ h++; }
8078 if( zLine[h]==0 ) break;
8079 if( zLine[h]=='\'' || zLine[h]=='"' ){
8080 int delim = zLine[h++];
8081 azArg[nArg++] = &zLine[h];
8082 while( zLine[h] && zLine[h]!=delim ){
8083 if( zLine[h]=='\\' && delim=='"' && zLine[h+1]!=0 ) h++;
8084 h++;
8085 }
8086 if( zLine[h]==delim ){
8087 zLine[h++] = 0;
8088 }
8089 if( delim=='"' ) resolve_backslashes(azArg[nArg-1]);
8090 }else{
8091 azArg[nArg++] = &zLine[h];
8092 while( zLine[h] && !IsSpace(zLine[h]) ){ h++; }
8093 if( zLine[h] ) zLine[h++] = 0;
8094 resolve_backslashes(azArg[nArg-1]);
8095 }
8096 }
drh5df84282019-08-17 19:45:25 +00008097 azArg[nArg] = 0;
drh2ce15c32017-07-11 13:34:40 +00008098
8099 /* Process the input line.
8100 */
8101 if( nArg==0 ) return 0; /* no tokens, no error */
8102 n = strlen30(azArg[0]);
8103 c = azArg[0][0];
drh13c20932018-01-10 21:41:55 +00008104 clearTempFile(p);
drh2ce15c32017-07-11 13:34:40 +00008105
8106#ifndef SQLITE_OMIT_AUTHORIZATION
8107 if( c=='a' && strncmp(azArg[0], "auth", n)==0 ){
8108 if( nArg!=2 ){
8109 raw_printf(stderr, "Usage: .auth ON|OFF\n");
8110 rc = 1;
8111 goto meta_command_exit;
8112 }
8113 open_db(p, 0);
8114 if( booleanValue(azArg[1]) ){
8115 sqlite3_set_authorizer(p->db, shellAuth, p);
drhb97e2ad2021-08-26 18:31:39 +00008116 }else if( p->bSafeModePersist ){
8117 sqlite3_set_authorizer(p->db, safeModeAuth, p);
drh2ce15c32017-07-11 13:34:40 +00008118 }else{
8119 sqlite3_set_authorizer(p->db, 0, 0);
8120 }
8121 }else
8122#endif
8123
drhe37c0e12018-01-06 19:19:50 +00008124#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
8125 if( c=='a' && strncmp(azArg[0], "archive", n)==0 ){
danfd0245d2017-12-07 15:44:29 +00008126 open_db(p, 0);
drhb97e2ad2021-08-26 18:31:39 +00008127 failIfSafeMode(p, "cannot run .archive in safe mode");
drhd0f9cdc2018-05-17 14:09:06 +00008128 rc = arDotCommand(p, 0, azArg, nArg);
danfd0245d2017-12-07 15:44:29 +00008129 }else
8130#endif
8131
drh2ce15c32017-07-11 13:34:40 +00008132 if( (c=='b' && n>=3 && strncmp(azArg[0], "backup", n)==0)
8133 || (c=='s' && n>=3 && strncmp(azArg[0], "save", n)==0)
8134 ){
8135 const char *zDestFile = 0;
8136 const char *zDb = 0;
8137 sqlite3 *pDest;
8138 sqlite3_backup *pBackup;
8139 int j;
drha50bffb2018-12-08 01:09:14 +00008140 int bAsync = 0;
drh69ed38a2018-05-14 00:23:08 +00008141 const char *zVfs = 0;
drhb97e2ad2021-08-26 18:31:39 +00008142 failIfSafeMode(p, "cannot run .%s in safe mode", azArg[0]);
drh2ce15c32017-07-11 13:34:40 +00008143 for(j=1; j<nArg; j++){
8144 const char *z = azArg[j];
8145 if( z[0]=='-' ){
drh69ed38a2018-05-14 00:23:08 +00008146 if( z[1]=='-' ) z++;
8147 if( strcmp(z, "-append")==0 ){
8148 zVfs = "apndvfs";
8149 }else
drha50bffb2018-12-08 01:09:14 +00008150 if( strcmp(z, "-async")==0 ){
8151 bAsync = 1;
8152 }else
drh2ce15c32017-07-11 13:34:40 +00008153 {
8154 utf8_printf(stderr, "unknown option: %s\n", azArg[j]);
8155 return 1;
8156 }
8157 }else if( zDestFile==0 ){
8158 zDestFile = azArg[j];
8159 }else if( zDb==0 ){
8160 zDb = zDestFile;
8161 zDestFile = azArg[j];
8162 }else{
drha50bffb2018-12-08 01:09:14 +00008163 raw_printf(stderr, "Usage: .backup ?DB? ?OPTIONS? FILENAME\n");
drh2ce15c32017-07-11 13:34:40 +00008164 return 1;
8165 }
8166 }
8167 if( zDestFile==0 ){
8168 raw_printf(stderr, "missing FILENAME argument on .backup\n");
8169 return 1;
8170 }
8171 if( zDb==0 ) zDb = "main";
drh69ed38a2018-05-14 00:23:08 +00008172 rc = sqlite3_open_v2(zDestFile, &pDest,
8173 SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE, zVfs);
drh2ce15c32017-07-11 13:34:40 +00008174 if( rc!=SQLITE_OK ){
8175 utf8_printf(stderr, "Error: cannot open \"%s\"\n", zDestFile);
drh9e804032018-05-18 17:11:50 +00008176 close_db(pDest);
drh2ce15c32017-07-11 13:34:40 +00008177 return 1;
8178 }
drha50bffb2018-12-08 01:09:14 +00008179 if( bAsync ){
8180 sqlite3_exec(pDest, "PRAGMA synchronous=OFF; PRAGMA journal_mode=OFF;",
8181 0, 0, 0);
8182 }
drh2ce15c32017-07-11 13:34:40 +00008183 open_db(p, 0);
8184 pBackup = sqlite3_backup_init(pDest, "main", p->db, zDb);
8185 if( pBackup==0 ){
8186 utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(pDest));
drh9e804032018-05-18 17:11:50 +00008187 close_db(pDest);
drh2ce15c32017-07-11 13:34:40 +00008188 return 1;
8189 }
8190 while( (rc = sqlite3_backup_step(pBackup,100))==SQLITE_OK ){}
8191 sqlite3_backup_finish(pBackup);
8192 if( rc==SQLITE_DONE ){
8193 rc = 0;
8194 }else{
8195 utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(pDest));
8196 rc = 1;
8197 }
drh9e804032018-05-18 17:11:50 +00008198 close_db(pDest);
drh2ce15c32017-07-11 13:34:40 +00008199 }else
8200
8201 if( c=='b' && n>=3 && strncmp(azArg[0], "bail", n)==0 ){
8202 if( nArg==2 ){
8203 bail_on_error = booleanValue(azArg[1]);
8204 }else{
8205 raw_printf(stderr, "Usage: .bail on|off\n");
8206 rc = 1;
8207 }
8208 }else
8209
8210 if( c=='b' && n>=3 && strncmp(azArg[0], "binary", n)==0 ){
8211 if( nArg==2 ){
8212 if( booleanValue(azArg[1]) ){
8213 setBinaryMode(p->out, 1);
8214 }else{
8215 setTextMode(p->out, 1);
8216 }
8217 }else{
8218 raw_printf(stderr, "Usage: .binary on|off\n");
8219 rc = 1;
8220 }
8221 }else
8222
drh37407122021-07-23 18:43:58 +00008223 /* The undocumented ".breakpoint" command causes a call to the no-op
8224 ** routine named test_breakpoint().
8225 */
8226 if( c=='b' && n>=3 && strncmp(azArg[0], "breakpoint", n)==0 ){
8227 test_breakpoint();
8228 }else
8229
drh2ce15c32017-07-11 13:34:40 +00008230 if( c=='c' && strcmp(azArg[0],"cd")==0 ){
drhb97e2ad2021-08-26 18:31:39 +00008231 failIfSafeMode(p, "cannot run .cd in safe mode");
drh2ce15c32017-07-11 13:34:40 +00008232 if( nArg==2 ){
8233#if defined(_WIN32) || defined(WIN32)
8234 wchar_t *z = sqlite3_win32_utf8_to_unicode(azArg[1]);
8235 rc = !SetCurrentDirectoryW(z);
8236 sqlite3_free(z);
8237#else
8238 rc = chdir(azArg[1]);
8239#endif
8240 if( rc ){
8241 utf8_printf(stderr, "Cannot change to directory \"%s\"\n", azArg[1]);
8242 rc = 1;
8243 }
8244 }else{
8245 raw_printf(stderr, "Usage: .cd DIRECTORY\n");
8246 rc = 1;
8247 }
8248 }else
8249
drh2ce15c32017-07-11 13:34:40 +00008250 if( c=='c' && n>=3 && strncmp(azArg[0], "changes", n)==0 ){
8251 if( nArg==2 ){
8252 setOrClearFlag(p, SHFLG_CountChanges, azArg[1]);
8253 }else{
8254 raw_printf(stderr, "Usage: .changes on|off\n");
8255 rc = 1;
8256 }
8257 }else
8258
8259 /* Cancel output redirection, if it is currently set (by .testcase)
8260 ** Then read the content of the testcase-out.txt file and compare against
8261 ** azArg[1]. If there are differences, report an error and exit.
8262 */
8263 if( c=='c' && n>=3 && strncmp(azArg[0], "check", n)==0 ){
8264 char *zRes = 0;
8265 output_reset(p);
8266 if( nArg!=2 ){
8267 raw_printf(stderr, "Usage: .check GLOB-PATTERN\n");
8268 rc = 2;
8269 }else if( (zRes = readFile("testcase-out.txt", 0))==0 ){
8270 raw_printf(stderr, "Error: cannot read 'testcase-out.txt'\n");
8271 rc = 2;
8272 }else if( testcase_glob(azArg[1],zRes)==0 ){
8273 utf8_printf(stderr,
8274 "testcase-%s FAILED\n Expected: [%s]\n Got: [%s]\n",
8275 p->zTestcase, azArg[1], zRes);
drhf30d3452017-10-17 13:44:46 +00008276 rc = 1;
drh2ce15c32017-07-11 13:34:40 +00008277 }else{
8278 utf8_printf(stdout, "testcase-%s ok\n", p->zTestcase);
8279 p->nCheck++;
8280 }
8281 sqlite3_free(zRes);
8282 }else
8283
8284 if( c=='c' && strncmp(azArg[0], "clone", n)==0 ){
drhb97e2ad2021-08-26 18:31:39 +00008285 failIfSafeMode(p, "cannot run .clone in safe mode");
drh2ce15c32017-07-11 13:34:40 +00008286 if( nArg==2 ){
8287 tryToClone(p, azArg[1]);
8288 }else{
8289 raw_printf(stderr, "Usage: .clone FILENAME\n");
8290 rc = 1;
8291 }
8292 }else
8293
drh37407122021-07-23 18:43:58 +00008294 if( c=='c' && strncmp(azArg[0], "connection", n)==0 ){
8295 if( nArg==1 ){
8296 /* List available connections */
8297 int i;
8298 for(i=0; i<ArraySize(p->aAuxDb); i++){
8299 const char *zFile = p->aAuxDb[i].zDbFilename;
8300 if( p->aAuxDb[i].db==0 && p->pAuxDb!=&p->aAuxDb[i] ){
8301 zFile = "(not open)";
8302 }else if( zFile==0 ){
8303 zFile = "(memory)";
8304 }else if( zFile[0]==0 ){
8305 zFile = "(temporary-file)";
8306 }
8307 if( p->pAuxDb == &p->aAuxDb[i] ){
8308 utf8_printf(stdout, "ACTIVE %d: %s\n", i, zFile);
8309 }else if( p->aAuxDb[i].db!=0 ){
8310 utf8_printf(stdout, " %d: %s\n", i, zFile);
8311 }
8312 }
8313 }else if( nArg==2 && IsDigit(azArg[1][0]) && azArg[1][1]==0 ){
8314 int i = azArg[1][0] - '0';
8315 if( p->pAuxDb != &p->aAuxDb[i] && i>=0 && i<ArraySize(p->aAuxDb) ){
8316 p->pAuxDb->db = p->db;
8317 p->pAuxDb = &p->aAuxDb[i];
8318 globalDb = p->db = p->pAuxDb->db;
8319 p->pAuxDb->db = 0;
8320 }
8321 }else if( nArg==3 && strcmp(azArg[1], "close")==0
8322 && IsDigit(azArg[2][0]) && azArg[2][1]==0 ){
8323 int i = azArg[2][0] - '0';
8324 if( i<0 || i>=ArraySize(p->aAuxDb) ){
8325 /* No-op */
8326 }else if( p->pAuxDb == &p->aAuxDb[i] ){
8327 raw_printf(stderr, "cannot close the active database connection\n");
8328 rc = 1;
8329 }else if( p->aAuxDb[i].db ){
8330 session_close_all(p, i);
8331 close_db(p->aAuxDb[i].db);
8332 p->aAuxDb[i].db = 0;
8333 }
8334 }else{
8335 raw_printf(stderr, "Usage: .connection [close] [CONNECTION-NUMBER]\n");
8336 rc = 1;
8337 }
8338 }else
8339
drh2ce15c32017-07-11 13:34:40 +00008340 if( c=='d' && n>1 && strncmp(azArg[0], "databases", n)==0 ){
drh60081a02020-08-26 19:07:18 +00008341 char **azName = 0;
8342 int nName = 0;
8343 sqlite3_stmt *pStmt;
drh60081a02020-08-26 19:07:18 +00008344 int i;
drh2ce15c32017-07-11 13:34:40 +00008345 open_db(p, 0);
drh60081a02020-08-26 19:07:18 +00008346 rc = sqlite3_prepare_v2(p->db, "PRAGMA database_list", -1, &pStmt, 0);
8347 if( rc ){
8348 utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
drh2ce15c32017-07-11 13:34:40 +00008349 rc = 1;
drh60081a02020-08-26 19:07:18 +00008350 }else{
8351 while( sqlite3_step(pStmt)==SQLITE_ROW ){
8352 const char *zSchema = (const char *)sqlite3_column_text(pStmt,1);
8353 const char *zFile = (const char*)sqlite3_column_text(pStmt,2);
drh621a5e02021-12-16 17:35:27 +00008354 if( zSchema==0 || zFile==0 ) continue;
drh60081a02020-08-26 19:07:18 +00008355 azName = sqlite3_realloc(azName, (nName+1)*2*sizeof(char*));
drhe3e25652021-12-16 13:29:28 +00008356 shell_check_oom(azName);
drh60081a02020-08-26 19:07:18 +00008357 azName[nName*2] = strdup(zSchema);
8358 azName[nName*2+1] = strdup(zFile);
8359 nName++;
8360 }
drh2ce15c32017-07-11 13:34:40 +00008361 }
drh60081a02020-08-26 19:07:18 +00008362 sqlite3_finalize(pStmt);
8363 for(i=0; i<nName; i++){
8364 int eTxn = sqlite3_txn_state(p->db, azName[i*2]);
8365 int bRdonly = sqlite3_db_readonly(p->db, azName[i*2]);
8366 const char *z = azName[i*2+1];
8367 utf8_printf(p->out, "%s: %s %s%s\n",
8368 azName[i*2],
8369 z && z[0] ? z : "\"\"",
8370 bRdonly ? "r/o" : "r/w",
8371 eTxn==SQLITE_TXN_NONE ? "" :
8372 eTxn==SQLITE_TXN_READ ? " read-txn" : " write-txn");
8373 free(azName[i*2]);
8374 free(azName[i*2+1]);
8375 }
8376 sqlite3_free(azName);
drh2ce15c32017-07-11 13:34:40 +00008377 }else
8378
drh7df01192018-04-28 12:43:16 +00008379 if( c=='d' && n>=3 && strncmp(azArg[0], "dbconfig", n)==0 ){
drheb7f2a02018-09-26 18:02:32 +00008380 static const struct DbConfigChoices {
8381 const char *zName;
8382 int op;
8383 } aDbConfig[] = {
drhb945bcd2019-12-31 22:52:10 +00008384 { "defensive", SQLITE_DBCONFIG_DEFENSIVE },
8385 { "dqs_ddl", SQLITE_DBCONFIG_DQS_DDL },
8386 { "dqs_dml", SQLITE_DBCONFIG_DQS_DML },
drh0a6873b2019-06-14 21:25:25 +00008387 { "enable_fkey", SQLITE_DBCONFIG_ENABLE_FKEY },
drhb945bcd2019-12-31 22:52:10 +00008388 { "enable_qpsg", SQLITE_DBCONFIG_ENABLE_QPSG },
drh0a6873b2019-06-14 21:25:25 +00008389 { "enable_trigger", SQLITE_DBCONFIG_ENABLE_TRIGGER },
drh11d88e62019-08-15 21:27:20 +00008390 { "enable_view", SQLITE_DBCONFIG_ENABLE_VIEW },
drh0a6873b2019-06-14 21:25:25 +00008391 { "fts3_tokenizer", SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER },
drhb945bcd2019-12-31 22:52:10 +00008392 { "legacy_alter_table", SQLITE_DBCONFIG_LEGACY_ALTER_TABLE },
8393 { "legacy_file_format", SQLITE_DBCONFIG_LEGACY_FILE_FORMAT },
drh0a6873b2019-06-14 21:25:25 +00008394 { "load_extension", SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION },
8395 { "no_ckpt_on_close", SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE },
drh0a6873b2019-06-14 21:25:25 +00008396 { "reset_database", SQLITE_DBCONFIG_RESET_DATABASE },
drhb945bcd2019-12-31 22:52:10 +00008397 { "trigger_eqp", SQLITE_DBCONFIG_TRIGGER_EQP },
drhb77da372020-01-07 16:09:11 +00008398 { "trusted_schema", SQLITE_DBCONFIG_TRUSTED_SCHEMA },
dan07312a62019-06-21 14:05:27 +00008399 { "writable_schema", SQLITE_DBCONFIG_WRITABLE_SCHEMA },
drh7df01192018-04-28 12:43:16 +00008400 };
8401 int ii, v;
8402 open_db(p, 0);
8403 for(ii=0; ii<ArraySize(aDbConfig); ii++){
8404 if( nArg>1 && strcmp(azArg[1], aDbConfig[ii].zName)!=0 ) continue;
8405 if( nArg>=3 ){
8406 sqlite3_db_config(p->db, aDbConfig[ii].op, booleanValue(azArg[2]), 0);
8407 }
8408 sqlite3_db_config(p->db, aDbConfig[ii].op, -1, &v);
drhb945bcd2019-12-31 22:52:10 +00008409 utf8_printf(p->out, "%19s %s\n", aDbConfig[ii].zName, v ? "on" : "off");
drh7df01192018-04-28 12:43:16 +00008410 if( nArg>1 ) break;
8411 }
8412 if( nArg>1 && ii==ArraySize(aDbConfig) ){
8413 utf8_printf(stderr, "Error: unknown dbconfig \"%s\"\n", azArg[1]);
8414 utf8_printf(stderr, "Enter \".dbconfig\" with no arguments for a list\n");
8415 }
8416 }else
8417
8418 if( c=='d' && n>=3 && strncmp(azArg[0], "dbinfo", n)==0 ){
drh2ce15c32017-07-11 13:34:40 +00008419 rc = shell_dbinfo_command(p, nArg, azArg);
8420 }else
8421
dan1b162162019-04-27 20:15:15 +00008422#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
dan68cb86e2019-04-20 20:57:28 +00008423 if( c=='r' && strncmp(azArg[0], "recover", n)==0 ){
8424 open_db(p, 0);
danb9b71db2019-04-25 16:20:40 +00008425 rc = recoverDatabaseCmd(p, nArg, azArg);
dan68cb86e2019-04-20 20:57:28 +00008426 }else
dan1b162162019-04-27 20:15:15 +00008427#endif /* !(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB) */
dan68cb86e2019-04-20 20:57:28 +00008428
drh2ce15c32017-07-11 13:34:40 +00008429 if( c=='d' && strncmp(azArg[0], "dump", n)==0 ){
drh8e9297f2020-03-25 12:50:13 +00008430 char *zLike = 0;
8431 char *zSql;
drh2ce15c32017-07-11 13:34:40 +00008432 int i;
8433 int savedShowHeader = p->showHeader;
drhf213b332018-07-05 17:35:46 +00008434 int savedShellFlags = p->shellFlgs;
larrybr527c39d2022-05-10 14:55:45 +00008435 ShellClearFlag(p,
drhc1962192020-10-12 16:54:28 +00008436 SHFLG_PreserveRowid|SHFLG_Newlines|SHFLG_Echo
8437 |SHFLG_DumpDataOnly|SHFLG_DumpNoSys);
drh2ce15c32017-07-11 13:34:40 +00008438 for(i=1; i<nArg; i++){
8439 if( azArg[i][0]=='-' ){
8440 const char *z = azArg[i]+1;
8441 if( z[0]=='-' ) z++;
8442 if( strcmp(z,"preserve-rowids")==0 ){
8443#ifdef SQLITE_OMIT_VIRTUALTABLE
8444 raw_printf(stderr, "The --preserve-rowids option is not compatible"
8445 " with SQLITE_OMIT_VIRTUALTABLE\n");
8446 rc = 1;
drh1d29fd82020-05-29 19:03:03 +00008447 sqlite3_free(zLike);
drh2ce15c32017-07-11 13:34:40 +00008448 goto meta_command_exit;
8449#else
8450 ShellSetFlag(p, SHFLG_PreserveRowid);
8451#endif
8452 }else
8453 if( strcmp(z,"newlines")==0 ){
8454 ShellSetFlag(p, SHFLG_Newlines);
8455 }else
drhc1962192020-10-12 16:54:28 +00008456 if( strcmp(z,"data-only")==0 ){
8457 ShellSetFlag(p, SHFLG_DumpDataOnly);
8458 }else
8459 if( strcmp(z,"nosys")==0 ){
8460 ShellSetFlag(p, SHFLG_DumpNoSys);
8461 }else
drh2ce15c32017-07-11 13:34:40 +00008462 {
8463 raw_printf(stderr, "Unknown option \"%s\" on \".dump\"\n", azArg[i]);
8464 rc = 1;
drh1d29fd82020-05-29 19:03:03 +00008465 sqlite3_free(zLike);
drh2ce15c32017-07-11 13:34:40 +00008466 goto meta_command_exit;
8467 }
drh2ce15c32017-07-11 13:34:40 +00008468 }else{
dan78a9d752021-05-25 11:39:14 +00008469 /* azArg[i] contains a LIKE pattern. This ".dump" request should
8470 ** only dump data for tables for which either the table name matches
8471 ** the LIKE pattern, or the table appears to be a shadow table of
8472 ** a virtual table for which the name matches the LIKE pattern.
8473 */
8474 char *zExpr = sqlite3_mprintf(
8475 "name LIKE %Q ESCAPE '\\' OR EXISTS ("
8476 " SELECT 1 FROM sqlite_schema WHERE "
8477 " name LIKE %Q ESCAPE '\\' AND"
8478 " sql LIKE 'CREATE VIRTUAL TABLE%%' AND"
8479 " substr(o.name, 1, length(name)+1) == (name||'_')"
8480 ")", azArg[i], azArg[i]
8481 );
8482
8483 if( zLike ){
8484 zLike = sqlite3_mprintf("%z OR %z", zLike, zExpr);
8485 }else{
8486 zLike = zExpr;
8487 }
drh2ce15c32017-07-11 13:34:40 +00008488 }
8489 }
dan68cb86e2019-04-20 20:57:28 +00008490
drh2ce15c32017-07-11 13:34:40 +00008491 open_db(p, 0);
dan68cb86e2019-04-20 20:57:28 +00008492
drhc1962192020-10-12 16:54:28 +00008493 if( (p->shellFlgs & SHFLG_DumpDataOnly)==0 ){
8494 /* When playing back a "dump", the content might appear in an order
8495 ** which causes immediate foreign key constraints to be violated.
8496 ** So disable foreign-key constraint enforcement to prevent problems. */
8497 raw_printf(p->out, "PRAGMA foreign_keys=OFF;\n");
8498 raw_printf(p->out, "BEGIN TRANSACTION;\n");
8499 }
drh2ce15c32017-07-11 13:34:40 +00008500 p->writableSchema = 0;
8501 p->showHeader = 0;
8502 /* Set writable_schema=ON since doing so forces SQLite to initialize
drh067b92b2020-06-19 15:24:12 +00008503 ** as much of the schema as it can even if the sqlite_schema table is
drh2ce15c32017-07-11 13:34:40 +00008504 ** corrupt. */
8505 sqlite3_exec(p->db, "SAVEPOINT dump; PRAGMA writable_schema=ON", 0, 0, 0);
8506 p->nErr = 0;
drh8e9297f2020-03-25 12:50:13 +00008507 if( zLike==0 ) zLike = sqlite3_mprintf("true");
8508 zSql = sqlite3_mprintf(
dan78a9d752021-05-25 11:39:14 +00008509 "SELECT name, type, sql FROM sqlite_schema AS o "
drh8e9297f2020-03-25 12:50:13 +00008510 "WHERE (%s) AND type=='table'"
8511 " AND sql NOT NULL"
8512 " ORDER BY tbl_name='sqlite_sequence', rowid",
8513 zLike
8514 );
8515 run_schema_dump_query(p,zSql);
8516 sqlite3_free(zSql);
drhc1962192020-10-12 16:54:28 +00008517 if( (p->shellFlgs & SHFLG_DumpDataOnly)==0 ){
8518 zSql = sqlite3_mprintf(
dan78a9d752021-05-25 11:39:14 +00008519 "SELECT sql FROM sqlite_schema AS o "
drhc1962192020-10-12 16:54:28 +00008520 "WHERE (%s) AND sql NOT NULL"
8521 " AND type IN ('index','trigger','view')",
8522 zLike
8523 );
8524 run_table_dump_query(p, zSql);
8525 sqlite3_free(zSql);
8526 }
drh8e9297f2020-03-25 12:50:13 +00008527 sqlite3_free(zLike);
drh2ce15c32017-07-11 13:34:40 +00008528 if( p->writableSchema ){
8529 raw_printf(p->out, "PRAGMA writable_schema=OFF;\n");
8530 p->writableSchema = 0;
8531 }
8532 sqlite3_exec(p->db, "PRAGMA writable_schema=OFF;", 0, 0, 0);
8533 sqlite3_exec(p->db, "RELEASE dump;", 0, 0, 0);
drhc1962192020-10-12 16:54:28 +00008534 if( (p->shellFlgs & SHFLG_DumpDataOnly)==0 ){
8535 raw_printf(p->out, p->nErr?"ROLLBACK; -- due to errors\n":"COMMIT;\n");
8536 }
drh2ce15c32017-07-11 13:34:40 +00008537 p->showHeader = savedShowHeader;
drhf213b332018-07-05 17:35:46 +00008538 p->shellFlgs = savedShellFlags;
drh2ce15c32017-07-11 13:34:40 +00008539 }else
8540
8541 if( c=='e' && strncmp(azArg[0], "echo", n)==0 ){
8542 if( nArg==2 ){
8543 setOrClearFlag(p, SHFLG_Echo, azArg[1]);
8544 }else{
8545 raw_printf(stderr, "Usage: .echo on|off\n");
8546 rc = 1;
8547 }
8548 }else
8549
8550 if( c=='e' && strncmp(azArg[0], "eqp", n)==0 ){
8551 if( nArg==2 ){
drhe2ca99c2018-05-02 00:33:43 +00008552 p->autoEQPtest = 0;
drhb4e50392019-01-26 15:40:04 +00008553 if( p->autoEQPtrace ){
8554 if( p->db ) sqlite3_exec(p->db, "PRAGMA vdbe_trace=OFF;", 0, 0, 0);
8555 p->autoEQPtrace = 0;
8556 }
drh2ce15c32017-07-11 13:34:40 +00008557 if( strcmp(azArg[1],"full")==0 ){
drhada70452017-12-21 21:02:27 +00008558 p->autoEQP = AUTOEQP_full;
8559 }else if( strcmp(azArg[1],"trigger")==0 ){
8560 p->autoEQP = AUTOEQP_trigger;
drhb4e50392019-01-26 15:40:04 +00008561#ifdef SQLITE_DEBUG
drhe2ca99c2018-05-02 00:33:43 +00008562 }else if( strcmp(azArg[1],"test")==0 ){
8563 p->autoEQP = AUTOEQP_on;
8564 p->autoEQPtest = 1;
drhb4e50392019-01-26 15:40:04 +00008565 }else if( strcmp(azArg[1],"trace")==0 ){
8566 p->autoEQP = AUTOEQP_full;
8567 p->autoEQPtrace = 1;
8568 open_db(p, 0);
drh067b92b2020-06-19 15:24:12 +00008569 sqlite3_exec(p->db, "SELECT name FROM sqlite_schema LIMIT 1", 0, 0, 0);
drhb4e50392019-01-26 15:40:04 +00008570 sqlite3_exec(p->db, "PRAGMA vdbe_trace=ON;", 0, 0, 0);
8571#endif
drh2ce15c32017-07-11 13:34:40 +00008572 }else{
mistachkinb71aa092018-01-23 00:05:18 +00008573 p->autoEQP = (u8)booleanValue(azArg[1]);
drh2ce15c32017-07-11 13:34:40 +00008574 }
8575 }else{
drhb4e50392019-01-26 15:40:04 +00008576 raw_printf(stderr, "Usage: .eqp off|on|trace|trigger|full\n");
drh2ce15c32017-07-11 13:34:40 +00008577 rc = 1;
8578 }
8579 }else
8580
8581 if( c=='e' && strncmp(azArg[0], "exit", n)==0 ){
8582 if( nArg>1 && (rc = (int)integerValue(azArg[1]))!=0 ) exit(rc);
8583 rc = 2;
8584 }else
8585
8586 /* The ".explain" command is automatic now. It is largely pointless. It
8587 ** retained purely for backwards compatibility */
8588 if( c=='e' && strncmp(azArg[0], "explain", n)==0 ){
8589 int val = 1;
8590 if( nArg>=2 ){
8591 if( strcmp(azArg[1],"auto")==0 ){
8592 val = 99;
8593 }else{
8594 val = booleanValue(azArg[1]);
8595 }
8596 }
8597 if( val==1 && p->mode!=MODE_Explain ){
8598 p->normalMode = p->mode;
8599 p->mode = MODE_Explain;
8600 p->autoExplain = 0;
8601 }else if( val==0 ){
8602 if( p->mode==MODE_Explain ) p->mode = p->normalMode;
8603 p->autoExplain = 0;
8604 }else if( val==99 ){
8605 if( p->mode==MODE_Explain ) p->mode = p->normalMode;
8606 p->autoExplain = 1;
8607 }
8608 }else
8609
dan6b046be2018-01-09 15:25:55 +00008610#ifndef SQLITE_OMIT_VIRTUALTABLE
dan43efc182017-12-19 17:42:13 +00008611 if( c=='e' && strncmp(azArg[0], "expert", n)==0 ){
drhfe463172021-12-16 17:57:21 +00008612 if( p->bSafeMode ){
8613 raw_printf(stderr,
8614 "Cannot run experimental commands such as \"%s\" in safe mode\n",
8615 azArg[0]);
8616 rc = 1;
8617 }else{
8618 open_db(p, 0);
8619 expertDotCommand(p, azArg, nArg);
8620 }
dan43efc182017-12-19 17:42:13 +00008621 }else
dan6b046be2018-01-09 15:25:55 +00008622#endif
dan43efc182017-12-19 17:42:13 +00008623
drhd985f722019-06-05 14:29:53 +00008624 if( c=='f' && strncmp(azArg[0], "filectrl", n)==0 ){
8625 static const struct {
8626 const char *zCtrlName; /* Name of a test-control option */
8627 int ctrlCode; /* Integer code for that option */
8628 const char *zUsage; /* Usage notes */
8629 } aCtrl[] = {
drhd985f722019-06-05 14:29:53 +00008630 { "chunk_size", SQLITE_FCNTL_CHUNK_SIZE, "SIZE" },
drh18a4bbd2020-12-17 15:17:42 +00008631 { "data_version", SQLITE_FCNTL_DATA_VERSION, "" },
drhd985f722019-06-05 14:29:53 +00008632 { "has_moved", SQLITE_FCNTL_HAS_MOVED, "" },
8633 { "lock_timeout", SQLITE_FCNTL_LOCK_TIMEOUT, "MILLISEC" },
drh18a4bbd2020-12-17 15:17:42 +00008634 { "persist_wal", SQLITE_FCNTL_PERSIST_WAL, "[BOOLEAN]" },
8635 /* { "pragma", SQLITE_FCNTL_PRAGMA, "NAME ARG" },*/
8636 { "psow", SQLITE_FCNTL_POWERSAFE_OVERWRITE, "[BOOLEAN]" },
drh541ef2c2020-04-20 16:21:30 +00008637 { "reserve_bytes", SQLITE_FCNTL_RESERVE_BYTES, "[N]" },
drh18a4bbd2020-12-17 15:17:42 +00008638 { "size_limit", SQLITE_FCNTL_SIZE_LIMIT, "[LIMIT]" },
8639 { "tempfilename", SQLITE_FCNTL_TEMPFILENAME, "" },
8640 /* { "win32_av_retry", SQLITE_FCNTL_WIN32_AV_RETRY, "COUNT DELAY" },*/
drhd985f722019-06-05 14:29:53 +00008641 };
8642 int filectrl = -1;
8643 int iCtrl = -1;
drh4245e042019-06-13 13:52:46 +00008644 sqlite3_int64 iRes = 0; /* Integer result to display if rc2==1 */
8645 int isOk = 0; /* 0: usage 1: %lld 2: no-result */
drhd985f722019-06-05 14:29:53 +00008646 int n2, i;
8647 const char *zCmd = 0;
drh541ef2c2020-04-20 16:21:30 +00008648 const char *zSchema = 0;
drhd985f722019-06-05 14:29:53 +00008649
8650 open_db(p, 0);
8651 zCmd = nArg>=2 ? azArg[1] : "help";
8652
drh541ef2c2020-04-20 16:21:30 +00008653 if( zCmd[0]=='-'
8654 && (strcmp(zCmd,"--schema")==0 || strcmp(zCmd,"-schema")==0)
8655 && nArg>=4
8656 ){
8657 zSchema = azArg[2];
8658 for(i=3; i<nArg; i++) azArg[i-2] = azArg[i];
8659 nArg -= 2;
8660 zCmd = azArg[1];
8661 }
8662
drhd985f722019-06-05 14:29:53 +00008663 /* The argument can optionally begin with "-" or "--" */
8664 if( zCmd[0]=='-' && zCmd[1] ){
8665 zCmd++;
8666 if( zCmd[0]=='-' && zCmd[1] ) zCmd++;
8667 }
8668
8669 /* --help lists all file-controls */
8670 if( strcmp(zCmd,"help")==0 ){
8671 utf8_printf(p->out, "Available file-controls:\n");
8672 for(i=0; i<ArraySize(aCtrl); i++){
8673 utf8_printf(p->out, " .filectrl %s %s\n",
8674 aCtrl[i].zCtrlName, aCtrl[i].zUsage);
8675 }
8676 rc = 1;
8677 goto meta_command_exit;
8678 }
8679
8680 /* convert filectrl text option to value. allow any unique prefix
8681 ** of the option name, or a numerical value. */
8682 n2 = strlen30(zCmd);
8683 for(i=0; i<ArraySize(aCtrl); i++){
8684 if( strncmp(zCmd, aCtrl[i].zCtrlName, n2)==0 ){
8685 if( filectrl<0 ){
8686 filectrl = aCtrl[i].ctrlCode;
8687 iCtrl = i;
8688 }else{
8689 utf8_printf(stderr, "Error: ambiguous file-control: \"%s\"\n"
8690 "Use \".filectrl --help\" for help\n", zCmd);
8691 rc = 1;
8692 goto meta_command_exit;
8693 }
8694 }
8695 }
8696 if( filectrl<0 ){
8697 utf8_printf(stderr,"Error: unknown file-control: %s\n"
8698 "Use \".filectrl --help\" for help\n", zCmd);
8699 }else{
8700 switch(filectrl){
8701 case SQLITE_FCNTL_SIZE_LIMIT: {
8702 if( nArg!=2 && nArg!=3 ) break;
8703 iRes = nArg==3 ? integerValue(azArg[2]) : -1;
drh541ef2c2020-04-20 16:21:30 +00008704 sqlite3_file_control(p->db, zSchema, SQLITE_FCNTL_SIZE_LIMIT, &iRes);
drhd985f722019-06-05 14:29:53 +00008705 isOk = 1;
8706 break;
8707 }
8708 case SQLITE_FCNTL_LOCK_TIMEOUT:
8709 case SQLITE_FCNTL_CHUNK_SIZE: {
8710 int x;
8711 if( nArg!=3 ) break;
8712 x = (int)integerValue(azArg[2]);
drh541ef2c2020-04-20 16:21:30 +00008713 sqlite3_file_control(p->db, zSchema, filectrl, &x);
drhd985f722019-06-05 14:29:53 +00008714 isOk = 2;
8715 break;
8716 }
8717 case SQLITE_FCNTL_PERSIST_WAL:
8718 case SQLITE_FCNTL_POWERSAFE_OVERWRITE: {
8719 int x;
8720 if( nArg!=2 && nArg!=3 ) break;
8721 x = nArg==3 ? booleanValue(azArg[2]) : -1;
drh541ef2c2020-04-20 16:21:30 +00008722 sqlite3_file_control(p->db, zSchema, filectrl, &x);
drhd985f722019-06-05 14:29:53 +00008723 iRes = x;
8724 isOk = 1;
8725 break;
8726 }
drh18a4bbd2020-12-17 15:17:42 +00008727 case SQLITE_FCNTL_DATA_VERSION:
drhd985f722019-06-05 14:29:53 +00008728 case SQLITE_FCNTL_HAS_MOVED: {
8729 int x;
8730 if( nArg!=2 ) break;
drh541ef2c2020-04-20 16:21:30 +00008731 sqlite3_file_control(p->db, zSchema, filectrl, &x);
drhd985f722019-06-05 14:29:53 +00008732 iRes = x;
8733 isOk = 1;
8734 break;
8735 }
8736 case SQLITE_FCNTL_TEMPFILENAME: {
8737 char *z = 0;
8738 if( nArg!=2 ) break;
drh541ef2c2020-04-20 16:21:30 +00008739 sqlite3_file_control(p->db, zSchema, filectrl, &z);
drhd985f722019-06-05 14:29:53 +00008740 if( z ){
8741 utf8_printf(p->out, "%s\n", z);
8742 sqlite3_free(z);
8743 }
8744 isOk = 2;
8745 break;
8746 }
drh541ef2c2020-04-20 16:21:30 +00008747 case SQLITE_FCNTL_RESERVE_BYTES: {
8748 int x;
8749 if( nArg>=3 ){
8750 x = atoi(azArg[2]);
8751 sqlite3_file_control(p->db, zSchema, filectrl, &x);
8752 }
8753 x = -1;
8754 sqlite3_file_control(p->db, zSchema, filectrl, &x);
8755 utf8_printf(p->out,"%d\n", x);
8756 isOk = 2;
8757 break;
8758 }
drhd985f722019-06-05 14:29:53 +00008759 }
8760 }
8761 if( isOk==0 && iCtrl>=0 ){
8762 utf8_printf(p->out, "Usage: .filectrl %s %s\n", zCmd,aCtrl[iCtrl].zUsage);
8763 rc = 1;
8764 }else if( isOk==1 ){
drhe2500762019-06-13 14:07:41 +00008765 char zBuf[100];
8766 sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld", iRes);
8767 raw_printf(p->out, "%s\n", zBuf);
drhd985f722019-06-05 14:29:53 +00008768 }
8769 }else
8770
drh2ce15c32017-07-11 13:34:40 +00008771 if( c=='f' && strncmp(azArg[0], "fullschema", n)==0 ){
8772 ShellState data;
drh2ce15c32017-07-11 13:34:40 +00008773 int doStats = 0;
8774 memcpy(&data, p, sizeof(data));
8775 data.showHeader = 0;
8776 data.cMode = data.mode = MODE_Semi;
8777 if( nArg==2 && optionMatch(azArg[1], "indent") ){
8778 data.cMode = data.mode = MODE_Pretty;
8779 nArg = 1;
8780 }
8781 if( nArg!=1 ){
8782 raw_printf(stderr, "Usage: .fullschema ?--indent?\n");
8783 rc = 1;
8784 goto meta_command_exit;
8785 }
8786 open_db(p, 0);
8787 rc = sqlite3_exec(p->db,
8788 "SELECT sql FROM"
8789 " (SELECT sql sql, type type, tbl_name tbl_name, name name, rowid x"
drh067b92b2020-06-19 15:24:12 +00008790 " FROM sqlite_schema UNION ALL"
8791 " SELECT sql, type, tbl_name, name, rowid FROM sqlite_temp_schema) "
drh2ce15c32017-07-11 13:34:40 +00008792 "WHERE type!='meta' AND sql NOTNULL AND name NOT LIKE 'sqlite_%' "
drh69935c02021-06-25 11:14:10 +00008793 "ORDER BY x",
drhf83d5012021-05-03 13:35:00 +00008794 callback, &data, 0
drh2ce15c32017-07-11 13:34:40 +00008795 );
8796 if( rc==SQLITE_OK ){
8797 sqlite3_stmt *pStmt;
8798 rc = sqlite3_prepare_v2(p->db,
drh067b92b2020-06-19 15:24:12 +00008799 "SELECT rowid FROM sqlite_schema"
drh2ce15c32017-07-11 13:34:40 +00008800 " WHERE name GLOB 'sqlite_stat[134]'",
8801 -1, &pStmt, 0);
8802 doStats = sqlite3_step(pStmt)==SQLITE_ROW;
8803 sqlite3_finalize(pStmt);
8804 }
8805 if( doStats==0 ){
8806 raw_printf(p->out, "/* No STAT tables available */\n");
8807 }else{
drh067b92b2020-06-19 15:24:12 +00008808 raw_printf(p->out, "ANALYZE sqlite_schema;\n");
drh2ce15c32017-07-11 13:34:40 +00008809 data.cMode = data.mode = MODE_Insert;
8810 data.zDestTable = "sqlite_stat1";
drhf83d5012021-05-03 13:35:00 +00008811 shell_exec(&data, "SELECT * FROM sqlite_stat1", 0);
drh2ce15c32017-07-11 13:34:40 +00008812 data.zDestTable = "sqlite_stat4";
drhf83d5012021-05-03 13:35:00 +00008813 shell_exec(&data, "SELECT * FROM sqlite_stat4", 0);
drh067b92b2020-06-19 15:24:12 +00008814 raw_printf(p->out, "ANALYZE sqlite_schema;\n");
drh2ce15c32017-07-11 13:34:40 +00008815 }
8816 }else
8817
8818 if( c=='h' && strncmp(azArg[0], "headers", n)==0 ){
8819 if( nArg==2 ){
8820 p->showHeader = booleanValue(azArg[1]);
drhc0605082020-06-05 00:54:27 +00008821 p->shellFlgs |= SHFLG_HeaderSet;
drh2ce15c32017-07-11 13:34:40 +00008822 }else{
8823 raw_printf(stderr, "Usage: .headers on|off\n");
8824 rc = 1;
8825 }
8826 }else
8827
8828 if( c=='h' && strncmp(azArg[0], "help", n)==0 ){
drh98aa2ab2018-09-26 16:53:51 +00008829 if( nArg>=2 ){
drhe93f8262018-10-11 16:53:37 +00008830 n = showHelp(p->out, azArg[1]);
drh98aa2ab2018-09-26 16:53:51 +00008831 if( n==0 ){
8832 utf8_printf(p->out, "Nothing matches '%s'\n", azArg[1]);
8833 }
8834 }else{
8835 showHelp(p->out, 0);
8836 }
drh2ce15c32017-07-11 13:34:40 +00008837 }else
8838
8839 if( c=='i' && strncmp(azArg[0], "import", n)==0 ){
drhccb37812020-03-09 15:39:39 +00008840 char *zTable = 0; /* Insert data into this table */
larrybr53e11862022-03-06 23:41:21 +00008841 char *zSchema = 0; /* within this schema (may default to "main") */
drhccb37812020-03-09 15:39:39 +00008842 char *zFile = 0; /* Name of file to extra content from */
drh2ce15c32017-07-11 13:34:40 +00008843 sqlite3_stmt *pStmt = NULL; /* A statement */
8844 int nCol; /* Number of columns in the table */
8845 int nByte; /* Number of bytes in an SQL string */
8846 int i, j; /* Loop counters */
8847 int needCommit; /* True to COMMIT or ROLLBACK at end */
8848 int nSep; /* Number of bytes in p->colSeparator[] */
8849 char *zSql; /* An SQL statement */
larrybr41f46702022-03-07 00:14:52 +00008850 char *zFullTabName; /* Table name with schema if applicable */
drh2ce15c32017-07-11 13:34:40 +00008851 ImportCtx sCtx; /* Reader context */
8852 char *(SQLITE_CDECL *xRead)(ImportCtx*); /* Func to read one value */
drhccb37812020-03-09 15:39:39 +00008853 int eVerbose = 0; /* Larger for more console output */
8854 int nSkip = 0; /* Initial lines to skip */
8855 int useOutputMode = 1; /* Use output mode to determine separators */
drhe684ac62022-03-08 13:59:46 +00008856 char *zCreate = 0; /* CREATE TABLE statement text */
drh2ce15c32017-07-11 13:34:40 +00008857
drhb97e2ad2021-08-26 18:31:39 +00008858 failIfSafeMode(p, "cannot run .import in safe mode");
drhccb37812020-03-09 15:39:39 +00008859 memset(&sCtx, 0, sizeof(sCtx));
8860 if( p->mode==MODE_Ascii ){
8861 xRead = ascii_read_one_field;
8862 }else{
8863 xRead = csv_read_one_field;
8864 }
larrybr2f5f6742022-05-09 12:29:47 +00008865 rc = 1;
drhccb37812020-03-09 15:39:39 +00008866 for(i=1; i<nArg; i++){
8867 char *z = azArg[i];
8868 if( z[0]=='-' && z[1]=='-' ) z++;
8869 if( z[0]!='-' ){
8870 if( zFile==0 ){
8871 zFile = z;
8872 }else if( zTable==0 ){
8873 zTable = z;
8874 }else{
8875 utf8_printf(p->out, "ERROR: extra argument: \"%s\". Usage:\n", z);
8876 showHelp(p->out, "import");
drhccb37812020-03-09 15:39:39 +00008877 goto meta_command_exit;
8878 }
8879 }else if( strcmp(z,"-v")==0 ){
8880 eVerbose++;
larrybr738d7b92022-01-13 21:22:54 +00008881 }else if( strcmp(z,"-schema")==0 && i<nArg-1 ){
8882 zSchema = azArg[++i];
drhccb37812020-03-09 15:39:39 +00008883 }else if( strcmp(z,"-skip")==0 && i<nArg-1 ){
8884 nSkip = integerValue(azArg[++i]);
8885 }else if( strcmp(z,"-ascii")==0 ){
8886 sCtx.cColSep = SEP_Unit[0];
8887 sCtx.cRowSep = SEP_Record[0];
8888 xRead = ascii_read_one_field;
8889 useOutputMode = 0;
8890 }else if( strcmp(z,"-csv")==0 ){
8891 sCtx.cColSep = ',';
8892 sCtx.cRowSep = '\n';
8893 xRead = csv_read_one_field;
8894 useOutputMode = 0;
8895 }else{
8896 utf8_printf(p->out, "ERROR: unknown option: \"%s\". Usage:\n", z);
8897 showHelp(p->out, "import");
drhccb37812020-03-09 15:39:39 +00008898 goto meta_command_exit;
8899 }
8900 }
8901 if( zTable==0 ){
8902 utf8_printf(p->out, "ERROR: missing %s argument. Usage:\n",
8903 zFile==0 ? "FILE" : "TABLE");
8904 showHelp(p->out, "import");
drh2ce15c32017-07-11 13:34:40 +00008905 goto meta_command_exit;
8906 }
drh2ce15c32017-07-11 13:34:40 +00008907 seenInterrupt = 0;
drh2ce15c32017-07-11 13:34:40 +00008908 open_db(p, 0);
drhccb37812020-03-09 15:39:39 +00008909 if( useOutputMode ){
8910 /* If neither the --csv or --ascii options are specified, then set
8911 ** the column and row separator characters from the output mode. */
8912 nSep = strlen30(p->colSeparator);
8913 if( nSep==0 ){
8914 raw_printf(stderr,
8915 "Error: non-null column separator required for import\n");
drhccb37812020-03-09 15:39:39 +00008916 goto meta_command_exit;
8917 }
8918 if( nSep>1 ){
larrybr2f5f6742022-05-09 12:29:47 +00008919 raw_printf(stderr,
drhccb37812020-03-09 15:39:39 +00008920 "Error: multi-character column separators not allowed"
8921 " for import\n");
drhccb37812020-03-09 15:39:39 +00008922 goto meta_command_exit;
8923 }
drh2ce15c32017-07-11 13:34:40 +00008924 nSep = strlen30(p->rowSeparator);
drhccb37812020-03-09 15:39:39 +00008925 if( nSep==0 ){
8926 raw_printf(stderr,
8927 "Error: non-null row separator required for import\n");
drhccb37812020-03-09 15:39:39 +00008928 goto meta_command_exit;
8929 }
8930 if( nSep==2 && p->mode==MODE_Csv && strcmp(p->rowSeparator,SEP_CrLf)==0 ){
8931 /* When importing CSV (only), if the row separator is set to the
8932 ** default output row separator, change it to the default input
8933 ** row separator. This avoids having to maintain different input
8934 ** and output row separators. */
8935 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
8936 nSep = strlen30(p->rowSeparator);
8937 }
8938 if( nSep>1 ){
8939 raw_printf(stderr, "Error: multi-character row separators not allowed"
8940 " for import\n");
drhccb37812020-03-09 15:39:39 +00008941 goto meta_command_exit;
8942 }
8943 sCtx.cColSep = p->colSeparator[0];
8944 sCtx.cRowSep = p->rowSeparator[0];
drh2ce15c32017-07-11 13:34:40 +00008945 }
8946 sCtx.zFile = zFile;
8947 sCtx.nLine = 1;
8948 if( sCtx.zFile[0]=='|' ){
8949#ifdef SQLITE_OMIT_POPEN
8950 raw_printf(stderr, "Error: pipes are not supported in this OS\n");
drhccb37812020-03-09 15:39:39 +00008951 goto meta_command_exit;
drh2ce15c32017-07-11 13:34:40 +00008952#else
8953 sCtx.in = popen(sCtx.zFile+1, "r");
8954 sCtx.zFile = "<pipe>";
drh97767842020-05-29 19:39:35 +00008955 sCtx.xCloser = pclose;
drh2ce15c32017-07-11 13:34:40 +00008956#endif
8957 }else{
8958 sCtx.in = fopen(sCtx.zFile, "rb");
drh97767842020-05-29 19:39:35 +00008959 sCtx.xCloser = fclose;
drh2ce15c32017-07-11 13:34:40 +00008960 }
drh2ce15c32017-07-11 13:34:40 +00008961 if( sCtx.in==0 ){
8962 utf8_printf(stderr, "Error: cannot open \"%s\"\n", zFile);
drhccb37812020-03-09 15:39:39 +00008963 goto meta_command_exit;
drh2ce15c32017-07-11 13:34:40 +00008964 }
larrybr2f5f6742022-05-09 12:29:47 +00008965 rc = 0;
drhccb37812020-03-09 15:39:39 +00008966 if( eVerbose>=2 || (eVerbose>=1 && useOutputMode) ){
8967 char zSep[2];
8968 zSep[1] = 0;
8969 zSep[0] = sCtx.cColSep;
8970 utf8_printf(p->out, "Column separator ");
8971 output_c_string(p->out, zSep);
8972 utf8_printf(p->out, ", row separator ");
8973 zSep[0] = sCtx.cRowSep;
8974 output_c_string(p->out, zSep);
8975 utf8_printf(p->out, "\n");
8976 }
larrybr2f5f6742022-05-09 12:29:47 +00008977 sCtx.z = sqlite3_malloc64(120);
8978 if( sCtx.z==0 ){
8979 import_cleanup(&sCtx);
8980 shell_out_of_memory();
8981 }
larrybr53e11862022-03-06 23:41:21 +00008982 /* Below, resources must be freed before exit. */
drhccb37812020-03-09 15:39:39 +00008983 while( (nSkip--)>0 ){
8984 while( xRead(&sCtx) && sCtx.cTerm==sCtx.cColSep ){}
drhccb37812020-03-09 15:39:39 +00008985 }
larrybr53e11862022-03-06 23:41:21 +00008986 if( zSchema!=0 ){
larrybr41f46702022-03-07 00:14:52 +00008987 zFullTabName = sqlite3_mprintf("\"%w\".\"%w\"", zSchema, zTable);
larrybr53e11862022-03-06 23:41:21 +00008988 }else{
larrybr41f46702022-03-07 00:14:52 +00008989 zFullTabName = sqlite3_mprintf("\"%w\"", zTable);
larrybr53e11862022-03-06 23:41:21 +00008990 }
larrybr41f46702022-03-07 00:14:52 +00008991 zSql = sqlite3_mprintf("SELECT * FROM %s", zFullTabName);
8992 if( zSql==0 || zFullTabName==0 ){
drh97767842020-05-29 19:39:35 +00008993 import_cleanup(&sCtx);
drh4b5345c2018-04-24 13:07:40 +00008994 shell_out_of_memory();
drh2ce15c32017-07-11 13:34:40 +00008995 }
8996 nByte = strlen30(zSql);
8997 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
8998 import_append_char(&sCtx, 0); /* To ensure sCtx.z is allocated */
8999 if( rc && sqlite3_strglob("no such table: *", sqlite3_errmsg(p->db))==0 ){
larrybr58a53d62022-02-10 03:21:48 +00009000 sqlite3 *dbCols = 0;
larrybr33633862022-02-14 01:12:46 +00009001 char *zRenames = 0;
larrybr58a53d62022-02-10 03:21:48 +00009002 char *zColDefs;
drhe684ac62022-03-08 13:59:46 +00009003 zCreate = sqlite3_mprintf("CREATE TABLE %s", zFullTabName);
drh2ce15c32017-07-11 13:34:40 +00009004 while( xRead(&sCtx) ){
larrybra0337272022-02-11 13:40:25 +00009005 zAutoColumn(sCtx.z, &dbCols, 0);
drh2ce15c32017-07-11 13:34:40 +00009006 if( sCtx.cTerm!=sCtx.cColSep ) break;
larrybr4c5c6212022-02-11 01:21:09 +00009007 }
larrybr33633862022-02-14 01:12:46 +00009008 zColDefs = zAutoColumn(0, &dbCols, &zRenames);
9009 if( zRenames!=0 ){
larrybra0337272022-02-11 13:40:25 +00009010 utf8_printf((stdin_is_interactive && p->in==stdin)? p->out : stderr,
larrybr33633862022-02-14 01:12:46 +00009011 "Columns renamed during .import %s due to duplicates:\n"
9012 "%s\n", sCtx.zFile, zRenames);
9013 sqlite3_free(zRenames);
larrybra0337272022-02-11 13:40:25 +00009014 }
larrybr58a53d62022-02-10 03:21:48 +00009015 assert(dbCols==0);
9016 if( zColDefs==0 ){
drh2ce15c32017-07-11 13:34:40 +00009017 utf8_printf(stderr,"%s: empty file\n", sCtx.zFile);
larrybr53e11862022-03-06 23:41:21 +00009018 import_fail:
9019 sqlite3_free(zCreate);
9020 sqlite3_free(zSql);
larrybr41f46702022-03-07 00:14:52 +00009021 sqlite3_free(zFullTabName);
larrybr53e11862022-03-06 23:41:21 +00009022 import_cleanup(&sCtx);
drhccb37812020-03-09 15:39:39 +00009023 rc = 1;
9024 goto meta_command_exit;
drh2ce15c32017-07-11 13:34:40 +00009025 }
larrybr58a53d62022-02-10 03:21:48 +00009026 zCreate = sqlite3_mprintf("%z%z\n", zCreate, zColDefs);
drhccb37812020-03-09 15:39:39 +00009027 if( eVerbose>=1 ){
9028 utf8_printf(p->out, "%s\n", zCreate);
9029 }
drh2ce15c32017-07-11 13:34:40 +00009030 rc = sqlite3_exec(p->db, zCreate, 0, 0, 0);
drh2ce15c32017-07-11 13:34:40 +00009031 if( rc ){
larrybrce0b5e42022-01-14 16:29:45 +00009032 utf8_printf(stderr, "%s failed:\n%s\n", zCreate, sqlite3_errmsg(p->db));
larrybr53e11862022-03-06 23:41:21 +00009033 goto import_fail;
drh2ce15c32017-07-11 13:34:40 +00009034 }
larrybrce0b5e42022-01-14 16:29:45 +00009035 sqlite3_free(zCreate);
larrybr53e11862022-03-06 23:41:21 +00009036 zCreate = 0;
drh2ce15c32017-07-11 13:34:40 +00009037 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
9038 }
drh2ce15c32017-07-11 13:34:40 +00009039 if( rc ){
9040 if (pStmt) sqlite3_finalize(pStmt);
9041 utf8_printf(stderr,"Error: %s\n", sqlite3_errmsg(p->db));
larrybr53e11862022-03-06 23:41:21 +00009042 goto import_fail;
drh2ce15c32017-07-11 13:34:40 +00009043 }
larrybr53e11862022-03-06 23:41:21 +00009044 sqlite3_free(zSql);
drh2ce15c32017-07-11 13:34:40 +00009045 nCol = sqlite3_column_count(pStmt);
9046 sqlite3_finalize(pStmt);
9047 pStmt = 0;
9048 if( nCol==0 ) return 0; /* no columns, no error */
9049 zSql = sqlite3_malloc64( nByte*2 + 20 + nCol*2 );
9050 if( zSql==0 ){
drh97767842020-05-29 19:39:35 +00009051 import_cleanup(&sCtx);
drh4b5345c2018-04-24 13:07:40 +00009052 shell_out_of_memory();
drh2ce15c32017-07-11 13:34:40 +00009053 }
larrybr41f46702022-03-07 00:14:52 +00009054 sqlite3_snprintf(nByte+20, zSql, "INSERT INTO %s VALUES(?", zFullTabName);
drh2ce15c32017-07-11 13:34:40 +00009055 j = strlen30(zSql);
9056 for(i=1; i<nCol; i++){
9057 zSql[j++] = ',';
9058 zSql[j++] = '?';
9059 }
9060 zSql[j++] = ')';
9061 zSql[j] = 0;
drhccb37812020-03-09 15:39:39 +00009062 if( eVerbose>=2 ){
9063 utf8_printf(p->out, "Insert using: %s\n", zSql);
9064 }
drh2ce15c32017-07-11 13:34:40 +00009065 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
drh2ce15c32017-07-11 13:34:40 +00009066 if( rc ){
9067 utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
9068 if (pStmt) sqlite3_finalize(pStmt);
larrybr53e11862022-03-06 23:41:21 +00009069 goto import_fail;
drh2ce15c32017-07-11 13:34:40 +00009070 }
larrybr53e11862022-03-06 23:41:21 +00009071 sqlite3_free(zSql);
larrybr41f46702022-03-07 00:14:52 +00009072 sqlite3_free(zFullTabName);
drh2ce15c32017-07-11 13:34:40 +00009073 needCommit = sqlite3_get_autocommit(p->db);
9074 if( needCommit ) sqlite3_exec(p->db, "BEGIN", 0, 0, 0);
9075 do{
9076 int startLine = sCtx.nLine;
9077 for(i=0; i<nCol; i++){
9078 char *z = xRead(&sCtx);
9079 /*
9080 ** Did we reach end-of-file before finding any columns?
9081 ** If so, stop instead of NULL filling the remaining columns.
9082 */
9083 if( z==0 && i==0 ) break;
9084 /*
9085 ** Did we reach end-of-file OR end-of-line before finding any
9086 ** columns in ASCII mode? If so, stop instead of NULL filling
9087 ** the remaining columns.
9088 */
9089 if( p->mode==MODE_Ascii && (z==0 || z[0]==0) && i==0 ) break;
9090 sqlite3_bind_text(pStmt, i+1, z, -1, SQLITE_TRANSIENT);
9091 if( i<nCol-1 && sCtx.cTerm!=sCtx.cColSep ){
9092 utf8_printf(stderr, "%s:%d: expected %d columns but found %d - "
9093 "filling the rest with NULL\n",
9094 sCtx.zFile, startLine, nCol, i+1);
9095 i += 2;
9096 while( i<=nCol ){ sqlite3_bind_null(pStmt, i); i++; }
9097 }
9098 }
9099 if( sCtx.cTerm==sCtx.cColSep ){
9100 do{
9101 xRead(&sCtx);
9102 i++;
9103 }while( sCtx.cTerm==sCtx.cColSep );
9104 utf8_printf(stderr, "%s:%d: expected %d columns but found %d - "
9105 "extras ignored\n",
9106 sCtx.zFile, startLine, nCol, i);
9107 }
9108 if( i>=nCol ){
9109 sqlite3_step(pStmt);
9110 rc = sqlite3_reset(pStmt);
9111 if( rc!=SQLITE_OK ){
9112 utf8_printf(stderr, "%s:%d: INSERT failed: %s\n", sCtx.zFile,
9113 startLine, sqlite3_errmsg(p->db));
drhccb37812020-03-09 15:39:39 +00009114 sCtx.nErr++;
9115 }else{
9116 sCtx.nRow++;
drh2ce15c32017-07-11 13:34:40 +00009117 }
9118 }
9119 }while( sCtx.cTerm!=EOF );
9120
drh97767842020-05-29 19:39:35 +00009121 import_cleanup(&sCtx);
drh2ce15c32017-07-11 13:34:40 +00009122 sqlite3_finalize(pStmt);
9123 if( needCommit ) sqlite3_exec(p->db, "COMMIT", 0, 0, 0);
drhccb37812020-03-09 15:39:39 +00009124 if( eVerbose>0 ){
9125 utf8_printf(p->out,
9126 "Added %d rows with %d errors using %d lines of input\n",
9127 sCtx.nRow, sCtx.nErr, sCtx.nLine-1);
9128 }
drh2ce15c32017-07-11 13:34:40 +00009129 }else
9130
9131#ifndef SQLITE_UNTESTABLE
9132 if( c=='i' && strncmp(azArg[0], "imposter", n)==0 ){
9133 char *zSql;
9134 char *zCollist = 0;
9135 sqlite3_stmt *pStmt;
9136 int tnum = 0;
drh491c5be2019-10-18 15:58:50 +00009137 int isWO = 0; /* True if making an imposter of a WITHOUT ROWID table */
9138 int lenPK = 0; /* Length of the PRIMARY KEY string for isWO tables */
drh2ce15c32017-07-11 13:34:40 +00009139 int i;
drh48d219a2018-04-23 18:38:48 +00009140 if( !(nArg==3 || (nArg==2 && sqlite3_stricmp(azArg[1],"off")==0)) ){
9141 utf8_printf(stderr, "Usage: .imposter INDEX IMPOSTER\n"
9142 " .imposter off\n");
drh491c5be2019-10-18 15:58:50 +00009143 /* Also allowed, but not documented:
9144 **
9145 ** .imposter TABLE IMPOSTER
9146 **
9147 ** where TABLE is a WITHOUT ROWID table. In that case, the
9148 ** imposter is another WITHOUT ROWID table with the columns in
9149 ** storage order. */
drh2ce15c32017-07-11 13:34:40 +00009150 rc = 1;
9151 goto meta_command_exit;
9152 }
9153 open_db(p, 0);
drh48d219a2018-04-23 18:38:48 +00009154 if( nArg==2 ){
9155 sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 0, 1);
9156 goto meta_command_exit;
9157 }
drh491c5be2019-10-18 15:58:50 +00009158 zSql = sqlite3_mprintf(
drh067b92b2020-06-19 15:24:12 +00009159 "SELECT rootpage, 0 FROM sqlite_schema"
drh491c5be2019-10-18 15:58:50 +00009160 " WHERE name='%q' AND type='index'"
9161 "UNION ALL "
drh067b92b2020-06-19 15:24:12 +00009162 "SELECT rootpage, 1 FROM sqlite_schema"
drh491c5be2019-10-18 15:58:50 +00009163 " WHERE name='%q' AND type='table'"
9164 " AND sql LIKE '%%without%%rowid%%'",
9165 azArg[1], azArg[1]
9166 );
drh2ce15c32017-07-11 13:34:40 +00009167 sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
9168 sqlite3_free(zSql);
9169 if( sqlite3_step(pStmt)==SQLITE_ROW ){
9170 tnum = sqlite3_column_int(pStmt, 0);
drh491c5be2019-10-18 15:58:50 +00009171 isWO = sqlite3_column_int(pStmt, 1);
drh2ce15c32017-07-11 13:34:40 +00009172 }
9173 sqlite3_finalize(pStmt);
drh2ce15c32017-07-11 13:34:40 +00009174 zSql = sqlite3_mprintf("PRAGMA index_xinfo='%q'", azArg[1]);
9175 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
9176 sqlite3_free(zSql);
9177 i = 0;
drhe85e1da2021-10-01 21:01:07 +00009178 while( rc==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW ){
drh2ce15c32017-07-11 13:34:40 +00009179 char zLabel[20];
9180 const char *zCol = (const char*)sqlite3_column_text(pStmt,2);
9181 i++;
9182 if( zCol==0 ){
9183 if( sqlite3_column_int(pStmt,1)==-1 ){
9184 zCol = "_ROWID_";
9185 }else{
9186 sqlite3_snprintf(sizeof(zLabel),zLabel,"expr%d",i);
9187 zCol = zLabel;
9188 }
9189 }
drh491c5be2019-10-18 15:58:50 +00009190 if( isWO && lenPK==0 && sqlite3_column_int(pStmt,5)==0 && zCollist ){
9191 lenPK = (int)strlen(zCollist);
9192 }
drh2ce15c32017-07-11 13:34:40 +00009193 if( zCollist==0 ){
9194 zCollist = sqlite3_mprintf("\"%w\"", zCol);
9195 }else{
9196 zCollist = sqlite3_mprintf("%z,\"%w\"", zCollist, zCol);
9197 }
9198 }
9199 sqlite3_finalize(pStmt);
drh491c5be2019-10-18 15:58:50 +00009200 if( i==0 || tnum==0 ){
9201 utf8_printf(stderr, "no such index: \"%s\"\n", azArg[1]);
9202 rc = 1;
9203 sqlite3_free(zCollist);
9204 goto meta_command_exit;
9205 }
9206 if( lenPK==0 ) lenPK = 100000;
drh2ce15c32017-07-11 13:34:40 +00009207 zSql = sqlite3_mprintf(
drh491c5be2019-10-18 15:58:50 +00009208 "CREATE TABLE \"%w\"(%s,PRIMARY KEY(%.*s))WITHOUT ROWID",
9209 azArg[2], zCollist, lenPK, zCollist);
drh2ce15c32017-07-11 13:34:40 +00009210 sqlite3_free(zCollist);
9211 rc = sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 1, tnum);
9212 if( rc==SQLITE_OK ){
9213 rc = sqlite3_exec(p->db, zSql, 0, 0, 0);
9214 sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 0, 0);
9215 if( rc ){
9216 utf8_printf(stderr, "Error in [%s]: %s\n", zSql, sqlite3_errmsg(p->db));
9217 }else{
9218 utf8_printf(stdout, "%s;\n", zSql);
9219 raw_printf(stdout,
drh491c5be2019-10-18 15:58:50 +00009220 "WARNING: writing to an imposter table will corrupt the \"%s\" %s!\n",
9221 azArg[1], isWO ? "table" : "index"
drh2ce15c32017-07-11 13:34:40 +00009222 );
9223 }
9224 }else{
9225 raw_printf(stderr, "SQLITE_TESTCTRL_IMPOSTER returns %d\n", rc);
9226 rc = 1;
9227 }
9228 sqlite3_free(zSql);
9229 }else
9230#endif /* !defined(SQLITE_OMIT_TEST_CONTROL) */
9231
9232#ifdef SQLITE_ENABLE_IOTRACE
9233 if( c=='i' && strncmp(azArg[0], "iotrace", n)==0 ){
9234 SQLITE_API extern void (SQLITE_CDECL *sqlite3IoTrace)(const char*, ...);
9235 if( iotrace && iotrace!=stdout ) fclose(iotrace);
9236 iotrace = 0;
9237 if( nArg<2 ){
9238 sqlite3IoTrace = 0;
9239 }else if( strcmp(azArg[1], "-")==0 ){
9240 sqlite3IoTrace = iotracePrintf;
9241 iotrace = stdout;
9242 }else{
9243 iotrace = fopen(azArg[1], "w");
9244 if( iotrace==0 ){
9245 utf8_printf(stderr, "Error: cannot open \"%s\"\n", azArg[1]);
9246 sqlite3IoTrace = 0;
9247 rc = 1;
9248 }else{
9249 sqlite3IoTrace = iotracePrintf;
9250 }
9251 }
9252 }else
9253#endif
9254
9255 if( c=='l' && n>=5 && strncmp(azArg[0], "limits", n)==0 ){
9256 static const struct {
9257 const char *zLimitName; /* Name of a limit */
9258 int limitCode; /* Integer code for that limit */
9259 } aLimit[] = {
9260 { "length", SQLITE_LIMIT_LENGTH },
9261 { "sql_length", SQLITE_LIMIT_SQL_LENGTH },
9262 { "column", SQLITE_LIMIT_COLUMN },
9263 { "expr_depth", SQLITE_LIMIT_EXPR_DEPTH },
9264 { "compound_select", SQLITE_LIMIT_COMPOUND_SELECT },
9265 { "vdbe_op", SQLITE_LIMIT_VDBE_OP },
9266 { "function_arg", SQLITE_LIMIT_FUNCTION_ARG },
9267 { "attached", SQLITE_LIMIT_ATTACHED },
9268 { "like_pattern_length", SQLITE_LIMIT_LIKE_PATTERN_LENGTH },
9269 { "variable_number", SQLITE_LIMIT_VARIABLE_NUMBER },
9270 { "trigger_depth", SQLITE_LIMIT_TRIGGER_DEPTH },
9271 { "worker_threads", SQLITE_LIMIT_WORKER_THREADS },
9272 };
9273 int i, n2;
9274 open_db(p, 0);
9275 if( nArg==1 ){
9276 for(i=0; i<ArraySize(aLimit); i++){
9277 printf("%20s %d\n", aLimit[i].zLimitName,
9278 sqlite3_limit(p->db, aLimit[i].limitCode, -1));
9279 }
9280 }else if( nArg>3 ){
9281 raw_printf(stderr, "Usage: .limit NAME ?NEW-VALUE?\n");
9282 rc = 1;
9283 goto meta_command_exit;
9284 }else{
9285 int iLimit = -1;
9286 n2 = strlen30(azArg[1]);
9287 for(i=0; i<ArraySize(aLimit); i++){
9288 if( sqlite3_strnicmp(aLimit[i].zLimitName, azArg[1], n2)==0 ){
9289 if( iLimit<0 ){
9290 iLimit = i;
9291 }else{
9292 utf8_printf(stderr, "ambiguous limit: \"%s\"\n", azArg[1]);
9293 rc = 1;
9294 goto meta_command_exit;
9295 }
9296 }
9297 }
9298 if( iLimit<0 ){
9299 utf8_printf(stderr, "unknown limit: \"%s\"\n"
9300 "enter \".limits\" with no arguments for a list.\n",
9301 azArg[1]);
9302 rc = 1;
9303 goto meta_command_exit;
9304 }
9305 if( nArg==3 ){
9306 sqlite3_limit(p->db, aLimit[iLimit].limitCode,
9307 (int)integerValue(azArg[2]));
9308 }
9309 printf("%20s %d\n", aLimit[iLimit].zLimitName,
9310 sqlite3_limit(p->db, aLimit[iLimit].limitCode, -1));
9311 }
9312 }else
9313
9314 if( c=='l' && n>2 && strncmp(azArg[0], "lint", n)==0 ){
9315 open_db(p, 0);
9316 lintDotCommand(p, azArg, nArg);
9317 }else
9318
9319#ifndef SQLITE_OMIT_LOAD_EXTENSION
9320 if( c=='l' && strncmp(azArg[0], "load", n)==0 ){
9321 const char *zFile, *zProc;
9322 char *zErrMsg = 0;
drhb97e2ad2021-08-26 18:31:39 +00009323 failIfSafeMode(p, "cannot run .load in safe mode");
drh2ce15c32017-07-11 13:34:40 +00009324 if( nArg<2 ){
9325 raw_printf(stderr, "Usage: .load FILE ?ENTRYPOINT?\n");
9326 rc = 1;
9327 goto meta_command_exit;
9328 }
9329 zFile = azArg[1];
9330 zProc = nArg>=3 ? azArg[2] : 0;
9331 open_db(p, 0);
9332 rc = sqlite3_load_extension(p->db, zFile, zProc, &zErrMsg);
9333 if( rc!=SQLITE_OK ){
9334 utf8_printf(stderr, "Error: %s\n", zErrMsg);
9335 sqlite3_free(zErrMsg);
9336 rc = 1;
9337 }
9338 }else
9339#endif
9340
9341 if( c=='l' && strncmp(azArg[0], "log", n)==0 ){
drhb97e2ad2021-08-26 18:31:39 +00009342 failIfSafeMode(p, "cannot run .log in safe mode");
drh2ce15c32017-07-11 13:34:40 +00009343 if( nArg!=2 ){
9344 raw_printf(stderr, "Usage: .log FILENAME\n");
9345 rc = 1;
9346 }else{
9347 const char *zFile = azArg[1];
9348 output_file_close(p->pLog);
drha92a01a2018-01-10 22:15:37 +00009349 p->pLog = output_file_open(zFile, 0);
drh2ce15c32017-07-11 13:34:40 +00009350 }
9351 }else
9352
9353 if( c=='m' && strncmp(azArg[0], "mode", n)==0 ){
drhe40f2862022-01-31 14:14:29 +00009354 const char *zMode = 0;
9355 const char *zTabname = 0;
9356 int i, n2;
larrybrcc4d55c2022-02-01 02:50:45 +00009357 ColModeOpts cmOpts = ColModeOpts_default;
drhe40f2862022-01-31 14:14:29 +00009358 for(i=1; i<nArg; i++){
9359 const char *z = azArg[i];
9360 if( optionMatch(z,"wrap") && i+1<nArg ){
larrybrcc4d55c2022-02-01 02:50:45 +00009361 cmOpts.iWrap = integerValue(azArg[++i]);
drhca1776b2022-02-01 12:28:17 +00009362 }else if( optionMatch(z,"ww") ){
9363 cmOpts.bWordWrap = 1;
larrybrcc4d55c2022-02-01 02:50:45 +00009364 }else if( optionMatch(z,"wordwrap") && i+1<nArg ){
9365 cmOpts.bWordWrap = (u8)booleanValue(azArg[++i]);
drhe40f2862022-01-31 14:14:29 +00009366 }else if( optionMatch(z,"quote") ){
larrybrcc4d55c2022-02-01 02:50:45 +00009367 cmOpts.bQuote = 1;
drhe40f2862022-01-31 14:14:29 +00009368 }else if( optionMatch(z,"noquote") ){
larrybrcc4d55c2022-02-01 02:50:45 +00009369 cmOpts.bQuote = 0;
drhe40f2862022-01-31 14:14:29 +00009370 }else if( zMode==0 ){
9371 zMode = z;
drhca1776b2022-02-01 12:28:17 +00009372 /* Apply defaults for qbox pseudo-mods. If that
larrybrcc4d55c2022-02-01 02:50:45 +00009373 * overwrites already-set values, user was informed of this.
9374 */
9375 if( strcmp(z, "qbox")==0 ){
9376 ColModeOpts cmo = ColModeOpts_default_qbox;
9377 zMode = "box";
9378 cmOpts = cmo;
larrybrcc4d55c2022-02-01 02:50:45 +00009379 }
drhe40f2862022-01-31 14:14:29 +00009380 }else if( zTabname==0 ){
9381 zTabname = z;
9382 }else if( z[0]=='-' ){
9383 utf8_printf(stderr, "unknown option: %s\n", z);
9384 utf8_printf(stderr, "options:\n"
9385 " --noquote\n"
9386 " --quote\n"
larrybrcc4d55c2022-02-01 02:50:45 +00009387 " --wordwrap on/off\n"
drhca1776b2022-02-01 12:28:17 +00009388 " --wrap N\n"
9389 " --ww\n");
drhe40f2862022-01-31 14:14:29 +00009390 rc = 1;
9391 goto meta_command_exit;
9392 }else{
9393 utf8_printf(stderr, "extra argument: \"%s\"\n", z);
9394 rc = 1;
9395 goto meta_command_exit;
9396 }
9397 }
9398 if( zMode==0 ){
9399 if( p->mode==MODE_Column
9400 || (p->mode>=MODE_Markdown && p->mode<=MODE_Box)
9401 ){
larrybrcc4d55c2022-02-01 02:50:45 +00009402 raw_printf
9403 (p->out,
9404 "current output mode: %s --wrap %d --wordwrap %s --%squote\n",
9405 modeDescr[p->mode], p->cmOpts.iWrap,
9406 p->cmOpts.bWordWrap ? "on" : "off",
9407 p->cmOpts.bQuote ? "" : "no");
drhe40f2862022-01-31 14:14:29 +00009408 }else{
9409 raw_printf(p->out, "current output mode: %s\n", modeDescr[p->mode]);
9410 }
drhe40f2862022-01-31 14:14:29 +00009411 zMode = modeDescr[p->mode];
9412 }
9413 n2 = strlen30(zMode);
9414 if( strncmp(zMode,"lines",n2)==0 ){
drh2ce15c32017-07-11 13:34:40 +00009415 p->mode = MODE_Line;
9416 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
drhe40f2862022-01-31 14:14:29 +00009417 }else if( strncmp(zMode,"columns",n2)==0 ){
drh2ce15c32017-07-11 13:34:40 +00009418 p->mode = MODE_Column;
drhc0605082020-06-05 00:54:27 +00009419 if( (p->shellFlgs & SHFLG_HeaderSet)==0 ){
9420 p->showHeader = 1;
9421 }
drh2ce15c32017-07-11 13:34:40 +00009422 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
larrybrcc4d55c2022-02-01 02:50:45 +00009423 p->cmOpts = cmOpts;
drhe40f2862022-01-31 14:14:29 +00009424 }else if( strncmp(zMode,"list",n2)==0 ){
drh2ce15c32017-07-11 13:34:40 +00009425 p->mode = MODE_List;
9426 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Column);
9427 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
drhe40f2862022-01-31 14:14:29 +00009428 }else if( strncmp(zMode,"html",n2)==0 ){
drh2ce15c32017-07-11 13:34:40 +00009429 p->mode = MODE_Html;
drhe40f2862022-01-31 14:14:29 +00009430 }else if( strncmp(zMode,"tcl",n2)==0 ){
drh2ce15c32017-07-11 13:34:40 +00009431 p->mode = MODE_Tcl;
9432 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Space);
9433 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
drhe40f2862022-01-31 14:14:29 +00009434 }else if( strncmp(zMode,"csv",n2)==0 ){
drh2ce15c32017-07-11 13:34:40 +00009435 p->mode = MODE_Csv;
9436 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Comma);
9437 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_CrLf);
drhe40f2862022-01-31 14:14:29 +00009438 }else if( strncmp(zMode,"tabs",n2)==0 ){
drh2ce15c32017-07-11 13:34:40 +00009439 p->mode = MODE_List;
9440 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Tab);
drhe40f2862022-01-31 14:14:29 +00009441 }else if( strncmp(zMode,"insert",n2)==0 ){
drh2ce15c32017-07-11 13:34:40 +00009442 p->mode = MODE_Insert;
drhe40f2862022-01-31 14:14:29 +00009443 set_table_name(p, zTabname ? zTabname : "table");
9444 }else if( strncmp(zMode,"quote",n2)==0 ){
drh2ce15c32017-07-11 13:34:40 +00009445 p->mode = MODE_Quote;
drhc6835732020-05-28 20:37:17 +00009446 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Comma);
9447 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
drhe40f2862022-01-31 14:14:29 +00009448 }else if( strncmp(zMode,"ascii",n2)==0 ){
drh2ce15c32017-07-11 13:34:40 +00009449 p->mode = MODE_Ascii;
9450 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Unit);
9451 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Record);
drhe40f2862022-01-31 14:14:29 +00009452 }else if( strncmp(zMode,"markdown",n2)==0 ){
drh30c54a02020-05-28 23:49:50 +00009453 p->mode = MODE_Markdown;
larrybrcc4d55c2022-02-01 02:50:45 +00009454 p->cmOpts = cmOpts;
drhe40f2862022-01-31 14:14:29 +00009455 }else if( strncmp(zMode,"table",n2)==0 ){
drh30c54a02020-05-28 23:49:50 +00009456 p->mode = MODE_Table;
larrybrcc4d55c2022-02-01 02:50:45 +00009457 p->cmOpts = cmOpts;
drhe40f2862022-01-31 14:14:29 +00009458 }else if( strncmp(zMode,"box",n2)==0 ){
drh0908e382020-06-04 18:05:39 +00009459 p->mode = MODE_Box;
larrybrcc4d55c2022-02-01 02:50:45 +00009460 p->cmOpts = cmOpts;
drhe40f2862022-01-31 14:14:29 +00009461 }else if( strncmp(zMode,"count",n2)==0 ){
drh5d88be82021-12-09 16:17:43 +00009462 p->mode = MODE_Count;
drhe40f2862022-01-31 14:14:29 +00009463 }else if( strncmp(zMode,"off",n2)==0 ){
drh5d88be82021-12-09 16:17:43 +00009464 p->mode = MODE_Off;
drhe40f2862022-01-31 14:14:29 +00009465 }else if( strncmp(zMode,"json",n2)==0 ){
drh30c54a02020-05-28 23:49:50 +00009466 p->mode = MODE_Json;
drh2ce15c32017-07-11 13:34:40 +00009467 }else{
9468 raw_printf(stderr, "Error: mode should be one of: "
drh0908e382020-06-04 18:05:39 +00009469 "ascii box column csv html insert json line list markdown "
drhca1776b2022-02-01 12:28:17 +00009470 "qbox quote table tabs tcl\n");
drh2ce15c32017-07-11 13:34:40 +00009471 rc = 1;
9472 }
9473 p->cMode = p->mode;
9474 }else
9475
drhb97e2ad2021-08-26 18:31:39 +00009476 if( c=='n' && strcmp(azArg[0], "nonce")==0 ){
9477 if( nArg!=2 ){
9478 raw_printf(stderr, "Usage: .nonce NONCE\n");
9479 rc = 1;
9480 }else if( p->zNonce==0 || strcmp(azArg[1],p->zNonce)!=0 ){
drhfe463172021-12-16 17:57:21 +00009481 raw_printf(stderr, "line %d: incorrect nonce: \"%s\"\n",
9482 p->lineno, azArg[1]);
drhb97e2ad2021-08-26 18:31:39 +00009483 exit(1);
drhe85e1da2021-10-01 21:01:07 +00009484 }else{
9485 p->bSafeMode = 0;
9486 return 0; /* Return immediately to bypass the safe mode reset
9487 ** at the end of this procedure */
drhb97e2ad2021-08-26 18:31:39 +00009488 }
drhb97e2ad2021-08-26 18:31:39 +00009489 }else
9490
drh2ce15c32017-07-11 13:34:40 +00009491 if( c=='n' && strncmp(azArg[0], "nullvalue", n)==0 ){
9492 if( nArg==2 ){
9493 sqlite3_snprintf(sizeof(p->nullValue), p->nullValue,
9494 "%.*s", (int)ArraySize(p->nullValue)-1, azArg[1]);
9495 }else{
9496 raw_printf(stderr, "Usage: .nullvalue STRING\n");
9497 rc = 1;
9498 }
9499 }else
9500
9501 if( c=='o' && strncmp(azArg[0], "open", n)==0 && n>=2 ){
drh61fd4b92021-12-16 14:59:25 +00009502 const char *zFN = 0; /* Pointer to constant filename */
drhf30bbce2020-12-02 18:27:48 +00009503 char *zNewFilename = 0; /* Name of the database file to open */
9504 int iName = 1; /* Index in azArg[] of the filename */
9505 int newFlag = 0; /* True to delete file before opening */
dan1872c5b2021-12-02 14:16:30 +00009506 int openMode = SHELL_OPEN_UNSPEC;
9507
drh2ce15c32017-07-11 13:34:40 +00009508 /* Check for command-line arguments */
drhf30bbce2020-12-02 18:27:48 +00009509 for(iName=1; iName<nArg; iName++){
drh2ce15c32017-07-11 13:34:40 +00009510 const char *z = azArg[iName];
9511 if( optionMatch(z,"new") ){
9512 newFlag = 1;
drh3baed312018-03-08 18:14:41 +00009513#ifdef SQLITE_HAVE_ZLIB
drh1fa6d9f2018-01-06 21:46:01 +00009514 }else if( optionMatch(z, "zip") ){
dan1872c5b2021-12-02 14:16:30 +00009515 openMode = SHELL_OPEN_ZIPFILE;
drh1fa6d9f2018-01-06 21:46:01 +00009516#endif
9517 }else if( optionMatch(z, "append") ){
dan1872c5b2021-12-02 14:16:30 +00009518 openMode = SHELL_OPEN_APPENDVFS;
drhee269a62018-02-14 23:27:43 +00009519 }else if( optionMatch(z, "readonly") ){
dan1872c5b2021-12-02 14:16:30 +00009520 openMode = SHELL_OPEN_READONLY;
drh0933aad2019-11-18 17:46:38 +00009521 }else if( optionMatch(z, "nofollow") ){
9522 p->openFlags |= SQLITE_OPEN_NOFOLLOW;
drh8d889af2021-05-08 17:18:23 +00009523#ifndef SQLITE_OMIT_DESERIALIZE
drh60f34ae2018-10-30 13:19:49 +00009524 }else if( optionMatch(z, "deserialize") ){
dan1872c5b2021-12-02 14:16:30 +00009525 openMode = SHELL_OPEN_DESERIALIZE;
drh33746482018-12-13 15:06:26 +00009526 }else if( optionMatch(z, "hexdb") ){
dan1872c5b2021-12-02 14:16:30 +00009527 openMode = SHELL_OPEN_HEXDB;
drh6ca64482019-01-22 16:06:20 +00009528 }else if( optionMatch(z, "maxsize") && iName+1<nArg ){
9529 p->szMax = integerValue(azArg[++iName]);
drh8d889af2021-05-08 17:18:23 +00009530#endif /* SQLITE_OMIT_DESERIALIZE */
drh2ce15c32017-07-11 13:34:40 +00009531 }else if( z[0]=='-' ){
9532 utf8_printf(stderr, "unknown option: %s\n", z);
9533 rc = 1;
9534 goto meta_command_exit;
drh61fd4b92021-12-16 14:59:25 +00009535 }else if( zFN ){
drhf30bbce2020-12-02 18:27:48 +00009536 utf8_printf(stderr, "extra argument: \"%s\"\n", z);
9537 rc = 1;
9538 goto meta_command_exit;
9539 }else{
drh61fd4b92021-12-16 14:59:25 +00009540 zFN = z;
drh2ce15c32017-07-11 13:34:40 +00009541 }
9542 }
dan1872c5b2021-12-02 14:16:30 +00009543
9544 /* Close the existing database */
9545 session_close_all(p, -1);
9546 close_db(p->db);
9547 p->db = 0;
9548 p->pAuxDb->zDbFilename = 0;
9549 sqlite3_free(p->pAuxDb->zFreeOnClose);
9550 p->pAuxDb->zFreeOnClose = 0;
9551 p->openMode = openMode;
9552 p->openFlags = 0;
9553 p->szMax = 0;
9554
drh2ce15c32017-07-11 13:34:40 +00009555 /* If a filename is specified, try to open it first */
drh61fd4b92021-12-16 14:59:25 +00009556 if( zFN || p->openMode==SHELL_OPEN_HEXDB ){
drhc320e062021-12-24 19:44:11 +00009557 if( newFlag && zFN && !p->bSafeMode ) shellDeleteFile(zFN);
drhb97e2ad2021-08-26 18:31:39 +00009558 if( p->bSafeMode
9559 && p->openMode!=SHELL_OPEN_HEXDB
drhc320e062021-12-24 19:44:11 +00009560 && zFN
9561 && strcmp(zFN,":memory:")!=0
drhb97e2ad2021-08-26 18:31:39 +00009562 ){
9563 failIfSafeMode(p, "cannot open disk-based database files in safe mode");
9564 }
drh61fd4b92021-12-16 14:59:25 +00009565 if( zFN ){
9566 zNewFilename = sqlite3_mprintf("%s", zFN);
9567 shell_check_oom(zNewFilename);
9568 }else{
9569 zNewFilename = 0;
9570 }
drh37407122021-07-23 18:43:58 +00009571 p->pAuxDb->zDbFilename = zNewFilename;
drhbe4ccb22018-05-17 20:04:24 +00009572 open_db(p, OPEN_DB_KEEPALIVE);
drh2ce15c32017-07-11 13:34:40 +00009573 if( p->db==0 ){
9574 utf8_printf(stderr, "Error: cannot open '%s'\n", zNewFilename);
9575 sqlite3_free(zNewFilename);
9576 }else{
drh37407122021-07-23 18:43:58 +00009577 p->pAuxDb->zFreeOnClose = zNewFilename;
drh2ce15c32017-07-11 13:34:40 +00009578 }
9579 }
9580 if( p->db==0 ){
9581 /* As a fall-back open a TEMP database */
drh37407122021-07-23 18:43:58 +00009582 p->pAuxDb->zDbFilename = 0;
drh2ce15c32017-07-11 13:34:40 +00009583 open_db(p, 0);
9584 }
9585 }else
9586
drh13c20932018-01-10 21:41:55 +00009587 if( (c=='o'
9588 && (strncmp(azArg[0], "output", n)==0||strncmp(azArg[0], "once", n)==0))
9589 || (c=='e' && n==5 && strcmp(azArg[0],"excel")==0)
drh2ce15c32017-07-11 13:34:40 +00009590 ){
drh4b0229a2021-02-17 13:19:22 +00009591 char *zFile = 0;
drha92a01a2018-01-10 22:15:37 +00009592 int bTxtMode = 0;
drh7a431002020-04-18 14:12:00 +00009593 int i;
9594 int eMode = 0;
drh8ad3c432022-03-23 10:04:52 +00009595 int bOnce = 0; /* 0: .output, 1: .once, 2: .excel */
9596 unsigned char zBOM[4]; /* Byte-order mark to using if --bom is present */
drh7a431002020-04-18 14:12:00 +00009597
drh8ad3c432022-03-23 10:04:52 +00009598 zBOM[0] = 0;
drhb97e2ad2021-08-26 18:31:39 +00009599 failIfSafeMode(p, "cannot run .%s in safe mode", azArg[0]);
drh7a431002020-04-18 14:12:00 +00009600 if( c=='e' ){
9601 eMode = 'x';
9602 bOnce = 2;
9603 }else if( strncmp(azArg[0],"once",n)==0 ){
9604 bOnce = 1;
drh13c20932018-01-10 21:41:55 +00009605 }
drh7a431002020-04-18 14:12:00 +00009606 for(i=1; i<nArg; i++){
9607 char *z = azArg[i];
9608 if( z[0]=='-' ){
9609 if( z[1]=='-' ) z++;
9610 if( strcmp(z,"-bom")==0 ){
drh8ad3c432022-03-23 10:04:52 +00009611 zBOM[0] = 0xef;
9612 zBOM[1] = 0xbb;
9613 zBOM[2] = 0xbf;
9614 zBOM[3] = 0;
drh7a431002020-04-18 14:12:00 +00009615 }else if( c!='e' && strcmp(z,"-x")==0 ){
9616 eMode = 'x'; /* spreadsheet */
9617 }else if( c!='e' && strcmp(z,"-e")==0 ){
9618 eMode = 'e'; /* text editor */
9619 }else{
9620 utf8_printf(p->out, "ERROR: unknown option: \"%s\". Usage:\n",
9621 azArg[i]);
9622 showHelp(p->out, azArg[0]);
9623 rc = 1;
9624 goto meta_command_exit;
9625 }
drh4b0229a2021-02-17 13:19:22 +00009626 }else if( zFile==0 && eMode!='e' && eMode!='x' ){
9627 zFile = sqlite3_mprintf("%s", z);
drhe3e25652021-12-16 13:29:28 +00009628 if( zFile && zFile[0]=='|' ){
drh4b0229a2021-02-17 13:19:22 +00009629 while( i+1<nArg ) zFile = sqlite3_mprintf("%z %s", zFile, azArg[++i]);
9630 break;
9631 }
drh7a431002020-04-18 14:12:00 +00009632 }else{
9633 utf8_printf(p->out,"ERROR: extra parameter: \"%s\". Usage:\n",
9634 azArg[i]);
9635 showHelp(p->out, azArg[0]);
drh2ce15c32017-07-11 13:34:40 +00009636 rc = 1;
drh4b0229a2021-02-17 13:19:22 +00009637 sqlite3_free(zFile);
drh2ce15c32017-07-11 13:34:40 +00009638 goto meta_command_exit;
9639 }
drh7a431002020-04-18 14:12:00 +00009640 }
drhe3e25652021-12-16 13:29:28 +00009641 if( zFile==0 ){
9642 zFile = sqlite3_mprintf("stdout");
9643 }
drh7a431002020-04-18 14:12:00 +00009644 if( bOnce ){
drh2ce15c32017-07-11 13:34:40 +00009645 p->outCount = 2;
9646 }else{
9647 p->outCount = 0;
9648 }
9649 output_reset(p);
drh04a28c32018-01-31 01:38:44 +00009650#ifndef SQLITE_NOHAVE_SYSTEM
drh7a431002020-04-18 14:12:00 +00009651 if( eMode=='e' || eMode=='x' ){
drh3c484e82018-01-10 22:27:21 +00009652 p->doXdgOpen = 1;
9653 outputModePush(p);
drh7a431002020-04-18 14:12:00 +00009654 if( eMode=='x' ){
9655 /* spreadsheet mode. Output as CSV. */
drh13c20932018-01-10 21:41:55 +00009656 newTempFile(p, "csv");
drh7a431002020-04-18 14:12:00 +00009657 ShellClearFlag(p, SHFLG_Echo);
drh13c20932018-01-10 21:41:55 +00009658 p->mode = MODE_Csv;
9659 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Comma);
9660 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_CrLf);
9661 }else{
drh7a431002020-04-18 14:12:00 +00009662 /* text editor mode */
drh13c20932018-01-10 21:41:55 +00009663 newTempFile(p, "txt");
drha92a01a2018-01-10 22:15:37 +00009664 bTxtMode = 1;
drh13c20932018-01-10 21:41:55 +00009665 }
drh4b0229a2021-02-17 13:19:22 +00009666 sqlite3_free(zFile);
9667 zFile = sqlite3_mprintf("%s", p->zTempFile);
drh13c20932018-01-10 21:41:55 +00009668 }
drh04a28c32018-01-31 01:38:44 +00009669#endif /* SQLITE_NOHAVE_SYSTEM */
drhe3e25652021-12-16 13:29:28 +00009670 shell_check_oom(zFile);
drh2ce15c32017-07-11 13:34:40 +00009671 if( zFile[0]=='|' ){
9672#ifdef SQLITE_OMIT_POPEN
9673 raw_printf(stderr, "Error: pipes are not supported in this OS\n");
9674 rc = 1;
9675 p->out = stdout;
9676#else
9677 p->out = popen(zFile + 1, "w");
9678 if( p->out==0 ){
9679 utf8_printf(stderr,"Error: cannot open pipe \"%s\"\n", zFile + 1);
9680 p->out = stdout;
9681 rc = 1;
9682 }else{
drh8ad3c432022-03-23 10:04:52 +00009683 if( zBOM[0] ) fwrite(zBOM, 1, 3, p->out);
drh2ce15c32017-07-11 13:34:40 +00009684 sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", zFile);
9685 }
9686#endif
9687 }else{
drha92a01a2018-01-10 22:15:37 +00009688 p->out = output_file_open(zFile, bTxtMode);
drh2ce15c32017-07-11 13:34:40 +00009689 if( p->out==0 ){
9690 if( strcmp(zFile,"off")!=0 ){
9691 utf8_printf(stderr,"Error: cannot write to \"%s\"\n", zFile);
9692 }
9693 p->out = stdout;
9694 rc = 1;
9695 } else {
drh8ad3c432022-03-23 10:04:52 +00009696 if( zBOM[0] ) fwrite(zBOM, 1, 3, p->out);
drh2ce15c32017-07-11 13:34:40 +00009697 sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", zFile);
9698 }
9699 }
drh4b0229a2021-02-17 13:19:22 +00009700 sqlite3_free(zFile);
drh2ce15c32017-07-11 13:34:40 +00009701 }else
9702
drh9cb02642019-02-28 20:10:52 +00009703 if( c=='p' && n>=3 && strncmp(azArg[0], "parameter", n)==0 ){
9704 open_db(p,0);
9705 if( nArg<=1 ) goto parameter_syntax_error;
9706
9707 /* .parameter clear
9708 ** Clear all bind parameters by dropping the TEMP table that holds them.
9709 */
9710 if( nArg==2 && strcmp(azArg[1],"clear")==0 ){
drh65c29fd2019-03-25 21:56:26 +00009711 sqlite3_exec(p->db, "DROP TABLE IF EXISTS temp.sqlite_parameters;",
drh9cb02642019-02-28 20:10:52 +00009712 0, 0, 0);
9713 }else
9714
9715 /* .parameter list
9716 ** List all bind parameters.
9717 */
9718 if( nArg==2 && strcmp(azArg[1],"list")==0 ){
9719 sqlite3_stmt *pStmt = 0;
9720 int rx;
9721 int len = 0;
9722 rx = sqlite3_prepare_v2(p->db,
9723 "SELECT max(length(key)) "
drh65c29fd2019-03-25 21:56:26 +00009724 "FROM temp.sqlite_parameters;", -1, &pStmt, 0);
drh9cb02642019-02-28 20:10:52 +00009725 if( rx==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW ){
9726 len = sqlite3_column_int(pStmt, 0);
9727 if( len>40 ) len = 40;
9728 }
9729 sqlite3_finalize(pStmt);
9730 pStmt = 0;
9731 if( len ){
9732 rx = sqlite3_prepare_v2(p->db,
9733 "SELECT key, quote(value) "
drh65c29fd2019-03-25 21:56:26 +00009734 "FROM temp.sqlite_parameters;", -1, &pStmt, 0);
drhe85e1da2021-10-01 21:01:07 +00009735 while( rx==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW ){
drh9cb02642019-02-28 20:10:52 +00009736 utf8_printf(p->out, "%-*s %s\n", len, sqlite3_column_text(pStmt,0),
9737 sqlite3_column_text(pStmt,1));
9738 }
9739 sqlite3_finalize(pStmt);
9740 }
9741 }else
9742
9743 /* .parameter init
9744 ** Make sure the TEMP table used to hold bind parameters exists.
9745 ** Create it if necessary.
9746 */
9747 if( nArg==2 && strcmp(azArg[1],"init")==0 ){
9748 bind_table_init(p);
9749 }else
9750
9751 /* .parameter set NAME VALUE
9752 ** Set or reset a bind parameter. NAME should be the full parameter
9753 ** name exactly as it appears in the query. (ex: $abc, @def). The
9754 ** VALUE can be in either SQL literal notation, or if not it will be
9755 ** understood to be a text string.
9756 */
9757 if( nArg==4 && strcmp(azArg[1],"set")==0 ){
9758 int rx;
9759 char *zSql;
9760 sqlite3_stmt *pStmt;
9761 const char *zKey = azArg[2];
9762 const char *zValue = azArg[3];
9763 bind_table_init(p);
9764 zSql = sqlite3_mprintf(
drh65c29fd2019-03-25 21:56:26 +00009765 "REPLACE INTO temp.sqlite_parameters(key,value)"
drh9cb02642019-02-28 20:10:52 +00009766 "VALUES(%Q,%s);", zKey, zValue);
drhe3e25652021-12-16 13:29:28 +00009767 shell_check_oom(zSql);
drh9cb02642019-02-28 20:10:52 +00009768 pStmt = 0;
9769 rx = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
9770 sqlite3_free(zSql);
9771 if( rx!=SQLITE_OK ){
9772 sqlite3_finalize(pStmt);
9773 pStmt = 0;
9774 zSql = sqlite3_mprintf(
drh65c29fd2019-03-25 21:56:26 +00009775 "REPLACE INTO temp.sqlite_parameters(key,value)"
drh9cb02642019-02-28 20:10:52 +00009776 "VALUES(%Q,%Q);", zKey, zValue);
drhe3e25652021-12-16 13:29:28 +00009777 shell_check_oom(zSql);
drh9cb02642019-02-28 20:10:52 +00009778 rx = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
9779 sqlite3_free(zSql);
9780 if( rx!=SQLITE_OK ){
9781 utf8_printf(p->out, "Error: %s\n", sqlite3_errmsg(p->db));
9782 sqlite3_finalize(pStmt);
9783 pStmt = 0;
9784 rc = 1;
9785 }
9786 }
9787 sqlite3_step(pStmt);
9788 sqlite3_finalize(pStmt);
9789 }else
9790
9791 /* .parameter unset NAME
9792 ** Remove the NAME binding from the parameter binding table, if it
9793 ** exists.
9794 */
9795 if( nArg==3 && strcmp(azArg[1],"unset")==0 ){
9796 char *zSql = sqlite3_mprintf(
drh65c29fd2019-03-25 21:56:26 +00009797 "DELETE FROM temp.sqlite_parameters WHERE key=%Q", azArg[2]);
drhe3e25652021-12-16 13:29:28 +00009798 shell_check_oom(zSql);
drh9cb02642019-02-28 20:10:52 +00009799 sqlite3_exec(p->db, zSql, 0, 0, 0);
9800 sqlite3_free(zSql);
9801 }else
9802 /* If no command name matches, show a syntax error */
9803 parameter_syntax_error:
9804 showHelp(p->out, "parameter");
9805 }else
9806
drh2ce15c32017-07-11 13:34:40 +00009807 if( c=='p' && n>=3 && strncmp(azArg[0], "print", n)==0 ){
9808 int i;
9809 for(i=1; i<nArg; i++){
9810 if( i>1 ) raw_printf(p->out, " ");
9811 utf8_printf(p->out, "%s", azArg[i]);
9812 }
9813 raw_printf(p->out, "\n");
9814 }else
9815
drh569b1d92019-02-05 20:51:41 +00009816#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
drh3f83f592019-02-04 14:53:18 +00009817 if( c=='p' && n>=3 && strncmp(azArg[0], "progress", n)==0 ){
9818 int i;
drhfc4eeef2019-02-05 19:48:46 +00009819 int nn = 0;
drh3f83f592019-02-04 14:53:18 +00009820 p->flgProgress = 0;
9821 p->mxProgress = 0;
9822 p->nProgress = 0;
9823 for(i=1; i<nArg; i++){
9824 const char *z = azArg[i];
9825 if( z[0]=='-' ){
9826 z++;
9827 if( z[0]=='-' ) z++;
9828 if( strcmp(z,"quiet")==0 || strcmp(z,"q")==0 ){
drhfc4eeef2019-02-05 19:48:46 +00009829 p->flgProgress |= SHELL_PROGRESS_QUIET;
drh3f83f592019-02-04 14:53:18 +00009830 continue;
9831 }
9832 if( strcmp(z,"reset")==0 ){
drhfc4eeef2019-02-05 19:48:46 +00009833 p->flgProgress |= SHELL_PROGRESS_RESET;
drh3f83f592019-02-04 14:53:18 +00009834 continue;
9835 }
9836 if( strcmp(z,"once")==0 ){
drhfc4eeef2019-02-05 19:48:46 +00009837 p->flgProgress |= SHELL_PROGRESS_ONCE;
drh3f83f592019-02-04 14:53:18 +00009838 continue;
9839 }
9840 if( strcmp(z,"limit")==0 ){
9841 if( i+1>=nArg ){
9842 utf8_printf(stderr, "Error: missing argument on --limit\n");
9843 rc = 1;
9844 goto meta_command_exit;
9845 }else{
9846 p->mxProgress = (int)integerValue(azArg[++i]);
9847 }
9848 continue;
9849 }
9850 utf8_printf(stderr, "Error: unknown option: \"%s\"\n", azArg[i]);
9851 rc = 1;
9852 goto meta_command_exit;
9853 }else{
drhfc4eeef2019-02-05 19:48:46 +00009854 nn = (int)integerValue(z);
drh3f83f592019-02-04 14:53:18 +00009855 }
9856 }
9857 open_db(p, 0);
drhfc4eeef2019-02-05 19:48:46 +00009858 sqlite3_progress_handler(p->db, nn, progress_handler, p);
drh3f83f592019-02-04 14:53:18 +00009859 }else
drh569b1d92019-02-05 20:51:41 +00009860#endif /* SQLITE_OMIT_PROGRESS_CALLBACK */
drh3f83f592019-02-04 14:53:18 +00009861
drh2ce15c32017-07-11 13:34:40 +00009862 if( c=='p' && strncmp(azArg[0], "prompt", n)==0 ){
9863 if( nArg >= 2) {
9864 strncpy(mainPrompt,azArg[1],(int)ArraySize(mainPrompt)-1);
9865 }
9866 if( nArg >= 3) {
9867 strncpy(continuePrompt,azArg[2],(int)ArraySize(continuePrompt)-1);
9868 }
9869 }else
9870
9871 if( c=='q' && strncmp(azArg[0], "quit", n)==0 ){
9872 rc = 2;
9873 }else
9874
9875 if( c=='r' && n>=3 && strncmp(azArg[0], "read", n)==0 ){
drh60379d42018-12-13 18:30:01 +00009876 FILE *inSaved = p->in;
drh2c8ee022018-12-13 18:59:30 +00009877 int savedLineno = p->lineno;
drhb97e2ad2021-08-26 18:31:39 +00009878 failIfSafeMode(p, "cannot run .read in safe mode");
drh2ce15c32017-07-11 13:34:40 +00009879 if( nArg!=2 ){
9880 raw_printf(stderr, "Usage: .read FILE\n");
9881 rc = 1;
9882 goto meta_command_exit;
9883 }
drh30497f42020-08-26 10:50:48 +00009884 if( azArg[1][0]=='|' ){
drh9d59e3b2021-03-12 01:49:08 +00009885#ifdef SQLITE_OMIT_POPEN
9886 raw_printf(stderr, "Error: pipes are not supported in this OS\n");
9887 rc = 1;
9888 p->out = stdout;
9889#else
drh30497f42020-08-26 10:50:48 +00009890 p->in = popen(azArg[1]+1, "r");
9891 if( p->in==0 ){
9892 utf8_printf(stderr, "Error: cannot open \"%s\"\n", azArg[1]);
9893 rc = 1;
9894 }else{
9895 rc = process_input(p);
9896 pclose(p->in);
9897 }
drh9d59e3b2021-03-12 01:49:08 +00009898#endif
larrybrd96bcc72021-09-17 21:12:47 +00009899 }else if( (p->in = openChrSource(azArg[1]))==0 ){
drh2ce15c32017-07-11 13:34:40 +00009900 utf8_printf(stderr,"Error: cannot open \"%s\"\n", azArg[1]);
9901 rc = 1;
9902 }else{
drh60379d42018-12-13 18:30:01 +00009903 rc = process_input(p);
9904 fclose(p->in);
drh2ce15c32017-07-11 13:34:40 +00009905 }
drh60379d42018-12-13 18:30:01 +00009906 p->in = inSaved;
drh2c8ee022018-12-13 18:59:30 +00009907 p->lineno = savedLineno;
drh2ce15c32017-07-11 13:34:40 +00009908 }else
9909
9910 if( c=='r' && n>=3 && strncmp(azArg[0], "restore", n)==0 ){
9911 const char *zSrcFile;
9912 const char *zDb;
9913 sqlite3 *pSrc;
9914 sqlite3_backup *pBackup;
9915 int nTimeout = 0;
9916
drhb97e2ad2021-08-26 18:31:39 +00009917 failIfSafeMode(p, "cannot run .restore in safe mode");
drh2ce15c32017-07-11 13:34:40 +00009918 if( nArg==2 ){
9919 zSrcFile = azArg[1];
9920 zDb = "main";
9921 }else if( nArg==3 ){
9922 zSrcFile = azArg[2];
9923 zDb = azArg[1];
9924 }else{
9925 raw_printf(stderr, "Usage: .restore ?DB? FILE\n");
9926 rc = 1;
9927 goto meta_command_exit;
9928 }
9929 rc = sqlite3_open(zSrcFile, &pSrc);
9930 if( rc!=SQLITE_OK ){
9931 utf8_printf(stderr, "Error: cannot open \"%s\"\n", zSrcFile);
drh9e804032018-05-18 17:11:50 +00009932 close_db(pSrc);
drh2ce15c32017-07-11 13:34:40 +00009933 return 1;
9934 }
9935 open_db(p, 0);
9936 pBackup = sqlite3_backup_init(p->db, zDb, pSrc, "main");
9937 if( pBackup==0 ){
9938 utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
drh9e804032018-05-18 17:11:50 +00009939 close_db(pSrc);
drh2ce15c32017-07-11 13:34:40 +00009940 return 1;
9941 }
9942 while( (rc = sqlite3_backup_step(pBackup,100))==SQLITE_OK
9943 || rc==SQLITE_BUSY ){
9944 if( rc==SQLITE_BUSY ){
9945 if( nTimeout++ >= 3 ) break;
9946 sqlite3_sleep(100);
9947 }
9948 }
9949 sqlite3_backup_finish(pBackup);
9950 if( rc==SQLITE_DONE ){
9951 rc = 0;
9952 }else if( rc==SQLITE_BUSY || rc==SQLITE_LOCKED ){
9953 raw_printf(stderr, "Error: source database is busy\n");
9954 rc = 1;
9955 }else{
9956 utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
9957 rc = 1;
9958 }
drh9e804032018-05-18 17:11:50 +00009959 close_db(pSrc);
drh2ce15c32017-07-11 13:34:40 +00009960 }else
9961
drh2ce15c32017-07-11 13:34:40 +00009962 if( c=='s' && strncmp(azArg[0], "scanstats", n)==0 ){
9963 if( nArg==2 ){
mistachkinb71aa092018-01-23 00:05:18 +00009964 p->scanstatsOn = (u8)booleanValue(azArg[1]);
drh2ce15c32017-07-11 13:34:40 +00009965#ifndef SQLITE_ENABLE_STMT_SCANSTATUS
9966 raw_printf(stderr, "Warning: .scanstats not available in this build.\n");
9967#endif
9968 }else{
9969 raw_printf(stderr, "Usage: .scanstats on|off\n");
9970 rc = 1;
9971 }
9972 }else
9973
9974 if( c=='s' && strncmp(azArg[0], "schema", n)==0 ){
9975 ShellText sSelect;
9976 ShellState data;
9977 char *zErrMsg = 0;
drh667a2a22018-01-02 00:04:37 +00009978 const char *zDiv = "(";
drhceba7922018-01-01 21:28:25 +00009979 const char *zName = 0;
drh2ce15c32017-07-11 13:34:40 +00009980 int iSchema = 0;
drhceba7922018-01-01 21:28:25 +00009981 int bDebug = 0;
drhbbb29ec2020-10-12 14:56:47 +00009982 int bNoSystemTabs = 0;
drhceba7922018-01-01 21:28:25 +00009983 int ii;
drh2ce15c32017-07-11 13:34:40 +00009984
9985 open_db(p, 0);
9986 memcpy(&data, p, sizeof(data));
9987 data.showHeader = 0;
9988 data.cMode = data.mode = MODE_Semi;
9989 initText(&sSelect);
drhceba7922018-01-01 21:28:25 +00009990 for(ii=1; ii<nArg; ii++){
9991 if( optionMatch(azArg[ii],"indent") ){
9992 data.cMode = data.mode = MODE_Pretty;
9993 }else if( optionMatch(azArg[ii],"debug") ){
9994 bDebug = 1;
drhbbb29ec2020-10-12 14:56:47 +00009995 }else if( optionMatch(azArg[ii],"nosys") ){
9996 bNoSystemTabs = 1;
9997 }else if( azArg[ii][0]=='-' ){
9998 utf8_printf(stderr, "Unknown option: \"%s\"\n", azArg[ii]);
9999 rc = 1;
10000 goto meta_command_exit;
drhceba7922018-01-01 21:28:25 +000010001 }else if( zName==0 ){
10002 zName = azArg[ii];
drh2ce15c32017-07-11 13:34:40 +000010003 }else{
drhbbb29ec2020-10-12 14:56:47 +000010004 raw_printf(stderr, "Usage: .schema ?--indent? ?--nosys? ?LIKE-PATTERN?\n");
drhceba7922018-01-01 21:28:25 +000010005 rc = 1;
10006 goto meta_command_exit;
drh2ce15c32017-07-11 13:34:40 +000010007 }
drh2ce15c32017-07-11 13:34:40 +000010008 }
drhceba7922018-01-01 21:28:25 +000010009 if( zName!=0 ){
drh067b92b2020-06-19 15:24:12 +000010010 int isSchema = sqlite3_strlike(zName, "sqlite_master", '\\')==0
drh346a70c2020-06-15 20:27:35 +000010011 || sqlite3_strlike(zName, "sqlite_schema", '\\')==0
10012 || sqlite3_strlike(zName,"sqlite_temp_master", '\\')==0
10013 || sqlite3_strlike(zName,"sqlite_temp_schema", '\\')==0;
drh067b92b2020-06-19 15:24:12 +000010014 if( isSchema ){
drh2ce15c32017-07-11 13:34:40 +000010015 char *new_argv[2], *new_colv[2];
drhc22b7162018-01-01 20:11:23 +000010016 new_argv[0] = sqlite3_mprintf(
10017 "CREATE TABLE %s (\n"
drh2ce15c32017-07-11 13:34:40 +000010018 " type text,\n"
10019 " name text,\n"
10020 " tbl_name text,\n"
10021 " rootpage integer,\n"
10022 " sql text\n"
drh346a70c2020-06-15 20:27:35 +000010023 ")", zName);
drhe3e25652021-12-16 13:29:28 +000010024 shell_check_oom(new_argv[0]);
drh2ce15c32017-07-11 13:34:40 +000010025 new_argv[1] = 0;
10026 new_colv[0] = "sql";
10027 new_colv[1] = 0;
10028 callback(&data, 1, new_argv, new_colv);
drhc22b7162018-01-01 20:11:23 +000010029 sqlite3_free(new_argv[0]);
drh2ce15c32017-07-11 13:34:40 +000010030 }
drh2ce15c32017-07-11 13:34:40 +000010031 }
10032 if( zDiv ){
10033 sqlite3_stmt *pStmt = 0;
10034 rc = sqlite3_prepare_v2(p->db, "SELECT name FROM pragma_database_list",
10035 -1, &pStmt, 0);
10036 if( rc ){
10037 utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
10038 sqlite3_finalize(pStmt);
10039 rc = 1;
10040 goto meta_command_exit;
10041 }
10042 appendText(&sSelect, "SELECT sql FROM", 0);
10043 iSchema = 0;
10044 while( sqlite3_step(pStmt)==SQLITE_ROW ){
10045 const char *zDb = (const char*)sqlite3_column_text(pStmt, 0);
10046 char zScNum[30];
10047 sqlite3_snprintf(sizeof(zScNum), zScNum, "%d", ++iSchema);
10048 appendText(&sSelect, zDiv, 0);
10049 zDiv = " UNION ALL ";
drhceba7922018-01-01 21:28:25 +000010050 appendText(&sSelect, "SELECT shell_add_schema(sql,", 0);
10051 if( sqlite3_stricmp(zDb, "main")!=0 ){
drhea38f4f2019-07-13 17:21:47 +000010052 appendText(&sSelect, zDb, '\'');
drh2ce15c32017-07-11 13:34:40 +000010053 }else{
drhceba7922018-01-01 21:28:25 +000010054 appendText(&sSelect, "NULL", 0);
drh2ce15c32017-07-11 13:34:40 +000010055 }
drhceba7922018-01-01 21:28:25 +000010056 appendText(&sSelect, ",name) AS sql, type, tbl_name, name, rowid,", 0);
10057 appendText(&sSelect, zScNum, 0);
10058 appendText(&sSelect, " AS snum, ", 0);
10059 appendText(&sSelect, zDb, '\'');
10060 appendText(&sSelect, " AS sname FROM ", 0);
drhea38f4f2019-07-13 17:21:47 +000010061 appendText(&sSelect, zDb, quoteChar(zDb));
drh067b92b2020-06-19 15:24:12 +000010062 appendText(&sSelect, ".sqlite_schema", 0);
drh2ce15c32017-07-11 13:34:40 +000010063 }
10064 sqlite3_finalize(pStmt);
drhcc3f3d12019-08-17 15:27:58 +000010065#ifndef SQLITE_OMIT_INTROSPECTION_PRAGMAS
drh667a2a22018-01-02 00:04:37 +000010066 if( zName ){
10067 appendText(&sSelect,
10068 " UNION ALL SELECT shell_module_schema(name),"
drhe2754c12019-08-26 12:50:01 +000010069 " 'table', name, name, name, 9e+99, 'main' FROM pragma_module_list",
10070 0);
drh667a2a22018-01-02 00:04:37 +000010071 }
drhcde7b772018-01-02 12:50:40 +000010072#endif
drh2ce15c32017-07-11 13:34:40 +000010073 appendText(&sSelect, ") WHERE ", 0);
drhceba7922018-01-01 21:28:25 +000010074 if( zName ){
10075 char *zQarg = sqlite3_mprintf("%Q", zName);
mistachkinc158c072021-12-31 19:08:20 +000010076 int bGlob;
drhe3e25652021-12-16 13:29:28 +000010077 shell_check_oom(zQarg);
mistachkinc158c072021-12-31 19:08:20 +000010078 bGlob = strchr(zName, '*') != 0 || strchr(zName, '?') != 0 ||
10079 strchr(zName, '[') != 0;
drhceba7922018-01-01 21:28:25 +000010080 if( strchr(zName, '.') ){
drh2ce15c32017-07-11 13:34:40 +000010081 appendText(&sSelect, "lower(printf('%s.%s',sname,tbl_name))", 0);
10082 }else{
10083 appendText(&sSelect, "lower(tbl_name)", 0);
10084 }
mistachkin9d107262018-03-23 14:24:34 +000010085 appendText(&sSelect, bGlob ? " GLOB " : " LIKE ", 0);
drh2ce15c32017-07-11 13:34:40 +000010086 appendText(&sSelect, zQarg, 0);
mistachkin9d107262018-03-23 14:24:34 +000010087 if( !bGlob ){
10088 appendText(&sSelect, " ESCAPE '\\' ", 0);
10089 }
drh2ce15c32017-07-11 13:34:40 +000010090 appendText(&sSelect, " AND ", 0);
10091 sqlite3_free(zQarg);
10092 }
drhbbb29ec2020-10-12 14:56:47 +000010093 if( bNoSystemTabs ){
10094 appendText(&sSelect, "name NOT LIKE 'sqlite_%%' AND ", 0);
10095 }
10096 appendText(&sSelect, "sql IS NOT NULL"
drh2ce15c32017-07-11 13:34:40 +000010097 " ORDER BY snum, rowid", 0);
drhceba7922018-01-01 21:28:25 +000010098 if( bDebug ){
10099 utf8_printf(p->out, "SQL: %s;\n", sSelect.z);
10100 }else{
10101 rc = sqlite3_exec(p->db, sSelect.z, callback, &data, &zErrMsg);
10102 }
drh2ce15c32017-07-11 13:34:40 +000010103 freeText(&sSelect);
10104 }
10105 if( zErrMsg ){
10106 utf8_printf(stderr,"Error: %s\n", zErrMsg);
10107 sqlite3_free(zErrMsg);
10108 rc = 1;
10109 }else if( rc != SQLITE_OK ){
10110 raw_printf(stderr,"Error: querying schema information\n");
10111 rc = 1;
10112 }else{
10113 rc = 0;
10114 }
10115 }else
10116
drh5e431be2022-04-06 11:08:38 +000010117 if( (c=='s' && n==11 && strncmp(azArg[0], "selecttrace", n)==0)
10118 || (c=='t' && n==9 && strncmp(azArg[0], "treetrace", n)==0)
10119 ){
drhfda8e492020-12-04 16:04:45 +000010120 unsigned int x = nArg>=2 ? (unsigned int)integerValue(azArg[1]) : 0xffffffff;
drhc0622a42020-12-04 01:17:57 +000010121 sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 1, &x);
drh2ce15c32017-07-11 13:34:40 +000010122 }else
drh2ce15c32017-07-11 13:34:40 +000010123
10124#if defined(SQLITE_ENABLE_SESSION)
10125 if( c=='s' && strncmp(azArg[0],"session",n)==0 && n>=3 ){
drh37407122021-07-23 18:43:58 +000010126 struct AuxDb *pAuxDb = p->pAuxDb;
10127 OpenSession *pSession = &pAuxDb->aSession[0];
drh2ce15c32017-07-11 13:34:40 +000010128 char **azCmd = &azArg[1];
10129 int iSes = 0;
10130 int nCmd = nArg - 1;
10131 int i;
10132 if( nArg<=1 ) goto session_syntax_error;
10133 open_db(p, 0);
10134 if( nArg>=3 ){
drh37407122021-07-23 18:43:58 +000010135 for(iSes=0; iSes<pAuxDb->nSession; iSes++){
10136 if( strcmp(pAuxDb->aSession[iSes].zName, azArg[1])==0 ) break;
drh2ce15c32017-07-11 13:34:40 +000010137 }
drh37407122021-07-23 18:43:58 +000010138 if( iSes<pAuxDb->nSession ){
10139 pSession = &pAuxDb->aSession[iSes];
drh2ce15c32017-07-11 13:34:40 +000010140 azCmd++;
10141 nCmd--;
10142 }else{
drh37407122021-07-23 18:43:58 +000010143 pSession = &pAuxDb->aSession[0];
drh2ce15c32017-07-11 13:34:40 +000010144 iSes = 0;
10145 }
10146 }
10147
10148 /* .session attach TABLE
10149 ** Invoke the sqlite3session_attach() interface to attach a particular
10150 ** table so that it is never filtered.
10151 */
10152 if( strcmp(azCmd[0],"attach")==0 ){
10153 if( nCmd!=2 ) goto session_syntax_error;
10154 if( pSession->p==0 ){
10155 session_not_open:
10156 raw_printf(stderr, "ERROR: No sessions are open\n");
10157 }else{
10158 rc = sqlite3session_attach(pSession->p, azCmd[1]);
10159 if( rc ){
10160 raw_printf(stderr, "ERROR: sqlite3session_attach() returns %d\n", rc);
10161 rc = 0;
10162 }
10163 }
10164 }else
10165
10166 /* .session changeset FILE
10167 ** .session patchset FILE
10168 ** Write a changeset or patchset into a file. The file is overwritten.
10169 */
10170 if( strcmp(azCmd[0],"changeset")==0 || strcmp(azCmd[0],"patchset")==0 ){
10171 FILE *out = 0;
drhb97e2ad2021-08-26 18:31:39 +000010172 failIfSafeMode(p, "cannot run \".session %s\" in safe mode", azCmd[0]);
drh2ce15c32017-07-11 13:34:40 +000010173 if( nCmd!=2 ) goto session_syntax_error;
10174 if( pSession->p==0 ) goto session_not_open;
10175 out = fopen(azCmd[1], "wb");
10176 if( out==0 ){
drhe2754c12019-08-26 12:50:01 +000010177 utf8_printf(stderr, "ERROR: cannot open \"%s\" for writing\n",
10178 azCmd[1]);
drh2ce15c32017-07-11 13:34:40 +000010179 }else{
10180 int szChng;
10181 void *pChng;
10182 if( azCmd[0][0]=='c' ){
10183 rc = sqlite3session_changeset(pSession->p, &szChng, &pChng);
10184 }else{
10185 rc = sqlite3session_patchset(pSession->p, &szChng, &pChng);
10186 }
10187 if( rc ){
10188 printf("Error: error code %d\n", rc);
10189 rc = 0;
10190 }
10191 if( pChng
10192 && fwrite(pChng, szChng, 1, out)!=1 ){
10193 raw_printf(stderr, "ERROR: Failed to write entire %d-byte output\n",
10194 szChng);
10195 }
10196 sqlite3_free(pChng);
10197 fclose(out);
10198 }
10199 }else
10200
10201 /* .session close
10202 ** Close the identified session
10203 */
10204 if( strcmp(azCmd[0], "close")==0 ){
10205 if( nCmd!=1 ) goto session_syntax_error;
drh37407122021-07-23 18:43:58 +000010206 if( pAuxDb->nSession ){
drh2ce15c32017-07-11 13:34:40 +000010207 session_close(pSession);
drh37407122021-07-23 18:43:58 +000010208 pAuxDb->aSession[iSes] = pAuxDb->aSession[--pAuxDb->nSession];
drh2ce15c32017-07-11 13:34:40 +000010209 }
10210 }else
10211
10212 /* .session enable ?BOOLEAN?
10213 ** Query or set the enable flag
10214 */
10215 if( strcmp(azCmd[0], "enable")==0 ){
10216 int ii;
10217 if( nCmd>2 ) goto session_syntax_error;
10218 ii = nCmd==1 ? -1 : booleanValue(azCmd[1]);
drh37407122021-07-23 18:43:58 +000010219 if( pAuxDb->nSession ){
drh2ce15c32017-07-11 13:34:40 +000010220 ii = sqlite3session_enable(pSession->p, ii);
10221 utf8_printf(p->out, "session %s enable flag = %d\n",
10222 pSession->zName, ii);
10223 }
10224 }else
10225
10226 /* .session filter GLOB ....
10227 ** Set a list of GLOB patterns of table names to be excluded.
10228 */
10229 if( strcmp(azCmd[0], "filter")==0 ){
10230 int ii, nByte;
10231 if( nCmd<2 ) goto session_syntax_error;
drh37407122021-07-23 18:43:58 +000010232 if( pAuxDb->nSession ){
drh2ce15c32017-07-11 13:34:40 +000010233 for(ii=0; ii<pSession->nFilter; ii++){
10234 sqlite3_free(pSession->azFilter[ii]);
10235 }
10236 sqlite3_free(pSession->azFilter);
10237 nByte = sizeof(pSession->azFilter[0])*(nCmd-1);
10238 pSession->azFilter = sqlite3_malloc( nByte );
10239 if( pSession->azFilter==0 ){
10240 raw_printf(stderr, "Error: out or memory\n");
10241 exit(1);
10242 }
10243 for(ii=1; ii<nCmd; ii++){
drhe3e25652021-12-16 13:29:28 +000010244 char *x = pSession->azFilter[ii-1] = sqlite3_mprintf("%s", azCmd[ii]);
10245 shell_check_oom(x);
drh2ce15c32017-07-11 13:34:40 +000010246 }
10247 pSession->nFilter = ii-1;
10248 }
10249 }else
10250
10251 /* .session indirect ?BOOLEAN?
10252 ** Query or set the indirect flag
10253 */
10254 if( strcmp(azCmd[0], "indirect")==0 ){
10255 int ii;
10256 if( nCmd>2 ) goto session_syntax_error;
10257 ii = nCmd==1 ? -1 : booleanValue(azCmd[1]);
drh37407122021-07-23 18:43:58 +000010258 if( pAuxDb->nSession ){
drh2ce15c32017-07-11 13:34:40 +000010259 ii = sqlite3session_indirect(pSession->p, ii);
10260 utf8_printf(p->out, "session %s indirect flag = %d\n",
10261 pSession->zName, ii);
10262 }
10263 }else
10264
10265 /* .session isempty
10266 ** Determine if the session is empty
10267 */
10268 if( strcmp(azCmd[0], "isempty")==0 ){
10269 int ii;
10270 if( nCmd!=1 ) goto session_syntax_error;
drh37407122021-07-23 18:43:58 +000010271 if( pAuxDb->nSession ){
drh2ce15c32017-07-11 13:34:40 +000010272 ii = sqlite3session_isempty(pSession->p);
10273 utf8_printf(p->out, "session %s isempty flag = %d\n",
10274 pSession->zName, ii);
10275 }
10276 }else
10277
10278 /* .session list
10279 ** List all currently open sessions
10280 */
10281 if( strcmp(azCmd[0],"list")==0 ){
drh37407122021-07-23 18:43:58 +000010282 for(i=0; i<pAuxDb->nSession; i++){
10283 utf8_printf(p->out, "%d %s\n", i, pAuxDb->aSession[i].zName);
drh2ce15c32017-07-11 13:34:40 +000010284 }
10285 }else
10286
10287 /* .session open DB NAME
10288 ** Open a new session called NAME on the attached database DB.
10289 ** DB is normally "main".
10290 */
10291 if( strcmp(azCmd[0],"open")==0 ){
10292 char *zName;
10293 if( nCmd!=3 ) goto session_syntax_error;
10294 zName = azCmd[2];
10295 if( zName[0]==0 ) goto session_syntax_error;
drh37407122021-07-23 18:43:58 +000010296 for(i=0; i<pAuxDb->nSession; i++){
10297 if( strcmp(pAuxDb->aSession[i].zName,zName)==0 ){
drh2ce15c32017-07-11 13:34:40 +000010298 utf8_printf(stderr, "Session \"%s\" already exists\n", zName);
10299 goto meta_command_exit;
10300 }
10301 }
drh37407122021-07-23 18:43:58 +000010302 if( pAuxDb->nSession>=ArraySize(pAuxDb->aSession) ){
10303 raw_printf(stderr, "Maximum of %d sessions\n", ArraySize(pAuxDb->aSession));
drh2ce15c32017-07-11 13:34:40 +000010304 goto meta_command_exit;
10305 }
drh37407122021-07-23 18:43:58 +000010306 pSession = &pAuxDb->aSession[pAuxDb->nSession];
drh2ce15c32017-07-11 13:34:40 +000010307 rc = sqlite3session_create(p->db, azCmd[1], &pSession->p);
10308 if( rc ){
10309 raw_printf(stderr, "Cannot open session: error code=%d\n", rc);
10310 rc = 0;
10311 goto meta_command_exit;
10312 }
10313 pSession->nFilter = 0;
10314 sqlite3session_table_filter(pSession->p, session_filter, pSession);
drh37407122021-07-23 18:43:58 +000010315 pAuxDb->nSession++;
drh2ce15c32017-07-11 13:34:40 +000010316 pSession->zName = sqlite3_mprintf("%s", zName);
drhe3e25652021-12-16 13:29:28 +000010317 shell_check_oom(pSession->zName);
drh2ce15c32017-07-11 13:34:40 +000010318 }else
10319 /* If no command name matches, show a syntax error */
10320 session_syntax_error:
drheb7f2a02018-09-26 18:02:32 +000010321 showHelp(p->out, "session");
drh2ce15c32017-07-11 13:34:40 +000010322 }else
10323#endif
10324
10325#ifdef SQLITE_DEBUG
10326 /* Undocumented commands for internal testing. Subject to change
10327 ** without notice. */
10328 if( c=='s' && n>=10 && strncmp(azArg[0], "selftest-", 9)==0 ){
10329 if( strncmp(azArg[0]+9, "boolean", n-9)==0 ){
10330 int i, v;
10331 for(i=1; i<nArg; i++){
10332 v = booleanValue(azArg[i]);
10333 utf8_printf(p->out, "%s: %d 0x%x\n", azArg[i], v, v);
10334 }
10335 }
10336 if( strncmp(azArg[0]+9, "integer", n-9)==0 ){
10337 int i; sqlite3_int64 v;
10338 for(i=1; i<nArg; i++){
10339 char zBuf[200];
10340 v = integerValue(azArg[i]);
10341 sqlite3_snprintf(sizeof(zBuf),zBuf,"%s: %lld 0x%llx\n", azArg[i],v,v);
10342 utf8_printf(p->out, "%s", zBuf);
10343 }
10344 }
10345 }else
10346#endif
10347
10348 if( c=='s' && n>=4 && strncmp(azArg[0],"selftest",n)==0 ){
10349 int bIsInit = 0; /* True to initialize the SELFTEST table */
10350 int bVerbose = 0; /* Verbose output */
10351 int bSelftestExists; /* True if SELFTEST already exists */
10352 int i, k; /* Loop counters */
10353 int nTest = 0; /* Number of tests runs */
10354 int nErr = 0; /* Number of errors seen */
10355 ShellText str; /* Answer for a query */
10356 sqlite3_stmt *pStmt = 0; /* Query against the SELFTEST table */
10357
10358 open_db(p,0);
10359 for(i=1; i<nArg; i++){
10360 const char *z = azArg[i];
10361 if( z[0]=='-' && z[1]=='-' ) z++;
10362 if( strcmp(z,"-init")==0 ){
10363 bIsInit = 1;
10364 }else
10365 if( strcmp(z,"-v")==0 ){
10366 bVerbose++;
10367 }else
10368 {
10369 utf8_printf(stderr, "Unknown option \"%s\" on \"%s\"\n",
10370 azArg[i], azArg[0]);
10371 raw_printf(stderr, "Should be one of: --init -v\n");
10372 rc = 1;
10373 goto meta_command_exit;
10374 }
10375 }
10376 if( sqlite3_table_column_metadata(p->db,"main","selftest",0,0,0,0,0,0)
10377 != SQLITE_OK ){
10378 bSelftestExists = 0;
10379 }else{
10380 bSelftestExists = 1;
10381 }
10382 if( bIsInit ){
10383 createSelftestTable(p);
10384 bSelftestExists = 1;
10385 }
10386 initText(&str);
10387 appendText(&str, "x", 0);
10388 for(k=bSelftestExists; k>=0; k--){
10389 if( k==1 ){
10390 rc = sqlite3_prepare_v2(p->db,
10391 "SELECT tno,op,cmd,ans FROM selftest ORDER BY tno",
10392 -1, &pStmt, 0);
10393 }else{
10394 rc = sqlite3_prepare_v2(p->db,
10395 "VALUES(0,'memo','Missing SELFTEST table - default checks only',''),"
10396 " (1,'run','PRAGMA integrity_check','ok')",
10397 -1, &pStmt, 0);
10398 }
10399 if( rc ){
10400 raw_printf(stderr, "Error querying the selftest table\n");
10401 rc = 1;
10402 sqlite3_finalize(pStmt);
10403 goto meta_command_exit;
10404 }
10405 for(i=1; sqlite3_step(pStmt)==SQLITE_ROW; i++){
10406 int tno = sqlite3_column_int(pStmt, 0);
10407 const char *zOp = (const char*)sqlite3_column_text(pStmt, 1);
10408 const char *zSql = (const char*)sqlite3_column_text(pStmt, 2);
10409 const char *zAns = (const char*)sqlite3_column_text(pStmt, 3);
10410
drh621a5e02021-12-16 17:35:27 +000010411 if( zOp==0 ) continue;
10412 if( zSql==0 ) continue;
10413 if( zAns==0 ) continue;
drh2ce15c32017-07-11 13:34:40 +000010414 k = 0;
10415 if( bVerbose>0 ){
drh2ce15c32017-07-11 13:34:40 +000010416 printf("%d: %s %s\n", tno, zOp, zSql);
drh2ce15c32017-07-11 13:34:40 +000010417 }
10418 if( strcmp(zOp,"memo")==0 ){
10419 utf8_printf(p->out, "%s\n", zSql);
10420 }else
10421 if( strcmp(zOp,"run")==0 ){
10422 char *zErrMsg = 0;
10423 str.n = 0;
10424 str.z[0] = 0;
10425 rc = sqlite3_exec(p->db, zSql, captureOutputCallback, &str, &zErrMsg);
10426 nTest++;
10427 if( bVerbose ){
10428 utf8_printf(p->out, "Result: %s\n", str.z);
10429 }
10430 if( rc || zErrMsg ){
10431 nErr++;
10432 rc = 1;
10433 utf8_printf(p->out, "%d: error-code-%d: %s\n", tno, rc, zErrMsg);
10434 sqlite3_free(zErrMsg);
10435 }else if( strcmp(zAns,str.z)!=0 ){
10436 nErr++;
10437 rc = 1;
10438 utf8_printf(p->out, "%d: Expected: [%s]\n", tno, zAns);
10439 utf8_printf(p->out, "%d: Got: [%s]\n", tno, str.z);
10440 }
10441 }else
10442 {
10443 utf8_printf(stderr,
10444 "Unknown operation \"%s\" on selftest line %d\n", zOp, tno);
10445 rc = 1;
10446 break;
10447 }
10448 } /* End loop over rows of content from SELFTEST */
10449 sqlite3_finalize(pStmt);
10450 } /* End loop over k */
10451 freeText(&str);
10452 utf8_printf(p->out, "%d errors out of %d tests\n", nErr, nTest);
10453 }else
10454
10455 if( c=='s' && strncmp(azArg[0], "separator", n)==0 ){
10456 if( nArg<2 || nArg>3 ){
10457 raw_printf(stderr, "Usage: .separator COL ?ROW?\n");
10458 rc = 1;
10459 }
10460 if( nArg>=2 ){
10461 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator,
10462 "%.*s", (int)ArraySize(p->colSeparator)-1, azArg[1]);
10463 }
10464 if( nArg>=3 ){
10465 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator,
10466 "%.*s", (int)ArraySize(p->rowSeparator)-1, azArg[2]);
10467 }
10468 }else
10469
10470 if( c=='s' && n>=4 && strncmp(azArg[0],"sha3sum",n)==0 ){
10471 const char *zLike = 0; /* Which table to checksum. 0 means everything */
10472 int i; /* Loop counter */
10473 int bSchema = 0; /* Also hash the schema */
10474 int bSeparate = 0; /* Hash each table separately */
10475 int iSize = 224; /* Hash algorithm to use */
10476 int bDebug = 0; /* Only show the query that would have run */
10477 sqlite3_stmt *pStmt; /* For querying tables names */
10478 char *zSql; /* SQL to be run */
10479 char *zSep; /* Separator */
10480 ShellText sSql; /* Complete SQL for the query to run the hash */
10481 ShellText sQuery; /* Set of queries used to read all content */
10482 open_db(p, 0);
10483 for(i=1; i<nArg; i++){
10484 const char *z = azArg[i];
10485 if( z[0]=='-' ){
10486 z++;
10487 if( z[0]=='-' ) z++;
10488 if( strcmp(z,"schema")==0 ){
10489 bSchema = 1;
10490 }else
10491 if( strcmp(z,"sha3-224")==0 || strcmp(z,"sha3-256")==0
10492 || strcmp(z,"sha3-384")==0 || strcmp(z,"sha3-512")==0
10493 ){
10494 iSize = atoi(&z[5]);
10495 }else
10496 if( strcmp(z,"debug")==0 ){
10497 bDebug = 1;
10498 }else
10499 {
10500 utf8_printf(stderr, "Unknown option \"%s\" on \"%s\"\n",
10501 azArg[i], azArg[0]);
drhe2754c12019-08-26 12:50:01 +000010502 showHelp(p->out, azArg[0]);
drh2ce15c32017-07-11 13:34:40 +000010503 rc = 1;
10504 goto meta_command_exit;
10505 }
10506 }else if( zLike ){
10507 raw_printf(stderr, "Usage: .sha3sum ?OPTIONS? ?LIKE-PATTERN?\n");
10508 rc = 1;
10509 goto meta_command_exit;
10510 }else{
10511 zLike = z;
10512 bSeparate = 1;
drhcedfecf2018-03-23 12:59:10 +000010513 if( sqlite3_strlike("sqlite\\_%", zLike, '\\')==0 ) bSchema = 1;
drh2ce15c32017-07-11 13:34:40 +000010514 }
10515 }
10516 if( bSchema ){
drh067b92b2020-06-19 15:24:12 +000010517 zSql = "SELECT lower(name) FROM sqlite_schema"
drh2ce15c32017-07-11 13:34:40 +000010518 " WHERE type='table' AND coalesce(rootpage,0)>1"
drh067b92b2020-06-19 15:24:12 +000010519 " UNION ALL SELECT 'sqlite_schema'"
drh2ce15c32017-07-11 13:34:40 +000010520 " ORDER BY 1 collate nocase";
10521 }else{
drh067b92b2020-06-19 15:24:12 +000010522 zSql = "SELECT lower(name) FROM sqlite_schema"
drh2ce15c32017-07-11 13:34:40 +000010523 " WHERE type='table' AND coalesce(rootpage,0)>1"
10524 " AND name NOT LIKE 'sqlite_%'"
10525 " ORDER BY 1 collate nocase";
10526 }
10527 sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
10528 initText(&sQuery);
10529 initText(&sSql);
10530 appendText(&sSql, "WITH [sha3sum$query](a,b) AS(",0);
10531 zSep = "VALUES(";
10532 while( SQLITE_ROW==sqlite3_step(pStmt) ){
10533 const char *zTab = (const char*)sqlite3_column_text(pStmt,0);
drh621a5e02021-12-16 17:35:27 +000010534 if( zTab==0 ) continue;
drh2ce15c32017-07-11 13:34:40 +000010535 if( zLike && sqlite3_strlike(zLike, zTab, 0)!=0 ) continue;
10536 if( strncmp(zTab, "sqlite_",7)!=0 ){
10537 appendText(&sQuery,"SELECT * FROM ", 0);
10538 appendText(&sQuery,zTab,'"');
10539 appendText(&sQuery," NOT INDEXED;", 0);
drh067b92b2020-06-19 15:24:12 +000010540 }else if( strcmp(zTab, "sqlite_schema")==0 ){
10541 appendText(&sQuery,"SELECT type,name,tbl_name,sql FROM sqlite_schema"
drh2ce15c32017-07-11 13:34:40 +000010542 " ORDER BY name;", 0);
10543 }else if( strcmp(zTab, "sqlite_sequence")==0 ){
10544 appendText(&sQuery,"SELECT name,seq FROM sqlite_sequence"
10545 " ORDER BY name;", 0);
10546 }else if( strcmp(zTab, "sqlite_stat1")==0 ){
10547 appendText(&sQuery,"SELECT tbl,idx,stat FROM sqlite_stat1"
10548 " ORDER BY tbl,idx;", 0);
drh175b8f02019-08-08 15:24:17 +000010549 }else if( strcmp(zTab, "sqlite_stat4")==0 ){
drh2ce15c32017-07-11 13:34:40 +000010550 appendText(&sQuery, "SELECT * FROM ", 0);
10551 appendText(&sQuery, zTab, 0);
10552 appendText(&sQuery, " ORDER BY tbl, idx, rowid;\n", 0);
10553 }
10554 appendText(&sSql, zSep, 0);
10555 appendText(&sSql, sQuery.z, '\'');
10556 sQuery.n = 0;
10557 appendText(&sSql, ",", 0);
10558 appendText(&sSql, zTab, '\'');
10559 zSep = "),(";
10560 }
10561 sqlite3_finalize(pStmt);
10562 if( bSeparate ){
10563 zSql = sqlite3_mprintf(
10564 "%s))"
10565 " SELECT lower(hex(sha3_query(a,%d))) AS hash, b AS label"
10566 " FROM [sha3sum$query]",
10567 sSql.z, iSize);
10568 }else{
10569 zSql = sqlite3_mprintf(
10570 "%s))"
10571 " SELECT lower(hex(sha3_query(group_concat(a,''),%d))) AS hash"
10572 " FROM [sha3sum$query]",
10573 sSql.z, iSize);
10574 }
drhe3e25652021-12-16 13:29:28 +000010575 shell_check_oom(zSql);
drh2ce15c32017-07-11 13:34:40 +000010576 freeText(&sQuery);
10577 freeText(&sSql);
10578 if( bDebug ){
10579 utf8_printf(p->out, "%s\n", zSql);
10580 }else{
drha10b9992018-03-09 15:24:33 +000010581 shell_exec(p, zSql, 0);
drh2ce15c32017-07-11 13:34:40 +000010582 }
10583 sqlite3_free(zSql);
10584 }else
10585
drh04a28c32018-01-31 01:38:44 +000010586#ifndef SQLITE_NOHAVE_SYSTEM
drh2ce15c32017-07-11 13:34:40 +000010587 if( c=='s'
10588 && (strncmp(azArg[0], "shell", n)==0 || strncmp(azArg[0],"system",n)==0)
10589 ){
10590 char *zCmd;
10591 int i, x;
drhb97e2ad2021-08-26 18:31:39 +000010592 failIfSafeMode(p, "cannot run .%s in safe mode", azArg[0]);
drh2ce15c32017-07-11 13:34:40 +000010593 if( nArg<2 ){
10594 raw_printf(stderr, "Usage: .system COMMAND\n");
10595 rc = 1;
10596 goto meta_command_exit;
10597 }
10598 zCmd = sqlite3_mprintf(strchr(azArg[1],' ')==0?"%s":"\"%s\"", azArg[1]);
drhe3e25652021-12-16 13:29:28 +000010599 for(i=2; i<nArg && zCmd!=0; i++){
drh2ce15c32017-07-11 13:34:40 +000010600 zCmd = sqlite3_mprintf(strchr(azArg[i],' ')==0?"%z %s":"%z \"%s\"",
10601 zCmd, azArg[i]);
10602 }
drhe3e25652021-12-16 13:29:28 +000010603 x = zCmd!=0 ? system(zCmd) : 1;
drh2ce15c32017-07-11 13:34:40 +000010604 sqlite3_free(zCmd);
10605 if( x ) raw_printf(stderr, "System command returns %d\n", x);
10606 }else
drh04a28c32018-01-31 01:38:44 +000010607#endif /* !defined(SQLITE_NOHAVE_SYSTEM) */
drh2ce15c32017-07-11 13:34:40 +000010608
10609 if( c=='s' && strncmp(azArg[0], "show", n)==0 ){
drhada70452017-12-21 21:02:27 +000010610 static const char *azBool[] = { "off", "on", "trigger", "full"};
drha6e6cf22021-01-09 19:10:04 +000010611 const char *zOut;
drh2ce15c32017-07-11 13:34:40 +000010612 int i;
10613 if( nArg!=1 ){
10614 raw_printf(stderr, "Usage: .show\n");
10615 rc = 1;
10616 goto meta_command_exit;
10617 }
10618 utf8_printf(p->out, "%12.12s: %s\n","echo",
larrybrf4874812022-05-11 19:59:31 +000010619 azBool[ShellHasFlag(p, SHFLG_Echo)]);
drh2ce15c32017-07-11 13:34:40 +000010620 utf8_printf(p->out, "%12.12s: %s\n","eqp", azBool[p->autoEQP&3]);
10621 utf8_printf(p->out, "%12.12s: %s\n","explain",
10622 p->mode==MODE_Explain ? "on" : p->autoExplain ? "auto" : "off");
10623 utf8_printf(p->out,"%12.12s: %s\n","headers", azBool[p->showHeader!=0]);
drhe40f2862022-01-31 14:14:29 +000010624 if( p->mode==MODE_Column
10625 || (p->mode>=MODE_Markdown && p->mode<=MODE_Box)
10626 ){
larrybrcc4d55c2022-02-01 02:50:45 +000010627 utf8_printf
10628 (p->out, "%12.12s: %s --wrap %d --wordwrap %s --%squote\n", "mode",
10629 modeDescr[p->mode], p->cmOpts.iWrap,
10630 p->cmOpts.bWordWrap ? "on" : "off",
10631 p->cmOpts.bQuote ? "" : "no");
drhe40f2862022-01-31 14:14:29 +000010632 }else{
10633 utf8_printf(p->out, "%12.12s: %s\n","mode", modeDescr[p->mode]);
10634 }
drh2ce15c32017-07-11 13:34:40 +000010635 utf8_printf(p->out, "%12.12s: ", "nullvalue");
10636 output_c_string(p->out, p->nullValue);
10637 raw_printf(p->out, "\n");
10638 utf8_printf(p->out,"%12.12s: %s\n","output",
10639 strlen30(p->outfile) ? p->outfile : "stdout");
10640 utf8_printf(p->out,"%12.12s: ", "colseparator");
10641 output_c_string(p->out, p->colSeparator);
10642 raw_printf(p->out, "\n");
10643 utf8_printf(p->out,"%12.12s: ", "rowseparator");
10644 output_c_string(p->out, p->rowSeparator);
10645 raw_printf(p->out, "\n");
drha6e6cf22021-01-09 19:10:04 +000010646 switch( p->statsOn ){
10647 case 0: zOut = "off"; break;
10648 default: zOut = "on"; break;
10649 case 2: zOut = "stmt"; break;
10650 case 3: zOut = "vmstep"; break;
10651 }
10652 utf8_printf(p->out, "%12.12s: %s\n","stats", zOut);
drh2ce15c32017-07-11 13:34:40 +000010653 utf8_printf(p->out, "%12.12s: ", "width");
drh0285d982020-05-29 14:38:43 +000010654 for (i=0;i<p->nWidth;i++) {
drh2ce15c32017-07-11 13:34:40 +000010655 raw_printf(p->out, "%d ", p->colWidth[i]);
10656 }
10657 raw_printf(p->out, "\n");
10658 utf8_printf(p->out, "%12.12s: %s\n", "filename",
drh37407122021-07-23 18:43:58 +000010659 p->pAuxDb->zDbFilename ? p->pAuxDb->zDbFilename : "");
drh2ce15c32017-07-11 13:34:40 +000010660 }else
10661
10662 if( c=='s' && strncmp(azArg[0], "stats", n)==0 ){
10663 if( nArg==2 ){
drha6e6cf22021-01-09 19:10:04 +000010664 if( strcmp(azArg[1],"stmt")==0 ){
10665 p->statsOn = 2;
10666 }else if( strcmp(azArg[1],"vmstep")==0 ){
10667 p->statsOn = 3;
10668 }else{
10669 p->statsOn = (u8)booleanValue(azArg[1]);
10670 }
drh2ce15c32017-07-11 13:34:40 +000010671 }else if( nArg==1 ){
10672 display_stats(p->db, p, 0);
10673 }else{
drha6e6cf22021-01-09 19:10:04 +000010674 raw_printf(stderr, "Usage: .stats ?on|off|stmt|vmstep?\n");
drh2ce15c32017-07-11 13:34:40 +000010675 rc = 1;
10676 }
10677 }else
10678
10679 if( (c=='t' && n>1 && strncmp(azArg[0], "tables", n)==0)
10680 || (c=='i' && (strncmp(azArg[0], "indices", n)==0
10681 || strncmp(azArg[0], "indexes", n)==0) )
10682 ){
10683 sqlite3_stmt *pStmt;
10684 char **azResult;
10685 int nRow, nAlloc;
10686 int ii;
10687 ShellText s;
10688 initText(&s);
10689 open_db(p, 0);
10690 rc = sqlite3_prepare_v2(p->db, "PRAGMA database_list", -1, &pStmt, 0);
drh9e804032018-05-18 17:11:50 +000010691 if( rc ){
10692 sqlite3_finalize(pStmt);
10693 return shellDatabaseError(p->db);
10694 }
drh2ce15c32017-07-11 13:34:40 +000010695
10696 if( nArg>2 && c=='i' ){
10697 /* It is an historical accident that the .indexes command shows an error
10698 ** when called with the wrong number of arguments whereas the .tables
10699 ** command does not. */
10700 raw_printf(stderr, "Usage: .indexes ?LIKE-PATTERN?\n");
10701 rc = 1;
drh9e804032018-05-18 17:11:50 +000010702 sqlite3_finalize(pStmt);
drh2ce15c32017-07-11 13:34:40 +000010703 goto meta_command_exit;
10704 }
10705 for(ii=0; sqlite3_step(pStmt)==SQLITE_ROW; ii++){
10706 const char *zDbName = (const char*)sqlite3_column_text(pStmt, 1);
10707 if( zDbName==0 ) continue;
10708 if( s.z && s.z[0] ) appendText(&s, " UNION ALL ", 0);
10709 if( sqlite3_stricmp(zDbName, "main")==0 ){
10710 appendText(&s, "SELECT name FROM ", 0);
10711 }else{
10712 appendText(&s, "SELECT ", 0);
10713 appendText(&s, zDbName, '\'');
10714 appendText(&s, "||'.'||name FROM ", 0);
10715 }
10716 appendText(&s, zDbName, '"');
drh067b92b2020-06-19 15:24:12 +000010717 appendText(&s, ".sqlite_schema ", 0);
drh2ce15c32017-07-11 13:34:40 +000010718 if( c=='t' ){
10719 appendText(&s," WHERE type IN ('table','view')"
10720 " AND name NOT LIKE 'sqlite_%'"
10721 " AND name LIKE ?1", 0);
10722 }else{
10723 appendText(&s," WHERE type='index'"
10724 " AND tbl_name LIKE ?1", 0);
10725 }
10726 }
10727 rc = sqlite3_finalize(pStmt);
drhe85e1da2021-10-01 21:01:07 +000010728 if( rc==SQLITE_OK ){
10729 appendText(&s, " ORDER BY 1", 0);
10730 rc = sqlite3_prepare_v2(p->db, s.z, -1, &pStmt, 0);
10731 }
drh2ce15c32017-07-11 13:34:40 +000010732 freeText(&s);
10733 if( rc ) return shellDatabaseError(p->db);
10734
10735 /* Run the SQL statement prepared by the above block. Store the results
10736 ** as an array of nul-terminated strings in azResult[]. */
10737 nRow = nAlloc = 0;
10738 azResult = 0;
10739 if( nArg>1 ){
10740 sqlite3_bind_text(pStmt, 1, azArg[1], -1, SQLITE_TRANSIENT);
10741 }else{
10742 sqlite3_bind_text(pStmt, 1, "%", -1, SQLITE_STATIC);
10743 }
10744 while( sqlite3_step(pStmt)==SQLITE_ROW ){
10745 if( nRow>=nAlloc ){
10746 char **azNew;
10747 int n2 = nAlloc*2 + 10;
10748 azNew = sqlite3_realloc64(azResult, sizeof(azResult[0])*n2);
drhe3e25652021-12-16 13:29:28 +000010749 shell_check_oom(azNew);
drh2ce15c32017-07-11 13:34:40 +000010750 nAlloc = n2;
10751 azResult = azNew;
10752 }
10753 azResult[nRow] = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 0));
drhe3e25652021-12-16 13:29:28 +000010754 shell_check_oom(azResult[nRow]);
drh2ce15c32017-07-11 13:34:40 +000010755 nRow++;
10756 }
10757 if( sqlite3_finalize(pStmt)!=SQLITE_OK ){
10758 rc = shellDatabaseError(p->db);
10759 }
10760
10761 /* Pretty-print the contents of array azResult[] to the output */
10762 if( rc==0 && nRow>0 ){
10763 int len, maxlen = 0;
10764 int i, j;
10765 int nPrintCol, nPrintRow;
10766 for(i=0; i<nRow; i++){
10767 len = strlen30(azResult[i]);
10768 if( len>maxlen ) maxlen = len;
10769 }
10770 nPrintCol = 80/(maxlen+2);
10771 if( nPrintCol<1 ) nPrintCol = 1;
10772 nPrintRow = (nRow + nPrintCol - 1)/nPrintCol;
10773 for(i=0; i<nPrintRow; i++){
10774 for(j=i; j<nRow; j+=nPrintRow){
10775 char *zSp = j<nPrintRow ? "" : " ";
10776 utf8_printf(p->out, "%s%-*s", zSp, maxlen,
10777 azResult[j] ? azResult[j]:"");
10778 }
10779 raw_printf(p->out, "\n");
10780 }
10781 }
10782
10783 for(ii=0; ii<nRow; ii++) sqlite3_free(azResult[ii]);
10784 sqlite3_free(azResult);
10785 }else
10786
10787 /* Begin redirecting output to the file "testcase-out.txt" */
10788 if( c=='t' && strcmp(azArg[0],"testcase")==0 ){
10789 output_reset(p);
drha92a01a2018-01-10 22:15:37 +000010790 p->out = output_file_open("testcase-out.txt", 0);
drh2ce15c32017-07-11 13:34:40 +000010791 if( p->out==0 ){
10792 raw_printf(stderr, "Error: cannot open 'testcase-out.txt'\n");
10793 }
10794 if( nArg>=2 ){
10795 sqlite3_snprintf(sizeof(p->zTestcase), p->zTestcase, "%s", azArg[1]);
10796 }else{
10797 sqlite3_snprintf(sizeof(p->zTestcase), p->zTestcase, "?");
10798 }
10799 }else
10800
10801#ifndef SQLITE_UNTESTABLE
drh35f51a42017-11-15 17:07:22 +000010802 if( c=='t' && n>=8 && strncmp(azArg[0], "testctrl", n)==0 ){
drh2ce15c32017-07-11 13:34:40 +000010803 static const struct {
10804 const char *zCtrlName; /* Name of a test-control option */
10805 int ctrlCode; /* Integer code for that option */
drh38ed1ce2021-12-06 15:24:36 +000010806 int unSafe; /* Not valid for --safe mode */
drhef302e82017-11-15 19:14:08 +000010807 const char *zUsage; /* Usage notes */
drh2ce15c32017-07-11 13:34:40 +000010808 } aCtrl[] = {
drh38ed1ce2021-12-06 15:24:36 +000010809 { "always", SQLITE_TESTCTRL_ALWAYS, 1, "BOOLEAN" },
10810 { "assert", SQLITE_TESTCTRL_ASSERT, 1, "BOOLEAN" },
10811 /*{ "benign_malloc_hooks",SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS,1, "" },*/
10812 /*{ "bitvec_test", SQLITE_TESTCTRL_BITVEC_TEST, 1, "" },*/
10813 { "byteorder", SQLITE_TESTCTRL_BYTEORDER, 0, "" },
10814 { "extra_schema_checks",SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS,0,"BOOLEAN" },
10815 /*{ "fault_install", SQLITE_TESTCTRL_FAULT_INSTALL, 1,"" },*/
10816 { "imposter", SQLITE_TESTCTRL_IMPOSTER,1,"SCHEMA ON/OFF ROOTPAGE"},
10817 { "internal_functions", SQLITE_TESTCTRL_INTERNAL_FUNCTIONS,0,"" },
10818 { "localtime_fault", SQLITE_TESTCTRL_LOCALTIME_FAULT,0,"BOOLEAN" },
10819 { "never_corrupt", SQLITE_TESTCTRL_NEVER_CORRUPT,1, "BOOLEAN" },
10820 { "optimizations", SQLITE_TESTCTRL_OPTIMIZATIONS,0,"DISABLE-MASK" },
drh0d9de992017-12-26 18:04:23 +000010821#ifdef YYCOVERAGE
drh38ed1ce2021-12-06 15:24:36 +000010822 { "parser_coverage", SQLITE_TESTCTRL_PARSER_COVERAGE,0,"" },
drh0d9de992017-12-26 18:04:23 +000010823#endif
drh38ed1ce2021-12-06 15:24:36 +000010824 { "pending_byte", SQLITE_TESTCTRL_PENDING_BYTE,0, "OFFSET " },
10825 { "prng_restore", SQLITE_TESTCTRL_PRNG_RESTORE,0, "" },
10826 { "prng_save", SQLITE_TESTCTRL_PRNG_SAVE, 0, "" },
10827 { "prng_seed", SQLITE_TESTCTRL_PRNG_SEED, 0, "SEED ?db?" },
10828 { "seek_count", SQLITE_TESTCTRL_SEEK_COUNT, 0, "" },
10829 { "sorter_mmap", SQLITE_TESTCTRL_SORTER_MMAP, 0, "NMAX" },
10830 { "tune", SQLITE_TESTCTRL_TUNE, 1, "ID VALUE" },
drh2ce15c32017-07-11 13:34:40 +000010831 };
10832 int testctrl = -1;
drhef302e82017-11-15 19:14:08 +000010833 int iCtrl = -1;
10834 int rc2 = 0; /* 0: usage. 1: %d 2: %x 3: no-output */
10835 int isOk = 0;
drh2ce15c32017-07-11 13:34:40 +000010836 int i, n2;
mistachkinc6bc15a2017-11-21 21:14:32 +000010837 const char *zCmd = 0;
10838
drh2ce15c32017-07-11 13:34:40 +000010839 open_db(p, 0);
mistachkinc6bc15a2017-11-21 21:14:32 +000010840 zCmd = nArg>=2 ? azArg[1] : "help";
drh35f51a42017-11-15 17:07:22 +000010841
10842 /* The argument can optionally begin with "-" or "--" */
10843 if( zCmd[0]=='-' && zCmd[1] ){
10844 zCmd++;
10845 if( zCmd[0]=='-' && zCmd[1] ) zCmd++;
10846 }
10847
10848 /* --help lists all test-controls */
10849 if( strcmp(zCmd,"help")==0 ){
10850 utf8_printf(p->out, "Available test-controls:\n");
10851 for(i=0; i<ArraySize(aCtrl); i++){
drhef302e82017-11-15 19:14:08 +000010852 utf8_printf(p->out, " .testctrl %s %s\n",
10853 aCtrl[i].zCtrlName, aCtrl[i].zUsage);
drh35f51a42017-11-15 17:07:22 +000010854 }
10855 rc = 1;
10856 goto meta_command_exit;
10857 }
drh2ce15c32017-07-11 13:34:40 +000010858
10859 /* convert testctrl text option to value. allow any unique prefix
10860 ** of the option name, or a numerical value. */
drh35f51a42017-11-15 17:07:22 +000010861 n2 = strlen30(zCmd);
drh2ce15c32017-07-11 13:34:40 +000010862 for(i=0; i<ArraySize(aCtrl); i++){
drh35f51a42017-11-15 17:07:22 +000010863 if( strncmp(zCmd, aCtrl[i].zCtrlName, n2)==0 ){
drh2ce15c32017-07-11 13:34:40 +000010864 if( testctrl<0 ){
10865 testctrl = aCtrl[i].ctrlCode;
drhef302e82017-11-15 19:14:08 +000010866 iCtrl = i;
drh2ce15c32017-07-11 13:34:40 +000010867 }else{
drh35f51a42017-11-15 17:07:22 +000010868 utf8_printf(stderr, "Error: ambiguous test-control: \"%s\"\n"
10869 "Use \".testctrl --help\" for help\n", zCmd);
10870 rc = 1;
10871 goto meta_command_exit;
drh2ce15c32017-07-11 13:34:40 +000010872 }
10873 }
10874 }
drhef302e82017-11-15 19:14:08 +000010875 if( testctrl<0 ){
drh35f51a42017-11-15 17:07:22 +000010876 utf8_printf(stderr,"Error: unknown test-control: %s\n"
10877 "Use \".testctrl --help\" for help\n", zCmd);
drh38ed1ce2021-12-06 15:24:36 +000010878 }else if( aCtrl[iCtrl].unSafe && p->bSafeMode ){
10879 utf8_printf(stderr,
10880 "line %d: \".testctrl %s\" may not be used in safe mode\n",
10881 p->lineno, aCtrl[iCtrl].zCtrlName);
10882 exit(1);
drh2ce15c32017-07-11 13:34:40 +000010883 }else{
10884 switch(testctrl){
10885
10886 /* sqlite3_test_control(int, db, int) */
10887 case SQLITE_TESTCTRL_OPTIMIZATIONS:
drh2ce15c32017-07-11 13:34:40 +000010888 if( nArg==3 ){
drhaf7b7652021-01-13 19:28:17 +000010889 unsigned int opt = (unsigned int)strtol(azArg[2], 0, 0);
drh2ce15c32017-07-11 13:34:40 +000010890 rc2 = sqlite3_test_control(testctrl, p->db, opt);
drhef302e82017-11-15 19:14:08 +000010891 isOk = 3;
drh2ce15c32017-07-11 13:34:40 +000010892 }
10893 break;
10894
10895 /* sqlite3_test_control(int) */
10896 case SQLITE_TESTCTRL_PRNG_SAVE:
10897 case SQLITE_TESTCTRL_PRNG_RESTORE:
drh2ce15c32017-07-11 13:34:40 +000010898 case SQLITE_TESTCTRL_BYTEORDER:
10899 if( nArg==2 ){
10900 rc2 = sqlite3_test_control(testctrl);
drhef302e82017-11-15 19:14:08 +000010901 isOk = testctrl==SQLITE_TESTCTRL_BYTEORDER ? 1 : 3;
drh2ce15c32017-07-11 13:34:40 +000010902 }
10903 break;
10904
10905 /* sqlite3_test_control(int, uint) */
10906 case SQLITE_TESTCTRL_PENDING_BYTE:
10907 if( nArg==3 ){
10908 unsigned int opt = (unsigned int)integerValue(azArg[2]);
10909 rc2 = sqlite3_test_control(testctrl, opt);
drhef302e82017-11-15 19:14:08 +000010910 isOk = 3;
drh2ce15c32017-07-11 13:34:40 +000010911 }
10912 break;
10913
drh2e6d83b2019-08-03 01:39:20 +000010914 /* sqlite3_test_control(int, int, sqlite3*) */
10915 case SQLITE_TESTCTRL_PRNG_SEED:
10916 if( nArg==3 || nArg==4 ){
drh51755a72019-08-08 19:40:29 +000010917 int ii = (int)integerValue(azArg[2]);
drh2e6d83b2019-08-03 01:39:20 +000010918 sqlite3 *db;
drh41428a92019-08-12 16:25:11 +000010919 if( ii==0 && strcmp(azArg[2],"random")==0 ){
10920 sqlite3_randomness(sizeof(ii),&ii);
10921 printf("-- random seed: %d\n", ii);
10922 }
drh2e6d83b2019-08-03 01:39:20 +000010923 if( nArg==3 ){
10924 db = 0;
10925 }else{
10926 db = p->db;
10927 /* Make sure the schema has been loaded */
10928 sqlite3_table_column_metadata(db, 0, "x", 0, 0, 0, 0, 0, 0);
10929 }
drh51755a72019-08-08 19:40:29 +000010930 rc2 = sqlite3_test_control(testctrl, ii, db);
drh2e6d83b2019-08-03 01:39:20 +000010931 isOk = 3;
10932 }
10933 break;
10934
drh2ce15c32017-07-11 13:34:40 +000010935 /* sqlite3_test_control(int, int) */
10936 case SQLITE_TESTCTRL_ASSERT:
10937 case SQLITE_TESTCTRL_ALWAYS:
drhef302e82017-11-15 19:14:08 +000010938 if( nArg==3 ){
10939 int opt = booleanValue(azArg[2]);
10940 rc2 = sqlite3_test_control(testctrl, opt);
10941 isOk = 1;
10942 }
10943 break;
10944
10945 /* sqlite3_test_control(int, int) */
10946 case SQLITE_TESTCTRL_LOCALTIME_FAULT:
drh2ce15c32017-07-11 13:34:40 +000010947 case SQLITE_TESTCTRL_NEVER_CORRUPT:
10948 if( nArg==3 ){
10949 int opt = booleanValue(azArg[2]);
10950 rc2 = sqlite3_test_control(testctrl, opt);
drhef302e82017-11-15 19:14:08 +000010951 isOk = 3;
drh2ce15c32017-07-11 13:34:40 +000010952 }
10953 break;
10954
drh171c50e2020-01-01 15:43:30 +000010955 /* sqlite3_test_control(sqlite3*) */
10956 case SQLITE_TESTCTRL_INTERNAL_FUNCTIONS:
10957 rc2 = sqlite3_test_control(testctrl, p->db);
drh2a83c102020-01-01 23:02:35 +000010958 isOk = 3;
drh171c50e2020-01-01 15:43:30 +000010959 break;
10960
drh2ce15c32017-07-11 13:34:40 +000010961 case SQLITE_TESTCTRL_IMPOSTER:
10962 if( nArg==5 ){
10963 rc2 = sqlite3_test_control(testctrl, p->db,
10964 azArg[2],
10965 integerValue(azArg[3]),
10966 integerValue(azArg[4]));
drhef302e82017-11-15 19:14:08 +000010967 isOk = 3;
drh2ce15c32017-07-11 13:34:40 +000010968 }
10969 break;
drh0d9de992017-12-26 18:04:23 +000010970
drh37ccfcf2020-08-31 18:49:04 +000010971 case SQLITE_TESTCTRL_SEEK_COUNT: {
10972 u64 x = 0;
10973 rc2 = sqlite3_test_control(testctrl, p->db, &x);
10974 utf8_printf(p->out, "%llu\n", x);
10975 isOk = 3;
10976 break;
10977 }
10978
drh0d9de992017-12-26 18:04:23 +000010979#ifdef YYCOVERAGE
drhf3c12562021-06-04 13:16:46 +000010980 case SQLITE_TESTCTRL_PARSER_COVERAGE: {
drh0d9de992017-12-26 18:04:23 +000010981 if( nArg==2 ){
10982 sqlite3_test_control(testctrl, p->out);
10983 isOk = 3;
10984 }
drhf3c12562021-06-04 13:16:46 +000010985 break;
10986 }
10987#endif
10988#ifdef SQLITE_DEBUG
10989 case SQLITE_TESTCTRL_TUNE: {
10990 if( nArg==4 ){
10991 int id = (int)integerValue(azArg[2]);
drh2d26cfc2021-06-04 13:40:26 +000010992 int val = (int)integerValue(azArg[3]);
10993 sqlite3_test_control(testctrl, id, &val);
10994 isOk = 3;
10995 }else if( nArg==3 ){
10996 int id = (int)integerValue(azArg[2]);
10997 sqlite3_test_control(testctrl, -id, &rc2);
10998 isOk = 1;
10999 }else if( nArg==2 ){
11000 int id = 1;
11001 while(1){
11002 int val = 0;
11003 rc2 = sqlite3_test_control(testctrl, -id, &val);
11004 if( rc2!=SQLITE_OK ) break;
11005 if( id>1 ) utf8_printf(p->out, " ");
11006 utf8_printf(p->out, "%d: %d", id, val);
11007 id++;
11008 }
11009 if( id>1 ) utf8_printf(p->out, "\n");
drhf3c12562021-06-04 13:16:46 +000011010 isOk = 3;
11011 }
11012 break;
11013 }
drh0d9de992017-12-26 18:04:23 +000011014#endif
dan779e9902021-07-28 18:13:28 +000011015 case SQLITE_TESTCTRL_SORTER_MMAP:
11016 if( nArg==3 ){
11017 int opt = (unsigned int)integerValue(azArg[2]);
11018 rc2 = sqlite3_test_control(testctrl, p->db, opt);
11019 isOk = 3;
11020 }
11021 break;
drh2ce15c32017-07-11 13:34:40 +000011022 }
11023 }
drhef302e82017-11-15 19:14:08 +000011024 if( isOk==0 && iCtrl>=0 ){
drhe2754c12019-08-26 12:50:01 +000011025 utf8_printf(p->out, "Usage: .testctrl %s %s\n", zCmd,aCtrl[iCtrl].zUsage);
drhef302e82017-11-15 19:14:08 +000011026 rc = 1;
11027 }else if( isOk==1 ){
11028 raw_printf(p->out, "%d\n", rc2);
11029 }else if( isOk==2 ){
11030 raw_printf(p->out, "0x%08x\n", rc2);
11031 }
drh2ce15c32017-07-11 13:34:40 +000011032 }else
11033#endif /* !defined(SQLITE_UNTESTABLE) */
11034
11035 if( c=='t' && n>4 && strncmp(azArg[0], "timeout", n)==0 ){
11036 open_db(p, 0);
11037 sqlite3_busy_timeout(p->db, nArg>=2 ? (int)integerValue(azArg[1]) : 0);
11038 }else
11039
11040 if( c=='t' && n>=5 && strncmp(azArg[0], "timer", n)==0 ){
11041 if( nArg==2 ){
11042 enableTimer = booleanValue(azArg[1]);
11043 if( enableTimer && !HAS_TIMER ){
11044 raw_printf(stderr, "Error: timer not available on this system.\n");
11045 enableTimer = 0;
11046 }
11047 }else{
11048 raw_printf(stderr, "Usage: .timer on|off\n");
11049 rc = 1;
11050 }
11051 }else
11052
drh707821f2018-12-05 13:39:06 +000011053#ifndef SQLITE_OMIT_TRACE
drh2ce15c32017-07-11 13:34:40 +000011054 if( c=='t' && strncmp(azArg[0], "trace", n)==0 ){
drh707821f2018-12-05 13:39:06 +000011055 int mType = 0;
11056 int jj;
drh2ce15c32017-07-11 13:34:40 +000011057 open_db(p, 0);
drh707821f2018-12-05 13:39:06 +000011058 for(jj=1; jj<nArg; jj++){
11059 const char *z = azArg[jj];
11060 if( z[0]=='-' ){
11061 if( optionMatch(z, "expanded") ){
11062 p->eTraceType = SHELL_TRACE_EXPANDED;
11063 }
11064#ifdef SQLITE_ENABLE_NORMALIZE
11065 else if( optionMatch(z, "normalized") ){
11066 p->eTraceType = SHELL_TRACE_NORMALIZED;
11067 }
11068#endif
11069 else if( optionMatch(z, "plain") ){
11070 p->eTraceType = SHELL_TRACE_PLAIN;
11071 }
11072 else if( optionMatch(z, "profile") ){
11073 mType |= SQLITE_TRACE_PROFILE;
11074 }
11075 else if( optionMatch(z, "row") ){
11076 mType |= SQLITE_TRACE_ROW;
11077 }
11078 else if( optionMatch(z, "stmt") ){
11079 mType |= SQLITE_TRACE_STMT;
11080 }
11081 else if( optionMatch(z, "close") ){
11082 mType |= SQLITE_TRACE_CLOSE;
11083 }
11084 else {
11085 raw_printf(stderr, "Unknown option \"%s\" on \".trace\"\n", z);
11086 rc = 1;
11087 goto meta_command_exit;
11088 }
11089 }else{
11090 output_file_close(p->traceOut);
11091 p->traceOut = output_file_open(azArg[1], 0);
11092 }
drh2ce15c32017-07-11 13:34:40 +000011093 }
drh2ce15c32017-07-11 13:34:40 +000011094 if( p->traceOut==0 ){
11095 sqlite3_trace_v2(p->db, 0, 0, 0);
11096 }else{
drh707821f2018-12-05 13:39:06 +000011097 if( mType==0 ) mType = SQLITE_TRACE_STMT;
11098 sqlite3_trace_v2(p->db, mType, sql_trace_callback, p);
drh2ce15c32017-07-11 13:34:40 +000011099 }
drh2ce15c32017-07-11 13:34:40 +000011100 }else
drh707821f2018-12-05 13:39:06 +000011101#endif /* !defined(SQLITE_OMIT_TRACE) */
drh2ce15c32017-07-11 13:34:40 +000011102
drhe2b7a762019-10-02 00:25:08 +000011103#if defined(SQLITE_DEBUG) && !defined(SQLITE_OMIT_VIRTUALTABLE)
drhcc5979d2019-08-16 22:58:29 +000011104 if( c=='u' && strncmp(azArg[0], "unmodule", n)==0 ){
11105 int ii;
drh8c754a32019-08-19 20:35:30 +000011106 int lenOpt;
drh5df84282019-08-17 19:45:25 +000011107 char *zOpt;
drhcc5979d2019-08-16 22:58:29 +000011108 if( nArg<2 ){
drh5df84282019-08-17 19:45:25 +000011109 raw_printf(stderr, "Usage: .unmodule [--allexcept] NAME ...\n");
drhcc5979d2019-08-16 22:58:29 +000011110 rc = 1;
11111 goto meta_command_exit;
11112 }
11113 open_db(p, 0);
drh5df84282019-08-17 19:45:25 +000011114 zOpt = azArg[1];
11115 if( zOpt[0]=='-' && zOpt[1]=='-' && zOpt[2]!=0 ) zOpt++;
drh8c754a32019-08-19 20:35:30 +000011116 lenOpt = (int)strlen(zOpt);
11117 if( lenOpt>=3 && strncmp(zOpt, "-allexcept",lenOpt)==0 ){
drh5df84282019-08-17 19:45:25 +000011118 assert( azArg[nArg]==0 );
drh8c754a32019-08-19 20:35:30 +000011119 sqlite3_drop_modules(p->db, nArg>2 ? (const char**)(azArg+2) : 0);
drh5df84282019-08-17 19:45:25 +000011120 }else{
11121 for(ii=1; ii<nArg; ii++){
11122 sqlite3_create_module(p->db, azArg[ii], 0, 0);
11123 }
drhcc5979d2019-08-16 22:58:29 +000011124 }
11125 }else
11126#endif
11127
drh2ce15c32017-07-11 13:34:40 +000011128#if SQLITE_USER_AUTHENTICATION
11129 if( c=='u' && strncmp(azArg[0], "user", n)==0 ){
11130 if( nArg<2 ){
11131 raw_printf(stderr, "Usage: .user SUBCOMMAND ...\n");
11132 rc = 1;
11133 goto meta_command_exit;
11134 }
11135 open_db(p, 0);
11136 if( strcmp(azArg[1],"login")==0 ){
11137 if( nArg!=4 ){
11138 raw_printf(stderr, "Usage: .user login USER PASSWORD\n");
11139 rc = 1;
11140 goto meta_command_exit;
11141 }
drhe2754c12019-08-26 12:50:01 +000011142 rc = sqlite3_user_authenticate(p->db, azArg[2], azArg[3],
11143 strlen30(azArg[3]));
drh2ce15c32017-07-11 13:34:40 +000011144 if( rc ){
11145 utf8_printf(stderr, "Authentication failed for user %s\n", azArg[2]);
11146 rc = 1;
11147 }
11148 }else if( strcmp(azArg[1],"add")==0 ){
11149 if( nArg!=5 ){
11150 raw_printf(stderr, "Usage: .user add USER PASSWORD ISADMIN\n");
11151 rc = 1;
11152 goto meta_command_exit;
11153 }
drhaf2770f2018-01-05 14:55:43 +000011154 rc = sqlite3_user_add(p->db, azArg[2], azArg[3], strlen30(azArg[3]),
drh2ce15c32017-07-11 13:34:40 +000011155 booleanValue(azArg[4]));
11156 if( rc ){
11157 raw_printf(stderr, "User-Add failed: %d\n", rc);
11158 rc = 1;
11159 }
11160 }else if( strcmp(azArg[1],"edit")==0 ){
11161 if( nArg!=5 ){
11162 raw_printf(stderr, "Usage: .user edit USER PASSWORD ISADMIN\n");
11163 rc = 1;
11164 goto meta_command_exit;
11165 }
drhaf2770f2018-01-05 14:55:43 +000011166 rc = sqlite3_user_change(p->db, azArg[2], azArg[3], strlen30(azArg[3]),
drh2ce15c32017-07-11 13:34:40 +000011167 booleanValue(azArg[4]));
11168 if( rc ){
11169 raw_printf(stderr, "User-Edit failed: %d\n", rc);
11170 rc = 1;
11171 }
11172 }else if( strcmp(azArg[1],"delete")==0 ){
11173 if( nArg!=3 ){
11174 raw_printf(stderr, "Usage: .user delete USER\n");
11175 rc = 1;
11176 goto meta_command_exit;
11177 }
11178 rc = sqlite3_user_delete(p->db, azArg[2]);
11179 if( rc ){
11180 raw_printf(stderr, "User-Delete failed: %d\n", rc);
11181 rc = 1;
11182 }
11183 }else{
11184 raw_printf(stderr, "Usage: .user login|add|edit|delete ...\n");
11185 rc = 1;
11186 goto meta_command_exit;
11187 }
11188 }else
11189#endif /* SQLITE_USER_AUTHENTICATION */
11190
11191 if( c=='v' && strncmp(azArg[0], "version", n)==0 ){
11192 utf8_printf(p->out, "SQLite %s %s\n" /*extra-version-info*/,
11193 sqlite3_libversion(), sqlite3_sourceid());
drh0ed2fd82018-01-16 20:05:27 +000011194#if SQLITE_HAVE_ZLIB
11195 utf8_printf(p->out, "zlib version %s\n", zlibVersion());
11196#endif
11197#define CTIMEOPT_VAL_(opt) #opt
11198#define CTIMEOPT_VAL(opt) CTIMEOPT_VAL_(opt)
11199#if defined(__clang__) && defined(__clang_major__)
11200 utf8_printf(p->out, "clang-" CTIMEOPT_VAL(__clang_major__) "."
11201 CTIMEOPT_VAL(__clang_minor__) "."
11202 CTIMEOPT_VAL(__clang_patchlevel__) "\n");
11203#elif defined(_MSC_VER)
11204 utf8_printf(p->out, "msvc-" CTIMEOPT_VAL(_MSC_VER) "\n");
11205#elif defined(__GNUC__) && defined(__VERSION__)
11206 utf8_printf(p->out, "gcc-" __VERSION__ "\n");
11207#endif
drh2ce15c32017-07-11 13:34:40 +000011208 }else
11209
11210 if( c=='v' && strncmp(azArg[0], "vfsinfo", n)==0 ){
11211 const char *zDbName = nArg==2 ? azArg[1] : "main";
11212 sqlite3_vfs *pVfs = 0;
11213 if( p->db ){
11214 sqlite3_file_control(p->db, zDbName, SQLITE_FCNTL_VFS_POINTER, &pVfs);
11215 if( pVfs ){
11216 utf8_printf(p->out, "vfs.zName = \"%s\"\n", pVfs->zName);
11217 raw_printf(p->out, "vfs.iVersion = %d\n", pVfs->iVersion);
11218 raw_printf(p->out, "vfs.szOsFile = %d\n", pVfs->szOsFile);
11219 raw_printf(p->out, "vfs.mxPathname = %d\n", pVfs->mxPathname);
11220 }
11221 }
11222 }else
11223
11224 if( c=='v' && strncmp(azArg[0], "vfslist", n)==0 ){
11225 sqlite3_vfs *pVfs;
11226 sqlite3_vfs *pCurrent = 0;
11227 if( p->db ){
11228 sqlite3_file_control(p->db, "main", SQLITE_FCNTL_VFS_POINTER, &pCurrent);
11229 }
11230 for(pVfs=sqlite3_vfs_find(0); pVfs; pVfs=pVfs->pNext){
11231 utf8_printf(p->out, "vfs.zName = \"%s\"%s\n", pVfs->zName,
11232 pVfs==pCurrent ? " <--- CURRENT" : "");
11233 raw_printf(p->out, "vfs.iVersion = %d\n", pVfs->iVersion);
11234 raw_printf(p->out, "vfs.szOsFile = %d\n", pVfs->szOsFile);
11235 raw_printf(p->out, "vfs.mxPathname = %d\n", pVfs->mxPathname);
11236 if( pVfs->pNext ){
11237 raw_printf(p->out, "-----------------------------------\n");
11238 }
11239 }
11240 }else
11241
11242 if( c=='v' && strncmp(azArg[0], "vfsname", n)==0 ){
11243 const char *zDbName = nArg==2 ? azArg[1] : "main";
11244 char *zVfsName = 0;
11245 if( p->db ){
11246 sqlite3_file_control(p->db, zDbName, SQLITE_FCNTL_VFSNAME, &zVfsName);
11247 if( zVfsName ){
11248 utf8_printf(p->out, "%s\n", zVfsName);
11249 sqlite3_free(zVfsName);
11250 }
11251 }
11252 }else
11253
drh2ce15c32017-07-11 13:34:40 +000011254 if( c=='w' && strncmp(azArg[0], "wheretrace", n)==0 ){
drhc0622a42020-12-04 01:17:57 +000011255 unsigned int x = nArg>=2 ? (unsigned int)integerValue(azArg[1]) : 0xffffffff;
11256 sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 3, &x);
drh2ce15c32017-07-11 13:34:40 +000011257 }else
drh2ce15c32017-07-11 13:34:40 +000011258
11259 if( c=='w' && strncmp(azArg[0], "width", n)==0 ){
11260 int j;
11261 assert( nArg<=ArraySize(azArg) );
drh0285d982020-05-29 14:38:43 +000011262 p->nWidth = nArg-1;
drh76fc88f2021-10-02 16:39:16 +000011263 p->colWidth = realloc(p->colWidth, (p->nWidth+1)*sizeof(int)*2);
drh0285d982020-05-29 14:38:43 +000011264 if( p->colWidth==0 && p->nWidth>0 ) shell_out_of_memory();
11265 if( p->nWidth ) p->actualWidth = &p->colWidth[p->nWidth];
11266 for(j=1; j<nArg; j++){
drh2ce15c32017-07-11 13:34:40 +000011267 p->colWidth[j-1] = (int)integerValue(azArg[j]);
11268 }
11269 }else
11270
11271 {
11272 utf8_printf(stderr, "Error: unknown command or invalid arguments: "
11273 " \"%s\". Enter \".help\" for help\n", azArg[0]);
11274 rc = 1;
11275 }
11276
11277meta_command_exit:
11278 if( p->outCount ){
11279 p->outCount--;
11280 if( p->outCount==0 ) output_reset(p);
11281 }
drhb97e2ad2021-08-26 18:31:39 +000011282 p->bSafeMode = p->bSafeModePersist;
drh2ce15c32017-07-11 13:34:40 +000011283 return rc;
11284}
11285
larrybr8bc4cbc2021-09-10 00:58:46 +000011286/* Line scan result and intermediate states (supporting scan resumption)
drh2ce15c32017-07-11 13:34:40 +000011287*/
drh68911c22021-09-22 14:26:22 +000011288#ifndef CHAR_BIT
11289# define CHAR_BIT 8
11290#endif
larrybr8bc4cbc2021-09-10 00:58:46 +000011291typedef enum {
larrybr7e009842021-09-18 21:35:22 +000011292 QSS_HasDark = 1<<CHAR_BIT, QSS_EndingSemi = 2<<CHAR_BIT,
11293 QSS_CharMask = (1<<CHAR_BIT)-1, QSS_ScanMask = 3<<CHAR_BIT,
larrybra96bbe92021-09-10 19:45:22 +000011294 QSS_Start = 0
larrybr8bc4cbc2021-09-10 00:58:46 +000011295} QuickScanState;
larrybr7e009842021-09-18 21:35:22 +000011296#define QSS_SETV(qss, newst) ((newst) | ((qss) & QSS_ScanMask))
11297#define QSS_INPLAIN(qss) (((qss)&QSS_CharMask)==QSS_Start)
11298#define QSS_PLAINWHITE(qss) (((qss)&~QSS_EndingSemi)==QSS_Start)
larrybra96bbe92021-09-10 19:45:22 +000011299#define QSS_PLAINDARK(qss) (((qss)&~QSS_EndingSemi)==QSS_HasDark)
larrybr7e009842021-09-18 21:35:22 +000011300#define QSS_SEMITERM(qss) (((qss)&~QSS_HasDark)==QSS_EndingSemi)
drh2ce15c32017-07-11 13:34:40 +000011301
11302/*
larrybr8bc4cbc2021-09-10 00:58:46 +000011303** Scan line for classification to guide shell's handling.
11304** The scan is resumable for subsequent lines when prior
11305** return values are passed as the 2nd argument.
drh2ce15c32017-07-11 13:34:40 +000011306*/
larrybr8bc4cbc2021-09-10 00:58:46 +000011307static QuickScanState quickscan(char *zLine, QuickScanState qss){
11308 char cin;
larrybr7e009842021-09-18 21:35:22 +000011309 char cWait = (char)qss; /* intentional narrowing loss */
11310 if( cWait==0 ){
11311 PlainScan:
drhe85e1da2021-10-01 21:01:07 +000011312 assert( cWait==0 );
drhfd7abcd2021-09-22 13:43:16 +000011313 while( (cin = *zLine++)!=0 ){
larrybr8bc4cbc2021-09-10 00:58:46 +000011314 if( IsSpace(cin) )
11315 continue;
11316 switch (cin){
11317 case '-':
larrybr7e009842021-09-18 21:35:22 +000011318 if( *zLine!='-' )
11319 break;
11320 while((cin = *++zLine)!=0 )
11321 if( cin=='\n')
11322 goto PlainScan;
11323 return qss;
larrybr8bc4cbc2021-09-10 00:58:46 +000011324 case ';':
larrybra96bbe92021-09-10 19:45:22 +000011325 qss |= QSS_EndingSemi;
11326 continue;
larrybr8bc4cbc2021-09-10 00:58:46 +000011327 case '/':
11328 if( *zLine=='*' ){
11329 ++zLine;
larrybr7e009842021-09-18 21:35:22 +000011330 cWait = '*';
11331 qss = QSS_SETV(qss, cWait);
11332 goto TermScan;
larrybr8bc4cbc2021-09-10 00:58:46 +000011333 }
11334 break;
larrybra96bbe92021-09-10 19:45:22 +000011335 case '[':
11336 cin = ']';
11337 /* fall thru */
11338 case '`': case '\'': case '"':
larrybr7e009842021-09-18 21:35:22 +000011339 cWait = cin;
11340 qss = QSS_HasDark | cWait;
11341 goto TermScan;
larrybr8bc4cbc2021-09-10 00:58:46 +000011342 default:
11343 break;
11344 }
larrybr7e009842021-09-18 21:35:22 +000011345 qss = (qss & ~QSS_EndingSemi) | QSS_HasDark;
drh2ce15c32017-07-11 13:34:40 +000011346 }
larrybr7e009842021-09-18 21:35:22 +000011347 }else{
11348 TermScan:
drhfd7abcd2021-09-22 13:43:16 +000011349 while( (cin = *zLine++)!=0 ){
larrybr7e009842021-09-18 21:35:22 +000011350 if( cin==cWait ){
11351 switch( cWait ){
11352 case '*':
11353 if( *zLine != '/' )
11354 continue;
11355 ++zLine;
11356 cWait = 0;
11357 qss = QSS_SETV(qss, 0);
11358 goto PlainScan;
11359 case '`': case '\'': case '"':
11360 if(*zLine==cWait){
larrybr8d463ce2021-09-11 02:42:04 +000011361 ++zLine;
larrybr7e009842021-09-18 21:35:22 +000011362 continue;
11363 }
11364 /* fall thru */
11365 case ']':
11366 cWait = 0;
11367 qss = QSS_SETV(qss, 0);
11368 goto PlainScan;
larrybr527c39d2022-05-10 14:55:45 +000011369 default: assert(0);
larrybr8bc4cbc2021-09-10 00:58:46 +000011370 }
11371 }
11372 }
drh2ce15c32017-07-11 13:34:40 +000011373 }
larrybr8bc4cbc2021-09-10 00:58:46 +000011374 return qss;
drh2ce15c32017-07-11 13:34:40 +000011375}
11376
11377/*
11378** Return TRUE if the line typed in is an SQL command terminator other
11379** than a semi-colon. The SQL Server style "go" command is understood
11380** as is the Oracle "/".
11381*/
larrybr8bc4cbc2021-09-10 00:58:46 +000011382static int line_is_command_terminator(char *zLine){
drh2ce15c32017-07-11 13:34:40 +000011383 while( IsSpace(zLine[0]) ){ zLine++; };
larrybr8bc4cbc2021-09-10 00:58:46 +000011384 if( zLine[0]=='/' )
11385 zLine += 1; /* Oracle */
11386 else if ( ToLower(zLine[0])=='g' && ToLower(zLine[1])=='o' )
11387 zLine += 2; /* SQL Server */
11388 else
11389 return 0;
larrybr527c39d2022-05-10 14:55:45 +000011390 return quickscan(zLine, QSS_Start)==QSS_Start;
drh2ce15c32017-07-11 13:34:40 +000011391}
11392
11393/*
drh56f17742018-01-24 01:58:49 +000011394** We need a default sqlite3_complete() implementation to use in case
11395** the shell is compiled with SQLITE_OMIT_COMPLETE. The default assumes
11396** any arbitrary text is a complete SQL statement. This is not very
11397** user-friendly, but it does seem to work.
11398*/
11399#ifdef SQLITE_OMIT_COMPLETE
danc86b23b2018-11-16 14:36:42 +000011400#define sqlite3_complete(x) 1
drh56f17742018-01-24 01:58:49 +000011401#endif
11402
11403/*
drh2ce15c32017-07-11 13:34:40 +000011404** Return true if zSql is a complete SQL statement. Return false if it
11405** ends in the middle of a string literal or C-style comment.
11406*/
11407static int line_is_complete(char *zSql, int nSql){
11408 int rc;
11409 if( zSql==0 ) return 1;
11410 zSql[nSql] = ';';
11411 zSql[nSql+1] = 0;
11412 rc = sqlite3_complete(zSql);
11413 zSql[nSql] = 0;
11414 return rc;
11415}
11416
11417/*
drhfc29a862018-05-11 19:11:18 +000011418** Run a single line of SQL. Return the number of errors.
drh2ce15c32017-07-11 13:34:40 +000011419*/
11420static int runOneSqlLine(ShellState *p, char *zSql, FILE *in, int startline){
11421 int rc;
11422 char *zErrMsg = 0;
11423
11424 open_db(p, 0);
11425 if( ShellHasFlag(p,SHFLG_Backslash) ) resolve_backslashes(zSql);
drhfc4eeef2019-02-05 19:48:46 +000011426 if( p->flgProgress & SHELL_PROGRESS_RESET ) p->nProgress = 0;
drh2ce15c32017-07-11 13:34:40 +000011427 BEGIN_TIMER;
drha10b9992018-03-09 15:24:33 +000011428 rc = shell_exec(p, zSql, &zErrMsg);
drh2ce15c32017-07-11 13:34:40 +000011429 END_TIMER;
11430 if( rc || zErrMsg ){
11431 char zPrefix[100];
drh3e46db22022-02-08 11:52:45 +000011432 const char *zErrorTail;
11433 const char *zErrorType;
11434 if( zErrMsg==0 ){
11435 zErrorType = "Error";
11436 zErrorTail = sqlite3_errmsg(p->db);
11437 }else if( strncmp(zErrMsg, "in prepare, ",12)==0 ){
11438 zErrorType = "Parse error";
11439 zErrorTail = &zErrMsg[12];
11440 }else if( strncmp(zErrMsg, "stepping, ", 10)==0 ){
11441 zErrorType = "Runtime error";
11442 zErrorTail = &zErrMsg[10];
11443 }else{
11444 zErrorType = "Error";
11445 zErrorTail = zErrMsg;
11446 }
drh2ce15c32017-07-11 13:34:40 +000011447 if( in!=0 || !stdin_is_interactive ){
11448 sqlite3_snprintf(sizeof(zPrefix), zPrefix,
drh3e46db22022-02-08 11:52:45 +000011449 "%s near line %d:", zErrorType, startline);
drh2ce15c32017-07-11 13:34:40 +000011450 }else{
drh3e46db22022-02-08 11:52:45 +000011451 sqlite3_snprintf(sizeof(zPrefix), zPrefix, "%s:", zErrorType);
drh2ce15c32017-07-11 13:34:40 +000011452 }
drh3e46db22022-02-08 11:52:45 +000011453 utf8_printf(stderr, "%s %s\n", zPrefix, zErrorTail);
11454 sqlite3_free(zErrMsg);
11455 zErrMsg = 0;
drh2ce15c32017-07-11 13:34:40 +000011456 return 1;
11457 }else if( ShellHasFlag(p, SHFLG_CountChanges) ){
drh6d9f0342021-09-22 10:28:50 +000011458 char zLineBuf[2000];
11459 sqlite3_snprintf(sizeof(zLineBuf), zLineBuf,
11460 "changes: %lld total_changes: %lld",
larrybr10496f72021-06-23 16:07:20 +000011461 sqlite3_changes64(p->db), sqlite3_total_changes64(p->db));
drh6d9f0342021-09-22 10:28:50 +000011462 raw_printf(p->out, "%s\n", zLineBuf);
drh2ce15c32017-07-11 13:34:40 +000011463 }
11464 return 0;
11465}
11466
larrybrf4874812022-05-11 19:59:31 +000011467static void echo_group_input(ShellState *p, const char *zDo){
11468 if( ShellHasFlag(p, SHFLG_Echo) ) utf8_printf(p->out, "%s\n", zDo);
11469}
drh2ce15c32017-07-11 13:34:40 +000011470
11471/*
11472** Read input from *in and process it. If *in==0 then input
11473** is interactive - the user is typing it it. Otherwise, input
11474** is coming from a file or device. A prompt is issued and history
11475** is saved only if input is interactive. An interrupt signal will
11476** cause this routine to exit immediately, unless input is interactive.
11477**
11478** Return the number of errors.
11479*/
drh60379d42018-12-13 18:30:01 +000011480static int process_input(ShellState *p){
drh2ce15c32017-07-11 13:34:40 +000011481 char *zLine = 0; /* A single input line */
11482 char *zSql = 0; /* Accumulated SQL text */
11483 int nLine; /* Length of current line */
11484 int nSql = 0; /* Bytes of zSql[] used */
11485 int nAlloc = 0; /* Allocated zSql[] space */
drh2ce15c32017-07-11 13:34:40 +000011486 int rc; /* Error code */
11487 int errCnt = 0; /* Number of errors seen */
drh2ce15c32017-07-11 13:34:40 +000011488 int startline = 0; /* Line number for start of current input */
larrybr7e009842021-09-18 21:35:22 +000011489 QuickScanState qss = QSS_Start; /* Accumulated line status (so far) */
drh2ce15c32017-07-11 13:34:40 +000011490
larrybrd48e88e2022-01-24 06:36:16 +000011491 if( p->inputNesting==MAX_INPUT_NESTING ){
11492 /* This will be more informative in a later version. */
11493 utf8_printf(stderr,"Input nesting limit (%d) reached at line %d."
11494 " Check recursion.\n", MAX_INPUT_NESTING, p->lineno);
11495 return 1;
11496 }
11497 ++p->inputNesting;
drh2c8ee022018-12-13 18:59:30 +000011498 p->lineno = 0;
drh60379d42018-12-13 18:30:01 +000011499 while( errCnt==0 || !bail_on_error || (p->in==0 && stdin_is_interactive) ){
drh2ce15c32017-07-11 13:34:40 +000011500 fflush(p->out);
drh60379d42018-12-13 18:30:01 +000011501 zLine = one_input_line(p->in, zLine, nSql>0);
drh2ce15c32017-07-11 13:34:40 +000011502 if( zLine==0 ){
11503 /* End of input */
drh60379d42018-12-13 18:30:01 +000011504 if( p->in==0 && stdin_is_interactive ) printf("\n");
drh2ce15c32017-07-11 13:34:40 +000011505 break;
11506 }
11507 if( seenInterrupt ){
drh60379d42018-12-13 18:30:01 +000011508 if( p->in!=0 ) break;
drh2ce15c32017-07-11 13:34:40 +000011509 seenInterrupt = 0;
11510 }
drh2c8ee022018-12-13 18:59:30 +000011511 p->lineno++;
larrybr7e009842021-09-18 21:35:22 +000011512 if( QSS_INPLAIN(qss)
larrybr8bc4cbc2021-09-10 00:58:46 +000011513 && line_is_command_terminator(zLine)
11514 && line_is_complete(zSql, nSql) ){
11515 memcpy(zLine,";",2);
11516 }
11517 qss = quickscan(zLine, qss);
11518 if( QSS_PLAINWHITE(qss) && nSql==0 ){
larrybrd797d6b2021-10-03 22:03:59 +000011519 /* Just swallow single-line whitespace */
larrybrf4874812022-05-11 19:59:31 +000011520 echo_group_input(p, zLine);
larrybrd797d6b2021-10-03 22:03:59 +000011521 qss = QSS_Start;
larrybr8bc4cbc2021-09-10 00:58:46 +000011522 continue;
drh2ce15c32017-07-11 13:34:40 +000011523 }
drh1615c372018-05-12 23:56:22 +000011524 if( zLine && (zLine[0]=='.' || zLine[0]=='#') && nSql==0 ){
larrybrf4874812022-05-11 19:59:31 +000011525 echo_group_input(p, zLine);
drh1615c372018-05-12 23:56:22 +000011526 if( zLine[0]=='.' ){
11527 rc = do_meta_command(zLine, p);
11528 if( rc==2 ){ /* exit requested */
11529 break;
11530 }else if( rc ){
11531 errCnt++;
11532 }
drh2ce15c32017-07-11 13:34:40 +000011533 }
larrybr81012162021-10-02 15:34:52 +000011534 qss = QSS_Start;
drh2ce15c32017-07-11 13:34:40 +000011535 continue;
11536 }
larrybrd797d6b2021-10-03 22:03:59 +000011537 /* No single-line dispositions remain; accumulate line(s). */
drh2ce15c32017-07-11 13:34:40 +000011538 nLine = strlen30(zLine);
11539 if( nSql+nLine+2>=nAlloc ){
larrybr31bffb42021-09-08 21:49:03 +000011540 /* Grow buffer by half-again increments when big. */
11541 nAlloc = nSql+(nSql>>1)+nLine+100;
drh2ce15c32017-07-11 13:34:40 +000011542 zSql = realloc(zSql, nAlloc);
drhe3e25652021-12-16 13:29:28 +000011543 shell_check_oom(zSql);
drh2ce15c32017-07-11 13:34:40 +000011544 }
drh2ce15c32017-07-11 13:34:40 +000011545 if( nSql==0 ){
11546 int i;
11547 for(i=0; zLine[i] && IsSpace(zLine[i]); i++){}
11548 assert( nAlloc>0 && zSql!=0 );
11549 memcpy(zSql, zLine+i, nLine+1-i);
drh2c8ee022018-12-13 18:59:30 +000011550 startline = p->lineno;
drh2ce15c32017-07-11 13:34:40 +000011551 nSql = nLine-i;
11552 }else{
11553 zSql[nSql++] = '\n';
11554 memcpy(zSql+nSql, zLine, nLine+1);
11555 nSql += nLine;
11556 }
larrybra96bbe92021-09-10 19:45:22 +000011557 if( nSql && QSS_SEMITERM(qss) && sqlite3_complete(zSql) ){
larrybrf4874812022-05-11 19:59:31 +000011558 echo_group_input(p, zSql);
drh60379d42018-12-13 18:30:01 +000011559 errCnt += runOneSqlLine(p, zSql, p->in, startline);
drh2ce15c32017-07-11 13:34:40 +000011560 nSql = 0;
11561 if( p->outCount ){
11562 output_reset(p);
11563 p->outCount = 0;
drh13c20932018-01-10 21:41:55 +000011564 }else{
11565 clearTempFile(p);
drh2ce15c32017-07-11 13:34:40 +000011566 }
drhb97e2ad2021-08-26 18:31:39 +000011567 p->bSafeMode = p->bSafeModePersist;
larrybrd797d6b2021-10-03 22:03:59 +000011568 qss = QSS_Start;
larrybr8bc4cbc2021-09-10 00:58:46 +000011569 }else if( nSql && QSS_PLAINWHITE(qss) ){
larrybrf4874812022-05-11 19:59:31 +000011570 echo_group_input(p, zSql);
drh2ce15c32017-07-11 13:34:40 +000011571 nSql = 0;
larrybrd797d6b2021-10-03 22:03:59 +000011572 qss = QSS_Start;
drh2ce15c32017-07-11 13:34:40 +000011573 }
11574 }
larrybrc6e2f2e2022-03-15 17:57:42 +000011575 if( nSql ){
11576 /* This may be incomplete. Let the SQL parser deal with that. */
larrybrf4874812022-05-11 19:59:31 +000011577 echo_group_input(p, zSql);
drh60379d42018-12-13 18:30:01 +000011578 errCnt += runOneSqlLine(p, zSql, p->in, startline);
drh2ce15c32017-07-11 13:34:40 +000011579 }
11580 free(zSql);
11581 free(zLine);
larrybrd48e88e2022-01-24 06:36:16 +000011582 --p->inputNesting;
drh2ce15c32017-07-11 13:34:40 +000011583 return errCnt>0;
11584}
11585
11586/*
11587** Return a pathname which is the user's home directory. A
11588** 0 return indicates an error of some kind.
11589*/
11590static char *find_home_dir(int clearFlag){
11591 static char *home_dir = NULL;
11592 if( clearFlag ){
11593 free(home_dir);
11594 home_dir = 0;
11595 return 0;
11596 }
11597 if( home_dir ) return home_dir;
11598
11599#if !defined(_WIN32) && !defined(WIN32) && !defined(_WIN32_WCE) \
11600 && !defined(__RTP__) && !defined(_WRS_KERNEL)
11601 {
11602 struct passwd *pwent;
11603 uid_t uid = getuid();
11604 if( (pwent=getpwuid(uid)) != NULL) {
11605 home_dir = pwent->pw_dir;
11606 }
11607 }
11608#endif
11609
11610#if defined(_WIN32_WCE)
11611 /* Windows CE (arm-wince-mingw32ce-gcc) does not provide getenv()
11612 */
11613 home_dir = "/";
11614#else
11615
11616#if defined(_WIN32) || defined(WIN32)
11617 if (!home_dir) {
11618 home_dir = getenv("USERPROFILE");
11619 }
11620#endif
11621
11622 if (!home_dir) {
11623 home_dir = getenv("HOME");
11624 }
11625
11626#if defined(_WIN32) || defined(WIN32)
11627 if (!home_dir) {
11628 char *zDrive, *zPath;
11629 int n;
11630 zDrive = getenv("HOMEDRIVE");
11631 zPath = getenv("HOMEPATH");
11632 if( zDrive && zPath ){
11633 n = strlen30(zDrive) + strlen30(zPath) + 1;
11634 home_dir = malloc( n );
11635 if( home_dir==0 ) return 0;
11636 sqlite3_snprintf(n, home_dir, "%s%s", zDrive, zPath);
11637 return home_dir;
11638 }
11639 home_dir = "c:\\";
11640 }
11641#endif
11642
11643#endif /* !_WIN32_WCE */
11644
11645 if( home_dir ){
11646 int n = strlen30(home_dir) + 1;
11647 char *z = malloc( n );
11648 if( z ) memcpy(z, home_dir, n);
11649 home_dir = z;
11650 }
11651
11652 return home_dir;
11653}
11654
11655/*
11656** Read input from the file given by sqliterc_override. Or if that
11657** parameter is NULL, take input from ~/.sqliterc
11658**
11659** Returns the number of errors.
11660*/
11661static void process_sqliterc(
11662 ShellState *p, /* Configuration data */
11663 const char *sqliterc_override /* Name of config file. NULL to use default */
11664){
11665 char *home_dir = NULL;
11666 const char *sqliterc = sqliterc_override;
11667 char *zBuf = 0;
drh60379d42018-12-13 18:30:01 +000011668 FILE *inSaved = p->in;
drh2c8ee022018-12-13 18:59:30 +000011669 int savedLineno = p->lineno;
drh2ce15c32017-07-11 13:34:40 +000011670
11671 if (sqliterc == NULL) {
11672 home_dir = find_home_dir(0);
11673 if( home_dir==0 ){
11674 raw_printf(stderr, "-- warning: cannot find home directory;"
11675 " cannot read ~/.sqliterc\n");
11676 return;
11677 }
drh2ce15c32017-07-11 13:34:40 +000011678 zBuf = sqlite3_mprintf("%s/.sqliterc",home_dir);
drhe3e25652021-12-16 13:29:28 +000011679 shell_check_oom(zBuf);
drh2ce15c32017-07-11 13:34:40 +000011680 sqliterc = zBuf;
11681 }
drh60379d42018-12-13 18:30:01 +000011682 p->in = fopen(sqliterc,"rb");
11683 if( p->in ){
drh2ce15c32017-07-11 13:34:40 +000011684 if( stdin_is_interactive ){
11685 utf8_printf(stderr,"-- Loading resources from %s\n",sqliterc);
11686 }
drhb7c46aa2020-11-25 13:59:47 +000011687 if( process_input(p) && bail_on_error ) exit(1);
drh60379d42018-12-13 18:30:01 +000011688 fclose(p->in);
drhb7c46aa2020-11-25 13:59:47 +000011689 }else if( sqliterc_override!=0 ){
11690 utf8_printf(stderr,"cannot open: \"%s\"\n", sqliterc);
11691 if( bail_on_error ) exit(1);
drh2ce15c32017-07-11 13:34:40 +000011692 }
drh60379d42018-12-13 18:30:01 +000011693 p->in = inSaved;
drh2c8ee022018-12-13 18:59:30 +000011694 p->lineno = savedLineno;
drh2ce15c32017-07-11 13:34:40 +000011695 sqlite3_free(zBuf);
11696}
11697
11698/*
11699** Show available command line options
11700*/
11701static const char zOptions[] =
drhda57d962018-03-05 19:34:05 +000011702#if defined(SQLITE_HAVE_ZLIB) && !defined(SQLITE_OMIT_VIRTUALTABLE)
drhad7fd5d2018-03-05 20:21:50 +000011703 " -A ARGS... run \".archive ARGS\" and exit\n"
drhda57d962018-03-05 19:34:05 +000011704#endif
drh3baed312018-03-08 18:14:41 +000011705 " -append append the database to the end of the file\n"
drh2ce15c32017-07-11 13:34:40 +000011706 " -ascii set output mode to 'ascii'\n"
11707 " -bail stop after hitting an error\n"
11708 " -batch force batch I/O\n"
drh0908e382020-06-04 18:05:39 +000011709 " -box set output mode to 'box'\n"
drh2ce15c32017-07-11 13:34:40 +000011710 " -column set output mode to 'column'\n"
11711 " -cmd COMMAND run \"COMMAND\" before reading stdin\n"
11712 " -csv set output mode to 'csv'\n"
drh8d889af2021-05-08 17:18:23 +000011713#if !defined(SQLITE_OMIT_DESERIALIZE)
drh6ca64482019-01-22 16:06:20 +000011714 " -deserialize open the database using sqlite3_deserialize()\n"
11715#endif
larrybr527c39d2022-05-10 14:55:45 +000011716 " -echo print inputs before execution\n"
drh2ce15c32017-07-11 13:34:40 +000011717 " -init FILENAME read/process named file\n"
11718 " -[no]header turn headers on or off\n"
11719#if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5)
11720 " -heap SIZE Size of heap for memsys3 or memsys5\n"
11721#endif
11722 " -help show this message\n"
11723 " -html set output mode to HTML\n"
11724 " -interactive force interactive I/O\n"
drh30c54a02020-05-28 23:49:50 +000011725 " -json set output mode to 'json'\n"
drh2ce15c32017-07-11 13:34:40 +000011726 " -line set output mode to 'line'\n"
11727 " -list set output mode to 'list'\n"
11728 " -lookaside SIZE N use N entries of SZ bytes for lookaside memory\n"
drh30c54a02020-05-28 23:49:50 +000011729 " -markdown set output mode to 'markdown'\n"
drh8d889af2021-05-08 17:18:23 +000011730#if !defined(SQLITE_OMIT_DESERIALIZE)
drh6ca64482019-01-22 16:06:20 +000011731 " -maxsize N maximum size for a --deserialize database\n"
11732#endif
drhaf482572019-02-04 19:52:39 +000011733 " -memtrace trace all memory allocations and deallocations\n"
drh2ce15c32017-07-11 13:34:40 +000011734 " -mmap N default mmap size set to N\n"
11735#ifdef SQLITE_ENABLE_MULTIPLEX
11736 " -multiplex enable the multiplexor VFS\n"
11737#endif
11738 " -newline SEP set output row separator. Default: '\\n'\n"
drh0933aad2019-11-18 17:46:38 +000011739 " -nofollow refuse to open symbolic links to database files\n"
drhb97e2ad2021-08-26 18:31:39 +000011740 " -nonce STRING set the safe-mode escape nonce\n"
drh2ce15c32017-07-11 13:34:40 +000011741 " -nullvalue TEXT set text string for NULL values. Default ''\n"
11742 " -pagecache SIZE N use N slots of SZ bytes each for page cache memory\n"
11743 " -quote set output mode to 'quote'\n"
drhee269a62018-02-14 23:27:43 +000011744 " -readonly open the database read-only\n"
drhb97e2ad2021-08-26 18:31:39 +000011745 " -safe enable safe-mode\n"
drh2ce15c32017-07-11 13:34:40 +000011746 " -separator SEP set output column separator. Default: '|'\n"
drha90d84f2018-04-18 15:21:13 +000011747#ifdef SQLITE_ENABLE_SORTER_REFERENCES
11748 " -sorterref SIZE sorter references threshold size\n"
11749#endif
drh2ce15c32017-07-11 13:34:40 +000011750 " -stats print memory stats before each finalize\n"
drh30c54a02020-05-28 23:49:50 +000011751 " -table set output mode to 'table'\n"
drh2fa78182020-10-31 18:58:37 +000011752 " -tabs set output mode to 'tabs'\n"
drh2ce15c32017-07-11 13:34:40 +000011753 " -version show SQLite version\n"
11754 " -vfs NAME use NAME as the default VFS\n"
11755#ifdef SQLITE_ENABLE_VFSTRACE
11756 " -vfstrace enable tracing of all VFS calls\n"
11757#endif
drh3baed312018-03-08 18:14:41 +000011758#ifdef SQLITE_HAVE_ZLIB
11759 " -zip open the file as a ZIP Archive\n"
11760#endif
drh2ce15c32017-07-11 13:34:40 +000011761;
11762static void usage(int showDetail){
11763 utf8_printf(stderr,
11764 "Usage: %s [OPTIONS] FILENAME [SQL]\n"
11765 "FILENAME is the name of an SQLite database. A new database is created\n"
11766 "if the file does not previously exist.\n", Argv0);
11767 if( showDetail ){
11768 utf8_printf(stderr, "OPTIONS include:\n%s", zOptions);
11769 }else{
11770 raw_printf(stderr, "Use the -help option for additional information\n");
11771 }
11772 exit(1);
11773}
11774
11775/*
drhe7df8922018-04-18 10:44:58 +000011776** Internal check: Verify that the SQLite is uninitialized. Print a
11777** error message if it is initialized.
11778*/
11779static void verify_uninitialized(void){
11780 if( sqlite3_config(-1)==SQLITE_MISUSE ){
drh8e02a182018-05-30 07:24:41 +000011781 utf8_printf(stdout, "WARNING: attempt to configure SQLite after"
drhe7df8922018-04-18 10:44:58 +000011782 " initialization.\n");
11783 }
11784}
11785
11786/*
drh2ce15c32017-07-11 13:34:40 +000011787** Initialize the state information in data
11788*/
11789static void main_init(ShellState *data) {
11790 memset(data, 0, sizeof(*data));
11791 data->normalMode = data->cMode = data->mode = MODE_List;
11792 data->autoExplain = 1;
drh37407122021-07-23 18:43:58 +000011793 data->pAuxDb = &data->aAuxDb[0];
drh2ce15c32017-07-11 13:34:40 +000011794 memcpy(data->colSeparator,SEP_Column, 2);
11795 memcpy(data->rowSeparator,SEP_Row, 2);
11796 data->showHeader = 0;
11797 data->shellFlgs = SHFLG_Lookaside;
drhe7df8922018-04-18 10:44:58 +000011798 verify_uninitialized();
drh2ce15c32017-07-11 13:34:40 +000011799 sqlite3_config(SQLITE_CONFIG_URI, 1);
11800 sqlite3_config(SQLITE_CONFIG_LOG, shellLog, data);
11801 sqlite3_config(SQLITE_CONFIG_MULTITHREAD);
11802 sqlite3_snprintf(sizeof(mainPrompt), mainPrompt,"sqlite> ");
11803 sqlite3_snprintf(sizeof(continuePrompt), continuePrompt," ...> ");
11804}
11805
11806/*
11807** Output text to the console in a font that attracts extra attention.
11808*/
11809#ifdef _WIN32
11810static void printBold(const char *zText){
mistachkin43e86272020-04-09 15:31:22 +000011811#if !SQLITE_OS_WINRT
drh2ce15c32017-07-11 13:34:40 +000011812 HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE);
11813 CONSOLE_SCREEN_BUFFER_INFO defaultScreenInfo;
11814 GetConsoleScreenBufferInfo(out, &defaultScreenInfo);
11815 SetConsoleTextAttribute(out,
11816 FOREGROUND_RED|FOREGROUND_INTENSITY
11817 );
mistachkin43e86272020-04-09 15:31:22 +000011818#endif
drh2ce15c32017-07-11 13:34:40 +000011819 printf("%s", zText);
mistachkin43e86272020-04-09 15:31:22 +000011820#if !SQLITE_OS_WINRT
drh2ce15c32017-07-11 13:34:40 +000011821 SetConsoleTextAttribute(out, defaultScreenInfo.wAttributes);
mistachkin43e86272020-04-09 15:31:22 +000011822#endif
drh2ce15c32017-07-11 13:34:40 +000011823}
11824#else
11825static void printBold(const char *zText){
11826 printf("\033[1m%s\033[0m", zText);
11827}
11828#endif
11829
11830/*
11831** Get the argument to an --option. Throw an error and die if no argument
11832** is available.
11833*/
11834static char *cmdline_option_value(int argc, char **argv, int i){
11835 if( i==argc ){
11836 utf8_printf(stderr, "%s: Error: missing argument to %s\n",
11837 argv[0], argv[argc-1]);
11838 exit(1);
11839 }
11840 return argv[i];
11841}
11842
11843#ifndef SQLITE_SHELL_IS_UTF8
dan39b6bd52021-03-04 18:31:07 +000011844# if (defined(_WIN32) || defined(WIN32)) \
11845 && (defined(_MSC_VER) || (defined(UNICODE) && defined(__GNUC__)))
drh2ce15c32017-07-11 13:34:40 +000011846# define SQLITE_SHELL_IS_UTF8 (0)
11847# else
11848# define SQLITE_SHELL_IS_UTF8 (1)
11849# endif
11850#endif
11851
11852#if SQLITE_SHELL_IS_UTF8
11853int SQLITE_CDECL main(int argc, char **argv){
11854#else
11855int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
11856 char **argv;
11857#endif
larrybrfa5dfa82022-05-07 03:53:14 +000011858#ifdef SQLITE_DEBUG
11859 sqlite3_uint64 mem_main_enter = sqlite3_memory_used();
11860#endif
drh2ce15c32017-07-11 13:34:40 +000011861 char *zErrMsg = 0;
11862 ShellState data;
11863 const char *zInitFile = 0;
11864 int i;
11865 int rc = 0;
11866 int warnInmemoryDb = 0;
11867 int readStdin = 1;
11868 int nCmd = 0;
11869 char **azCmd = 0;
dan16a47422018-04-18 09:16:11 +000011870 const char *zVfs = 0; /* Value of -vfs command-line option */
drh1f22f622018-05-17 13:29:14 +000011871#if !SQLITE_SHELL_IS_UTF8
11872 char **argvToFree = 0;
11873 int argcToFree = 0;
11874#endif
drh2ce15c32017-07-11 13:34:40 +000011875
11876 setBinaryMode(stdin, 0);
11877 setvbuf(stderr, 0, _IONBF, 0); /* Make sure stderr is unbuffered */
11878 stdin_is_interactive = isatty(0);
11879 stdout_is_console = isatty(1);
11880
mistachkin1e8487d2018-07-22 06:25:35 +000011881#if !defined(_WIN32_WCE)
11882 if( getenv("SQLITE_DEBUG_BREAK") ){
11883 if( isatty(0) && isatty(2) ){
11884 fprintf(stderr,
11885 "attach debugger to process %d and press any key to continue.\n",
11886 GETPID());
11887 fgetc(stdin);
11888 }else{
11889#if defined(_WIN32) || defined(WIN32)
mistachkin43e86272020-04-09 15:31:22 +000011890#if SQLITE_OS_WINRT
11891 __debugbreak();
11892#else
mistachkin1e8487d2018-07-22 06:25:35 +000011893 DebugBreak();
mistachkin43e86272020-04-09 15:31:22 +000011894#endif
mistachkin1e8487d2018-07-22 06:25:35 +000011895#elif defined(SIGTRAP)
11896 raise(SIGTRAP);
11897#endif
11898 }
11899 }
11900#endif
11901
drh2ce15c32017-07-11 13:34:40 +000011902#if USE_SYSTEM_SQLITE+0!=1
drhb3c45232017-08-28 14:33:27 +000011903 if( strncmp(sqlite3_sourceid(),SQLITE_SOURCE_ID,60)!=0 ){
drh2ce15c32017-07-11 13:34:40 +000011904 utf8_printf(stderr, "SQLite header and source version mismatch\n%s\n%s\n",
11905 sqlite3_sourceid(), SQLITE_SOURCE_ID);
11906 exit(1);
11907 }
11908#endif
11909 main_init(&data);
drh501ea052018-02-15 01:03:37 +000011910
11911 /* On Windows, we must translate command-line arguments into UTF-8.
11912 ** The SQLite memory allocator subsystem has to be enabled in order to
11913 ** do this. But we want to run an sqlite3_shutdown() afterwards so that
11914 ** subsequent sqlite3_config() calls will work. So copy all results into
11915 ** memory that does not come from the SQLite memory allocator.
11916 */
drh4b18c1d2018-02-04 20:33:13 +000011917#if !SQLITE_SHELL_IS_UTF8
drh501ea052018-02-15 01:03:37 +000011918 sqlite3_initialize();
drh1f22f622018-05-17 13:29:14 +000011919 argvToFree = malloc(sizeof(argv[0])*argc*2);
drhe3e25652021-12-16 13:29:28 +000011920 shell_check_oom(argvToFree);
drh1f22f622018-05-17 13:29:14 +000011921 argcToFree = argc;
11922 argv = argvToFree + argc;
drh2ce15c32017-07-11 13:34:40 +000011923 for(i=0; i<argc; i++){
drh501ea052018-02-15 01:03:37 +000011924 char *z = sqlite3_win32_unicode_to_utf8(wargv[i]);
11925 int n;
drhe3e25652021-12-16 13:29:28 +000011926 shell_check_oom(z);
drh501ea052018-02-15 01:03:37 +000011927 n = (int)strlen(z);
11928 argv[i] = malloc( n+1 );
drhe3e25652021-12-16 13:29:28 +000011929 shell_check_oom(argv[i]);
drh501ea052018-02-15 01:03:37 +000011930 memcpy(argv[i], z, n+1);
drh1f22f622018-05-17 13:29:14 +000011931 argvToFree[i] = argv[i];
drh501ea052018-02-15 01:03:37 +000011932 sqlite3_free(z);
drh2ce15c32017-07-11 13:34:40 +000011933 }
drh501ea052018-02-15 01:03:37 +000011934 sqlite3_shutdown();
drh2ce15c32017-07-11 13:34:40 +000011935#endif
drh501ea052018-02-15 01:03:37 +000011936
drh2ce15c32017-07-11 13:34:40 +000011937 assert( argc>=1 && argv && argv[0] );
11938 Argv0 = argv[0];
11939
11940 /* Make sure we have a valid signal handler early, before anything
11941 ** else is done.
11942 */
11943#ifdef SIGINT
11944 signal(SIGINT, interrupt_handler);
mistachkinb4bab902017-10-27 17:09:44 +000011945#elif (defined(_WIN32) || defined(WIN32)) && !defined(_WIN32_WCE)
11946 SetConsoleCtrlHandler(ConsoleCtrlHandler, TRUE);
drh2ce15c32017-07-11 13:34:40 +000011947#endif
11948
11949#ifdef SQLITE_SHELL_DBNAME_PROC
11950 {
11951 /* If the SQLITE_SHELL_DBNAME_PROC macro is defined, then it is the name
11952 ** of a C-function that will provide the name of the database file. Use
11953 ** this compile-time option to embed this shell program in larger
11954 ** applications. */
11955 extern void SQLITE_SHELL_DBNAME_PROC(const char**);
drh37407122021-07-23 18:43:58 +000011956 SQLITE_SHELL_DBNAME_PROC(&data.pAuxDb->zDbFilename);
drh2ce15c32017-07-11 13:34:40 +000011957 warnInmemoryDb = 0;
11958 }
11959#endif
11960
11961 /* Do an initial pass through the command-line argument to locate
11962 ** the name of the database file, the name of the initialization file,
11963 ** the size of the alternative malloc heap,
11964 ** and the first command to execute.
11965 */
drhe7df8922018-04-18 10:44:58 +000011966 verify_uninitialized();
drh2ce15c32017-07-11 13:34:40 +000011967 for(i=1; i<argc; i++){
11968 char *z;
11969 z = argv[i];
11970 if( z[0]!='-' ){
drh37407122021-07-23 18:43:58 +000011971 if( data.aAuxDb->zDbFilename==0 ){
11972 data.aAuxDb->zDbFilename = z;
drh2ce15c32017-07-11 13:34:40 +000011973 }else{
11974 /* Excesss arguments are interpreted as SQL (or dot-commands) and
11975 ** mean that nothing is read from stdin */
11976 readStdin = 0;
11977 nCmd++;
11978 azCmd = realloc(azCmd, sizeof(azCmd[0])*nCmd);
drhe3e25652021-12-16 13:29:28 +000011979 shell_check_oom(azCmd);
drh2ce15c32017-07-11 13:34:40 +000011980 azCmd[nCmd-1] = z;
11981 }
11982 }
11983 if( z[1]=='-' ) z++;
11984 if( strcmp(z,"-separator")==0
11985 || strcmp(z,"-nullvalue")==0
11986 || strcmp(z,"-newline")==0
11987 || strcmp(z,"-cmd")==0
11988 ){
11989 (void)cmdline_option_value(argc, argv, ++i);
11990 }else if( strcmp(z,"-init")==0 ){
11991 zInitFile = cmdline_option_value(argc, argv, ++i);
11992 }else if( strcmp(z,"-batch")==0 ){
11993 /* Need to check for batch mode here to so we can avoid printing
11994 ** informational messages (like from process_sqliterc) before
11995 ** we do the actual processing of arguments later in a second pass.
11996 */
11997 stdin_is_interactive = 0;
11998 }else if( strcmp(z,"-heap")==0 ){
11999#if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5)
12000 const char *zSize;
12001 sqlite3_int64 szHeap;
12002
12003 zSize = cmdline_option_value(argc, argv, ++i);
12004 szHeap = integerValue(zSize);
12005 if( szHeap>0x7fff0000 ) szHeap = 0x7fff0000;
12006 sqlite3_config(SQLITE_CONFIG_HEAP, malloc((int)szHeap), (int)szHeap, 64);
12007#else
12008 (void)cmdline_option_value(argc, argv, ++i);
12009#endif
drh2ce15c32017-07-11 13:34:40 +000012010 }else if( strcmp(z,"-pagecache")==0 ){
drhf573b4f2020-09-28 13:34:05 +000012011 sqlite3_int64 n, sz;
12012 sz = integerValue(cmdline_option_value(argc,argv,++i));
drh2ce15c32017-07-11 13:34:40 +000012013 if( sz>70000 ) sz = 70000;
12014 if( sz<0 ) sz = 0;
drhf573b4f2020-09-28 13:34:05 +000012015 n = integerValue(cmdline_option_value(argc,argv,++i));
12016 if( sz>0 && n>0 && 0xffffffffffffLL/sz<n ){
12017 n = 0xffffffffffffLL/sz;
12018 }
drh2ce15c32017-07-11 13:34:40 +000012019 sqlite3_config(SQLITE_CONFIG_PAGECACHE,
12020 (n>0 && sz>0) ? malloc(n*sz) : 0, sz, n);
12021 data.shellFlgs |= SHFLG_Pagecache;
12022 }else if( strcmp(z,"-lookaside")==0 ){
12023 int n, sz;
12024 sz = (int)integerValue(cmdline_option_value(argc,argv,++i));
12025 if( sz<0 ) sz = 0;
12026 n = (int)integerValue(cmdline_option_value(argc,argv,++i));
12027 if( n<0 ) n = 0;
12028 sqlite3_config(SQLITE_CONFIG_LOOKASIDE, sz, n);
12029 if( sz*n==0 ) data.shellFlgs &= ~SHFLG_Lookaside;
drhaf6d1af2021-08-09 17:37:58 +000012030 }else if( strcmp(z,"-threadsafe")==0 ){
drh9d16fb12021-08-09 17:45:00 +000012031 int n;
12032 n = (int)integerValue(cmdline_option_value(argc,argv,++i));
12033 switch( n ){
drhaf6d1af2021-08-09 17:37:58 +000012034 case 0: sqlite3_config(SQLITE_CONFIG_SINGLETHREAD); break;
12035 case 2: sqlite3_config(SQLITE_CONFIG_MULTITHREAD); break;
12036 default: sqlite3_config(SQLITE_CONFIG_SERIALIZED); break;
12037 }
drh2ce15c32017-07-11 13:34:40 +000012038#ifdef SQLITE_ENABLE_VFSTRACE
12039 }else if( strcmp(z,"-vfstrace")==0 ){
12040 extern int vfstrace_register(
12041 const char *zTraceName,
12042 const char *zOldVfsName,
12043 int (*xOut)(const char*,void*),
12044 void *pOutArg,
12045 int makeDefault
12046 );
12047 vfstrace_register("trace",0,(int(*)(const char*,void*))fputs,stderr,1);
12048#endif
12049#ifdef SQLITE_ENABLE_MULTIPLEX
12050 }else if( strcmp(z,"-multiplex")==0 ){
12051 extern int sqlite3_multiple_initialize(const char*,int);
12052 sqlite3_multiplex_initialize(0, 1);
12053#endif
12054 }else if( strcmp(z,"-mmap")==0 ){
12055 sqlite3_int64 sz = integerValue(cmdline_option_value(argc,argv,++i));
12056 sqlite3_config(SQLITE_CONFIG_MMAP_SIZE, sz, sz);
drha90d84f2018-04-18 15:21:13 +000012057#ifdef SQLITE_ENABLE_SORTER_REFERENCES
12058 }else if( strcmp(z,"-sorterref")==0 ){
12059 sqlite3_int64 sz = integerValue(cmdline_option_value(argc,argv,++i));
12060 sqlite3_config(SQLITE_CONFIG_SORTERREF_SIZE, (int)sz);
12061#endif
drh2ce15c32017-07-11 13:34:40 +000012062 }else if( strcmp(z,"-vfs")==0 ){
dan16a47422018-04-18 09:16:11 +000012063 zVfs = cmdline_option_value(argc, argv, ++i);
drh3baed312018-03-08 18:14:41 +000012064#ifdef SQLITE_HAVE_ZLIB
drh8682e122018-01-07 20:38:10 +000012065 }else if( strcmp(z,"-zip")==0 ){
12066 data.openMode = SHELL_OPEN_ZIPFILE;
12067#endif
12068 }else if( strcmp(z,"-append")==0 ){
12069 data.openMode = SHELL_OPEN_APPENDVFS;
drh8d889af2021-05-08 17:18:23 +000012070#ifndef SQLITE_OMIT_DESERIALIZE
drh60f34ae2018-10-30 13:19:49 +000012071 }else if( strcmp(z,"-deserialize")==0 ){
12072 data.openMode = SHELL_OPEN_DESERIALIZE;
drh6ca64482019-01-22 16:06:20 +000012073 }else if( strcmp(z,"-maxsize")==0 && i+1<argc ){
12074 data.szMax = integerValue(argv[++i]);
drha751f392018-10-30 15:31:22 +000012075#endif
drhee269a62018-02-14 23:27:43 +000012076 }else if( strcmp(z,"-readonly")==0 ){
12077 data.openMode = SHELL_OPEN_READONLY;
drh0933aad2019-11-18 17:46:38 +000012078 }else if( strcmp(z,"-nofollow")==0 ){
12079 data.openFlags = SQLITE_OPEN_NOFOLLOW;
drhda57d962018-03-05 19:34:05 +000012080#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
drh93b77312018-03-05 20:20:22 +000012081 }else if( strncmp(z, "-A",2)==0 ){
drhda57d962018-03-05 19:34:05 +000012082 /* All remaining command-line arguments are passed to the ".archive"
12083 ** command, so ignore them */
12084 break;
12085#endif
drh50b910a2019-01-21 14:55:03 +000012086 }else if( strcmp(z, "-memtrace")==0 ){
12087 sqlite3MemTraceActivate(stderr);
drhb7c46aa2020-11-25 13:59:47 +000012088 }else if( strcmp(z,"-bail")==0 ){
12089 bail_on_error = 1;
drhb97e2ad2021-08-26 18:31:39 +000012090 }else if( strcmp(z,"-nonce")==0 ){
12091 free(data.zNonce);
12092 data.zNonce = strdup(argv[++i]);
12093 }else if( strcmp(z,"-safe")==0 ){
12094 /* no-op - catch this on the second pass */
drh2ce15c32017-07-11 13:34:40 +000012095 }
12096 }
drhe7df8922018-04-18 10:44:58 +000012097 verify_uninitialized();
12098
dan16a47422018-04-18 09:16:11 +000012099
drhd11b8f62018-04-25 13:27:07 +000012100#ifdef SQLITE_SHELL_INIT_PROC
12101 {
12102 /* If the SQLITE_SHELL_INIT_PROC macro is defined, then it is the name
12103 ** of a C-function that will perform initialization actions on SQLite that
12104 ** occur just before or after sqlite3_initialize(). Use this compile-time
12105 ** option to embed this shell program in larger applications. */
12106 extern void SQLITE_SHELL_INIT_PROC(void);
12107 SQLITE_SHELL_INIT_PROC();
12108 }
12109#else
dan16a47422018-04-18 09:16:11 +000012110 /* All the sqlite3_config() calls have now been made. So it is safe
12111 ** to call sqlite3_initialize() and process any command line -vfs option. */
12112 sqlite3_initialize();
drhd11b8f62018-04-25 13:27:07 +000012113#endif
12114
dan16a47422018-04-18 09:16:11 +000012115 if( zVfs ){
12116 sqlite3_vfs *pVfs = sqlite3_vfs_find(zVfs);
12117 if( pVfs ){
12118 sqlite3_vfs_register(pVfs, 1);
12119 }else{
12120 utf8_printf(stderr, "no such VFS: \"%s\"\n", argv[i]);
12121 exit(1);
12122 }
12123 }
12124
drh37407122021-07-23 18:43:58 +000012125 if( data.pAuxDb->zDbFilename==0 ){
drh2ce15c32017-07-11 13:34:40 +000012126#ifndef SQLITE_OMIT_MEMORYDB
drh37407122021-07-23 18:43:58 +000012127 data.pAuxDb->zDbFilename = ":memory:";
drh2ce15c32017-07-11 13:34:40 +000012128 warnInmemoryDb = argc==1;
12129#else
12130 utf8_printf(stderr,"%s: Error: no database filename specified\n", Argv0);
12131 return 1;
12132#endif
12133 }
12134 data.out = stdout;
drh8682e122018-01-07 20:38:10 +000012135 sqlite3_appendvfs_init(0,0,0);
drh2ce15c32017-07-11 13:34:40 +000012136
12137 /* Go ahead and open the database file if it already exists. If the
12138 ** file does not exist, delay opening it. This prevents empty database
12139 ** files from being created if a user mistypes the database name argument
12140 ** to the sqlite command-line tool.
12141 */
drh37407122021-07-23 18:43:58 +000012142 if( access(data.pAuxDb->zDbFilename, 0)==0 ){
drh2ce15c32017-07-11 13:34:40 +000012143 open_db(&data, 0);
12144 }
12145
12146 /* Process the initialization file if there is one. If no -init option
12147 ** is given on the command line, look for a file named ~/.sqliterc and
12148 ** try to process it.
12149 */
12150 process_sqliterc(&data,zInitFile);
12151
12152 /* Make a second pass through the command-line argument and set
12153 ** options. This second pass is delayed until after the initialization
12154 ** file is processed so that the command-line arguments will override
12155 ** settings in the initialization file.
12156 */
12157 for(i=1; i<argc; i++){
12158 char *z = argv[i];
12159 if( z[0]!='-' ) continue;
12160 if( z[1]=='-' ){ z++; }
12161 if( strcmp(z,"-init")==0 ){
12162 i++;
12163 }else if( strcmp(z,"-html")==0 ){
12164 data.mode = MODE_Html;
12165 }else if( strcmp(z,"-list")==0 ){
12166 data.mode = MODE_List;
12167 }else if( strcmp(z,"-quote")==0 ){
12168 data.mode = MODE_Quote;
drh9191c702020-08-17 09:11:21 +000012169 sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator, SEP_Comma);
12170 sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator, SEP_Row);
drh2ce15c32017-07-11 13:34:40 +000012171 }else if( strcmp(z,"-line")==0 ){
12172 data.mode = MODE_Line;
12173 }else if( strcmp(z,"-column")==0 ){
12174 data.mode = MODE_Column;
drh30c54a02020-05-28 23:49:50 +000012175 }else if( strcmp(z,"-json")==0 ){
12176 data.mode = MODE_Json;
12177 }else if( strcmp(z,"-markdown")==0 ){
12178 data.mode = MODE_Markdown;
12179 }else if( strcmp(z,"-table")==0 ){
12180 data.mode = MODE_Table;
drh0908e382020-06-04 18:05:39 +000012181 }else if( strcmp(z,"-box")==0 ){
12182 data.mode = MODE_Box;
drh2ce15c32017-07-11 13:34:40 +000012183 }else if( strcmp(z,"-csv")==0 ){
12184 data.mode = MODE_Csv;
12185 memcpy(data.colSeparator,",",2);
drh3baed312018-03-08 18:14:41 +000012186#ifdef SQLITE_HAVE_ZLIB
drh1fa6d9f2018-01-06 21:46:01 +000012187 }else if( strcmp(z,"-zip")==0 ){
12188 data.openMode = SHELL_OPEN_ZIPFILE;
12189#endif
12190 }else if( strcmp(z,"-append")==0 ){
12191 data.openMode = SHELL_OPEN_APPENDVFS;
drh8d889af2021-05-08 17:18:23 +000012192#ifndef SQLITE_OMIT_DESERIALIZE
drh60f34ae2018-10-30 13:19:49 +000012193 }else if( strcmp(z,"-deserialize")==0 ){
12194 data.openMode = SHELL_OPEN_DESERIALIZE;
drh6ca64482019-01-22 16:06:20 +000012195 }else if( strcmp(z,"-maxsize")==0 && i+1<argc ){
12196 data.szMax = integerValue(argv[++i]);
drha751f392018-10-30 15:31:22 +000012197#endif
drh4aafe592018-03-23 16:08:30 +000012198 }else if( strcmp(z,"-readonly")==0 ){
12199 data.openMode = SHELL_OPEN_READONLY;
drh0933aad2019-11-18 17:46:38 +000012200 }else if( strcmp(z,"-nofollow")==0 ){
12201 data.openFlags |= SQLITE_OPEN_NOFOLLOW;
drh2ce15c32017-07-11 13:34:40 +000012202 }else if( strcmp(z,"-ascii")==0 ){
12203 data.mode = MODE_Ascii;
drh2fa78182020-10-31 18:58:37 +000012204 sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator, SEP_Unit);
12205 sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator, SEP_Record);
12206 }else if( strcmp(z,"-tabs")==0 ){
12207 data.mode = MODE_List;
12208 sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator, SEP_Tab);
12209 sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator, SEP_Row);
drh2ce15c32017-07-11 13:34:40 +000012210 }else if( strcmp(z,"-separator")==0 ){
12211 sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator,
12212 "%s",cmdline_option_value(argc,argv,++i));
12213 }else if( strcmp(z,"-newline")==0 ){
12214 sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator,
12215 "%s",cmdline_option_value(argc,argv,++i));
12216 }else if( strcmp(z,"-nullvalue")==0 ){
12217 sqlite3_snprintf(sizeof(data.nullValue), data.nullValue,
12218 "%s",cmdline_option_value(argc,argv,++i));
12219 }else if( strcmp(z,"-header")==0 ){
12220 data.showHeader = 1;
larrybrae509122021-09-10 01:45:20 +000012221 ShellSetFlag(&data, SHFLG_HeaderSet);
12222 }else if( strcmp(z,"-noheader")==0 ){
drh2ce15c32017-07-11 13:34:40 +000012223 data.showHeader = 0;
larrybrae509122021-09-10 01:45:20 +000012224 ShellSetFlag(&data, SHFLG_HeaderSet);
drh2ce15c32017-07-11 13:34:40 +000012225 }else if( strcmp(z,"-echo")==0 ){
12226 ShellSetFlag(&data, SHFLG_Echo);
12227 }else if( strcmp(z,"-eqp")==0 ){
drhada70452017-12-21 21:02:27 +000012228 data.autoEQP = AUTOEQP_on;
drh2ce15c32017-07-11 13:34:40 +000012229 }else if( strcmp(z,"-eqpfull")==0 ){
drhada70452017-12-21 21:02:27 +000012230 data.autoEQP = AUTOEQP_full;
drh2ce15c32017-07-11 13:34:40 +000012231 }else if( strcmp(z,"-stats")==0 ){
12232 data.statsOn = 1;
12233 }else if( strcmp(z,"-scanstats")==0 ){
12234 data.scanstatsOn = 1;
12235 }else if( strcmp(z,"-backslash")==0 ){
12236 /* Undocumented command-line option: -backslash
12237 ** Causes C-style backslash escapes to be evaluated in SQL statements
12238 ** prior to sending the SQL into SQLite. Useful for injecting
12239 ** crazy bytes in the middle of SQL statements for testing and debugging.
12240 */
12241 ShellSetFlag(&data, SHFLG_Backslash);
12242 }else if( strcmp(z,"-bail")==0 ){
drhb7c46aa2020-11-25 13:59:47 +000012243 /* No-op. The bail_on_error flag should already be set. */
drh2ce15c32017-07-11 13:34:40 +000012244 }else if( strcmp(z,"-version")==0 ){
12245 printf("%s %s\n", sqlite3_libversion(), sqlite3_sourceid());
12246 return 0;
12247 }else if( strcmp(z,"-interactive")==0 ){
12248 stdin_is_interactive = 1;
12249 }else if( strcmp(z,"-batch")==0 ){
12250 stdin_is_interactive = 0;
12251 }else if( strcmp(z,"-heap")==0 ){
12252 i++;
drh2ce15c32017-07-11 13:34:40 +000012253 }else if( strcmp(z,"-pagecache")==0 ){
12254 i+=2;
12255 }else if( strcmp(z,"-lookaside")==0 ){
12256 i+=2;
drhaf6d1af2021-08-09 17:37:58 +000012257 }else if( strcmp(z,"-threadsafe")==0 ){
12258 i+=2;
drhb97e2ad2021-08-26 18:31:39 +000012259 }else if( strcmp(z,"-nonce")==0 ){
12260 i += 2;
drh2ce15c32017-07-11 13:34:40 +000012261 }else if( strcmp(z,"-mmap")==0 ){
12262 i++;
drh50b910a2019-01-21 14:55:03 +000012263 }else if( strcmp(z,"-memtrace")==0 ){
12264 i++;
drha90d84f2018-04-18 15:21:13 +000012265#ifdef SQLITE_ENABLE_SORTER_REFERENCES
12266 }else if( strcmp(z,"-sorterref")==0 ){
12267 i++;
12268#endif
drh2ce15c32017-07-11 13:34:40 +000012269 }else if( strcmp(z,"-vfs")==0 ){
12270 i++;
12271#ifdef SQLITE_ENABLE_VFSTRACE
12272 }else if( strcmp(z,"-vfstrace")==0 ){
12273 i++;
12274#endif
12275#ifdef SQLITE_ENABLE_MULTIPLEX
12276 }else if( strcmp(z,"-multiplex")==0 ){
12277 i++;
12278#endif
12279 }else if( strcmp(z,"-help")==0 ){
12280 usage(1);
12281 }else if( strcmp(z,"-cmd")==0 ){
12282 /* Run commands that follow -cmd first and separately from commands
12283 ** that simply appear on the command-line. This seems goofy. It would
12284 ** be better if all commands ran in the order that they appear. But
12285 ** we retain the goofy behavior for historical compatibility. */
12286 if( i==argc-1 ) break;
12287 z = cmdline_option_value(argc,argv,++i);
12288 if( z[0]=='.' ){
12289 rc = do_meta_command(z, &data);
12290 if( rc && bail_on_error ) return rc==2 ? 0 : rc;
12291 }else{
12292 open_db(&data, 0);
drha10b9992018-03-09 15:24:33 +000012293 rc = shell_exec(&data, z, &zErrMsg);
drh2ce15c32017-07-11 13:34:40 +000012294 if( zErrMsg!=0 ){
12295 utf8_printf(stderr,"Error: %s\n", zErrMsg);
12296 if( bail_on_error ) return rc!=0 ? rc : 1;
12297 }else if( rc!=0 ){
12298 utf8_printf(stderr,"Error: unable to process SQL \"%s\"\n", z);
12299 if( bail_on_error ) return rc;
12300 }
12301 }
drhda57d962018-03-05 19:34:05 +000012302#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
drh93b77312018-03-05 20:20:22 +000012303 }else if( strncmp(z, "-A", 2)==0 ){
drhda57d962018-03-05 19:34:05 +000012304 if( nCmd>0 ){
12305 utf8_printf(stderr, "Error: cannot mix regular SQL or dot-commands"
12306 " with \"%s\"\n", z);
12307 return 1;
12308 }
drhbe4ccb22018-05-17 20:04:24 +000012309 open_db(&data, OPEN_DB_ZIPFILE);
drh93b77312018-03-05 20:20:22 +000012310 if( z[2] ){
12311 argv[i] = &z[2];
drhd0f9cdc2018-05-17 14:09:06 +000012312 arDotCommand(&data, 1, argv+(i-1), argc-(i-1));
drh93b77312018-03-05 20:20:22 +000012313 }else{
drhd0f9cdc2018-05-17 14:09:06 +000012314 arDotCommand(&data, 1, argv+i, argc-i);
drh93b77312018-03-05 20:20:22 +000012315 }
drhda57d962018-03-05 19:34:05 +000012316 readStdin = 0;
12317 break;
12318#endif
drhb97e2ad2021-08-26 18:31:39 +000012319 }else if( strcmp(z,"-safe")==0 ){
12320 data.bSafeMode = data.bSafeModePersist = 1;
drh2ce15c32017-07-11 13:34:40 +000012321 }else{
12322 utf8_printf(stderr,"%s: Error: unknown option: %s\n", Argv0, z);
12323 raw_printf(stderr,"Use -help for a list of options.\n");
12324 return 1;
12325 }
12326 data.cMode = data.mode;
12327 }
12328
12329 if( !readStdin ){
12330 /* Run all arguments that do not begin with '-' as if they were separate
12331 ** command-line inputs, except for the argToSkip argument which contains
12332 ** the database filename.
12333 */
12334 for(i=0; i<nCmd; i++){
12335 if( azCmd[i][0]=='.' ){
12336 rc = do_meta_command(azCmd[i], &data);
danaff1a572020-11-17 21:09:56 +000012337 if( rc ){
12338 free(azCmd);
12339 return rc==2 ? 0 : rc;
12340 }
drh2ce15c32017-07-11 13:34:40 +000012341 }else{
12342 open_db(&data, 0);
drha10b9992018-03-09 15:24:33 +000012343 rc = shell_exec(&data, azCmd[i], &zErrMsg);
danaff1a572020-11-17 21:09:56 +000012344 if( zErrMsg || rc ){
12345 if( zErrMsg!=0 ){
12346 utf8_printf(stderr,"Error: %s\n", zErrMsg);
12347 }else{
12348 utf8_printf(stderr,"Error: unable to process SQL: %s\n", azCmd[i]);
12349 }
12350 sqlite3_free(zErrMsg);
12351 free(azCmd);
drh2ce15c32017-07-11 13:34:40 +000012352 return rc!=0 ? rc : 1;
drh2ce15c32017-07-11 13:34:40 +000012353 }
12354 }
12355 }
drh2ce15c32017-07-11 13:34:40 +000012356 }else{
12357 /* Run commands received from standard input
12358 */
12359 if( stdin_is_interactive ){
12360 char *zHome;
drha9e4be32018-10-10 18:56:40 +000012361 char *zHistory;
drh2ce15c32017-07-11 13:34:40 +000012362 int nHistory;
12363 printf(
12364 "SQLite version %s %.19s\n" /*extra-version-info*/
12365 "Enter \".help\" for usage hints.\n",
12366 sqlite3_libversion(), sqlite3_sourceid()
12367 );
12368 if( warnInmemoryDb ){
12369 printf("Connected to a ");
12370 printBold("transient in-memory database");
12371 printf(".\nUse \".open FILENAME\" to reopen on a "
12372 "persistent database.\n");
12373 }
drha9e4be32018-10-10 18:56:40 +000012374 zHistory = getenv("SQLITE_HISTORY");
12375 if( zHistory ){
12376 zHistory = strdup(zHistory);
12377 }else if( (zHome = find_home_dir(0))!=0 ){
drh2ce15c32017-07-11 13:34:40 +000012378 nHistory = strlen30(zHome) + 20;
12379 if( (zHistory = malloc(nHistory))!=0 ){
12380 sqlite3_snprintf(nHistory, zHistory,"%s/.sqlite_history", zHome);
12381 }
12382 }
12383 if( zHistory ){ shell_read_history(zHistory); }
drh56eb09b2017-07-11 13:59:07 +000012384#if HAVE_READLINE || HAVE_EDITLINE
12385 rl_attempted_completion_function = readline_completion;
12386#elif HAVE_LINENOISE
12387 linenoiseSetCompletionCallback(linenoise_completion);
12388#endif
drh60379d42018-12-13 18:30:01 +000012389 data.in = 0;
12390 rc = process_input(&data);
drh2ce15c32017-07-11 13:34:40 +000012391 if( zHistory ){
drh5a75dd82017-07-18 20:59:40 +000012392 shell_stifle_history(2000);
drh2ce15c32017-07-11 13:34:40 +000012393 shell_write_history(zHistory);
12394 free(zHistory);
12395 }
12396 }else{
drh60379d42018-12-13 18:30:01 +000012397 data.in = stdin;
12398 rc = process_input(&data);
drh2ce15c32017-07-11 13:34:40 +000012399 }
12400 }
danaff1a572020-11-17 21:09:56 +000012401 free(azCmd);
drh2ce15c32017-07-11 13:34:40 +000012402 set_table_name(&data, 0);
12403 if( data.db ){
drh37407122021-07-23 18:43:58 +000012404 session_close_all(&data, -1);
drh9e804032018-05-18 17:11:50 +000012405 close_db(data.db);
drh2ce15c32017-07-11 13:34:40 +000012406 }
drh37407122021-07-23 18:43:58 +000012407 for(i=0; i<ArraySize(data.aAuxDb); i++){
12408 sqlite3_free(data.aAuxDb[i].zFreeOnClose);
12409 if( data.aAuxDb[i].db ){
12410 session_close_all(&data, i);
12411 close_db(data.aAuxDb[i].db);
12412 }
12413 }
drh2ce15c32017-07-11 13:34:40 +000012414 find_home_dir(1);
drh536c3452018-01-11 00:38:39 +000012415 output_reset(&data);
12416 data.doXdgOpen = 0;
drh13c20932018-01-10 21:41:55 +000012417 clearTempFile(&data);
drh2ce15c32017-07-11 13:34:40 +000012418#if !SQLITE_SHELL_IS_UTF8
drh1f22f622018-05-17 13:29:14 +000012419 for(i=0; i<argcToFree; i++) free(argvToFree[i]);
12420 free(argvToFree);
drh2ce15c32017-07-11 13:34:40 +000012421#endif
drh0285d982020-05-29 14:38:43 +000012422 free(data.colWidth);
drhb97e2ad2021-08-26 18:31:39 +000012423 free(data.zNonce);
drh9e804032018-05-18 17:11:50 +000012424 /* Clear the global data structure so that valgrind will detect memory
12425 ** leaks */
12426 memset(&data, 0, sizeof(data));
larrybrfa5dfa82022-05-07 03:53:14 +000012427#ifdef SQLITE_DEBUG
12428 if( sqlite3_memory_used()>mem_main_enter ){
12429 utf8_printf(stderr, "Memory leaked: %u bytes\n",
12430 (unsigned int)(sqlite3_memory_used()-mem_main_enter));
12431 }
12432#endif
drh2ce15c32017-07-11 13:34:40 +000012433 return rc;
12434}