blob: 2758a734432f2df8d278488d16a37404e3e6d307 [file] [log] [blame]
drh2ce15c32017-07-11 13:34:40 +00001/*
2** 2001 September 15
3**
4** The author disclaims copyright to this source code. In place of
5** a legal notice, here is a blessing:
6**
7** May you do good and not evil.
8** May you find forgiveness for yourself and forgive others.
9** May you share freely, never taking more than you give.
10**
11*************************************************************************
12** This file contains code to implement the "sqlite" command line
13** utility for accessing SQLite databases.
14*/
15#if (defined(_WIN32) || defined(WIN32)) && !defined(_CRT_SECURE_NO_WARNINGS)
16/* This needs to come before any includes for MSVC compiler */
17#define _CRT_SECURE_NO_WARNINGS
18#endif
19
20/*
larrybra13c0c72021-07-09 00:12:05 +000021** Optionally #include a user-defined header, whereby compilation options
22** may be set prior to where they take effect, but after platform setup.
23** If SQLITE_CUSTOM_INCLUDE=? is defined, its value names the #include
24** file. Note that this macro has a like effect on sqlite3.c compilation.
25*/
larrybr78138392022-02-12 02:15:37 +000026# define SHELL_STRINGIFY_(f) #f
27# define SHELL_STRINGIFY(f) SHELL_STRINGIFY_(f)
larrybra13c0c72021-07-09 00:12:05 +000028#ifdef SQLITE_CUSTOM_INCLUDE
larrybr78138392022-02-12 02:15:37 +000029# include SHELL_STRINGIFY(SQLITE_CUSTOM_INCLUDE)
larrybra13c0c72021-07-09 00:12:05 +000030#endif
31
32/*
mistachkin43e86272020-04-09 15:31:22 +000033** Determine if we are dealing with WinRT, which provides only a subset of
34** the full Win32 API.
35*/
36#if !defined(SQLITE_OS_WINRT)
37# define SQLITE_OS_WINRT 0
38#endif
39
40/*
drh2ce15c32017-07-11 13:34:40 +000041** Warning pragmas copied from msvc.h in the core.
42*/
43#if defined(_MSC_VER)
44#pragma warning(disable : 4054)
45#pragma warning(disable : 4055)
46#pragma warning(disable : 4100)
47#pragma warning(disable : 4127)
48#pragma warning(disable : 4130)
49#pragma warning(disable : 4152)
50#pragma warning(disable : 4189)
51#pragma warning(disable : 4206)
52#pragma warning(disable : 4210)
53#pragma warning(disable : 4232)
54#pragma warning(disable : 4244)
55#pragma warning(disable : 4305)
56#pragma warning(disable : 4306)
57#pragma warning(disable : 4702)
58#pragma warning(disable : 4706)
59#endif /* defined(_MSC_VER) */
60
61/*
62** No support for loadable extensions in VxWorks.
63*/
64#if (defined(__RTP__) || defined(_WRS_KERNEL)) && !SQLITE_OMIT_LOAD_EXTENSION
65# define SQLITE_OMIT_LOAD_EXTENSION 1
66#endif
67
68/*
69** Enable large-file support for fopen() and friends on unix.
70*/
71#ifndef SQLITE_DISABLE_LFS
72# define _LARGE_FILE 1
73# ifndef _FILE_OFFSET_BITS
74# define _FILE_OFFSET_BITS 64
75# endif
76# define _LARGEFILE_SOURCE 1
77#endif
78
79#include <stdlib.h>
80#include <string.h>
81#include <stdio.h>
82#include <assert.h>
83#include "sqlite3.h"
drh1e506b52018-01-05 21:01:37 +000084typedef sqlite3_int64 i64;
85typedef sqlite3_uint64 u64;
drh1fa6d9f2018-01-06 21:46:01 +000086typedef unsigned char u8;
drh2ce15c32017-07-11 13:34:40 +000087#if SQLITE_USER_AUTHENTICATION
88# include "sqlite3userauth.h"
89#endif
90#include <ctype.h>
91#include <stdarg.h>
92
93#if !defined(_WIN32) && !defined(WIN32)
94# include <signal.h>
95# if !defined(__RTP__) && !defined(_WRS_KERNEL)
96# include <pwd.h>
97# endif
mistachkinacae8c32018-01-05 20:08:46 +000098#endif
mistachkin562f0c82018-01-09 00:28:24 +000099#if (!defined(_WIN32) && !defined(WIN32)) || defined(__MINGW32__)
drh2ce15c32017-07-11 13:34:40 +0000100# include <unistd.h>
mistachkinacae8c32018-01-05 20:08:46 +0000101# include <dirent.h>
mistachkin1e8487d2018-07-22 06:25:35 +0000102# define GETPID getpid
mistachkin562f0c82018-01-09 00:28:24 +0000103# if defined(__MINGW32__)
mistachkinacae8c32018-01-05 20:08:46 +0000104# define DIRENT dirent
mistachkin2f74b3c2018-01-05 20:26:06 +0000105# ifndef S_ISLNK
106# define S_ISLNK(mode) (0)
107# endif
mistachkinacae8c32018-01-05 20:08:46 +0000108# endif
mistachkin1e8487d2018-07-22 06:25:35 +0000109#else
110# define GETPID (int)GetCurrentProcessId
drh2ce15c32017-07-11 13:34:40 +0000111#endif
mistachkindfdfd8c2018-01-04 22:46:08 +0000112#include <sys/types.h>
113#include <sys/stat.h>
drh2ce15c32017-07-11 13:34:40 +0000114
115#if HAVE_READLINE
116# include <readline/readline.h>
117# include <readline/history.h>
118#endif
119
120#if HAVE_EDITLINE
121# include <editline/readline.h>
122#endif
123
124#if HAVE_EDITLINE || HAVE_READLINE
125
126# define shell_add_history(X) add_history(X)
127# define shell_read_history(X) read_history(X)
128# define shell_write_history(X) write_history(X)
129# define shell_stifle_history(X) stifle_history(X)
130# define shell_readline(X) readline(X)
131
132#elif HAVE_LINENOISE
133
134# include "linenoise.h"
135# define shell_add_history(X) linenoiseHistoryAdd(X)
136# define shell_read_history(X) linenoiseHistoryLoad(X)
137# define shell_write_history(X) linenoiseHistorySave(X)
138# define shell_stifle_history(X) linenoiseHistorySetMaxLen(X)
139# define shell_readline(X) linenoise(X)
140
141#else
142
143# define shell_read_history(X)
144# define shell_write_history(X)
145# define shell_stifle_history(X)
146
147# define SHELL_USE_LOCAL_GETLINE 1
148#endif
149
150
151#if defined(_WIN32) || defined(WIN32)
mistachkin43e86272020-04-09 15:31:22 +0000152# if SQLITE_OS_WINRT
153# define SQLITE_OMIT_POPEN 1
154# else
155# include <io.h>
156# include <fcntl.h>
157# define isatty(h) _isatty(h)
158# ifndef access
159# define access(f,m) _access((f),(m))
160# endif
161# ifndef unlink
162# define unlink _unlink
163# endif
164# ifndef strdup
165# define strdup _strdup
166# endif
167# undef popen
168# define popen _popen
169# undef pclose
170# define pclose _pclose
drh2ce15c32017-07-11 13:34:40 +0000171# endif
drh2ce15c32017-07-11 13:34:40 +0000172#else
173 /* Make sure isatty() has a prototype. */
174 extern int isatty(int);
175
176# if !defined(__RTP__) && !defined(_WRS_KERNEL)
177 /* popen and pclose are not C89 functions and so are
178 ** sometimes omitted from the <stdio.h> header */
179 extern FILE *popen(const char*,const char*);
180 extern int pclose(FILE*);
181# else
182# define SQLITE_OMIT_POPEN 1
183# endif
184#endif
185
186#if defined(_WIN32_WCE)
187/* Windows CE (arm-wince-mingw32ce-gcc) does not provide isatty()
188 * thus we always assume that we have a console. That can be
189 * overridden with the -batch command line option.
190 */
191#define isatty(x) 1
192#endif
193
194/* ctype macros that work with signed characters */
195#define IsSpace(X) isspace((unsigned char)X)
196#define IsDigit(X) isdigit((unsigned char)X)
197#define ToLower(X) (char)tolower((unsigned char)X)
198
199#if defined(_WIN32) || defined(WIN32)
mistachkin43e86272020-04-09 15:31:22 +0000200#if SQLITE_OS_WINRT
201#include <intrin.h>
202#endif
drh2ce15c32017-07-11 13:34:40 +0000203#include <windows.h>
204
205/* string conversion routines only needed on Win32 */
206extern char *sqlite3_win32_unicode_to_utf8(LPCWSTR);
207extern char *sqlite3_win32_mbcs_to_utf8_v2(const char *, int);
208extern char *sqlite3_win32_utf8_to_mbcs_v2(const char *, int);
209extern LPWSTR sqlite3_win32_utf8_to_unicode(const char *zText);
210#endif
211
212/* On Windows, we normally run with output mode of TEXT so that \n characters
213** are automatically translated into \r\n. However, this behavior needs
214** to be disabled in some cases (ex: when generating CSV output and when
215** rendering quoted strings that contain \n characters). The following
216** routines take care of that.
217*/
mistachkin43e86272020-04-09 15:31:22 +0000218#if (defined(_WIN32) || defined(WIN32)) && !SQLITE_OS_WINRT
drh2ce15c32017-07-11 13:34:40 +0000219static void setBinaryMode(FILE *file, int isOutput){
220 if( isOutput ) fflush(file);
221 _setmode(_fileno(file), _O_BINARY);
222}
223static void setTextMode(FILE *file, int isOutput){
224 if( isOutput ) fflush(file);
225 _setmode(_fileno(file), _O_TEXT);
226}
227#else
228# define setBinaryMode(X,Y)
229# define setTextMode(X,Y)
230#endif
231
232
233/* True if the timer is enabled */
234static int enableTimer = 0;
235
236/* Return the current wall-clock time */
237static sqlite3_int64 timeOfDay(void){
238 static sqlite3_vfs *clockVfs = 0;
239 sqlite3_int64 t;
240 if( clockVfs==0 ) clockVfs = sqlite3_vfs_find(0);
drha959bf52021-06-15 15:15:40 +0000241 if( clockVfs==0 ) return 0; /* Never actually happens */
drh2ce15c32017-07-11 13:34:40 +0000242 if( clockVfs->iVersion>=2 && clockVfs->xCurrentTimeInt64!=0 ){
243 clockVfs->xCurrentTimeInt64(clockVfs, &t);
244 }else{
245 double r;
246 clockVfs->xCurrentTime(clockVfs, &r);
247 t = (sqlite3_int64)(r*86400000.0);
248 }
249 return t;
250}
251
252#if !defined(_WIN32) && !defined(WIN32) && !defined(__minux)
253#include <sys/time.h>
254#include <sys/resource.h>
255
256/* VxWorks does not support getrusage() as far as we can determine */
257#if defined(_WRS_KERNEL) || defined(__RTP__)
258struct rusage {
259 struct timeval ru_utime; /* user CPU time used */
260 struct timeval ru_stime; /* system CPU time used */
261};
262#define getrusage(A,B) memset(B,0,sizeof(*B))
263#endif
264
265/* Saved resource information for the beginning of an operation */
266static struct rusage sBegin; /* CPU time at start */
267static sqlite3_int64 iBegin; /* Wall-clock time at start */
268
269/*
270** Begin timing an operation
271*/
272static void beginTimer(void){
273 if( enableTimer ){
274 getrusage(RUSAGE_SELF, &sBegin);
275 iBegin = timeOfDay();
276 }
277}
278
279/* Return the difference of two time_structs in seconds */
280static double timeDiff(struct timeval *pStart, struct timeval *pEnd){
281 return (pEnd->tv_usec - pStart->tv_usec)*0.000001 +
282 (double)(pEnd->tv_sec - pStart->tv_sec);
283}
284
285/*
286** Print the timing results.
287*/
288static void endTimer(void){
289 if( enableTimer ){
290 sqlite3_int64 iEnd = timeOfDay();
291 struct rusage sEnd;
292 getrusage(RUSAGE_SELF, &sEnd);
293 printf("Run Time: real %.3f user %f sys %f\n",
294 (iEnd - iBegin)*0.001,
295 timeDiff(&sBegin.ru_utime, &sEnd.ru_utime),
296 timeDiff(&sBegin.ru_stime, &sEnd.ru_stime));
297 }
298}
299
300#define BEGIN_TIMER beginTimer()
301#define END_TIMER endTimer()
302#define HAS_TIMER 1
303
304#elif (defined(_WIN32) || defined(WIN32))
305
306/* Saved resource information for the beginning of an operation */
307static HANDLE hProcess;
308static FILETIME ftKernelBegin;
309static FILETIME ftUserBegin;
310static sqlite3_int64 ftWallBegin;
311typedef BOOL (WINAPI *GETPROCTIMES)(HANDLE, LPFILETIME, LPFILETIME,
312 LPFILETIME, LPFILETIME);
313static GETPROCTIMES getProcessTimesAddr = NULL;
314
315/*
316** Check to see if we have timer support. Return 1 if necessary
317** support found (or found previously).
318*/
319static int hasTimer(void){
320 if( getProcessTimesAddr ){
321 return 1;
322 } else {
mistachkin43e86272020-04-09 15:31:22 +0000323#if !SQLITE_OS_WINRT
drh2ce15c32017-07-11 13:34:40 +0000324 /* GetProcessTimes() isn't supported in WIN95 and some other Windows
325 ** versions. See if the version we are running on has it, and if it
326 ** does, save off a pointer to it and the current process handle.
327 */
328 hProcess = GetCurrentProcess();
329 if( hProcess ){
330 HINSTANCE hinstLib = LoadLibrary(TEXT("Kernel32.dll"));
331 if( NULL != hinstLib ){
332 getProcessTimesAddr =
333 (GETPROCTIMES) GetProcAddress(hinstLib, "GetProcessTimes");
334 if( NULL != getProcessTimesAddr ){
335 return 1;
336 }
337 FreeLibrary(hinstLib);
338 }
339 }
mistachkin43e86272020-04-09 15:31:22 +0000340#endif
drh2ce15c32017-07-11 13:34:40 +0000341 }
342 return 0;
343}
344
345/*
346** Begin timing an operation
347*/
348static void beginTimer(void){
349 if( enableTimer && getProcessTimesAddr ){
350 FILETIME ftCreation, ftExit;
351 getProcessTimesAddr(hProcess,&ftCreation,&ftExit,
352 &ftKernelBegin,&ftUserBegin);
353 ftWallBegin = timeOfDay();
354 }
355}
356
357/* Return the difference of two FILETIME structs in seconds */
358static double timeDiff(FILETIME *pStart, FILETIME *pEnd){
359 sqlite_int64 i64Start = *((sqlite_int64 *) pStart);
360 sqlite_int64 i64End = *((sqlite_int64 *) pEnd);
361 return (double) ((i64End - i64Start) / 10000000.0);
362}
363
364/*
365** Print the timing results.
366*/
367static void endTimer(void){
368 if( enableTimer && getProcessTimesAddr){
369 FILETIME ftCreation, ftExit, ftKernelEnd, ftUserEnd;
370 sqlite3_int64 ftWallEnd = timeOfDay();
371 getProcessTimesAddr(hProcess,&ftCreation,&ftExit,&ftKernelEnd,&ftUserEnd);
372 printf("Run Time: real %.3f user %f sys %f\n",
373 (ftWallEnd - ftWallBegin)*0.001,
374 timeDiff(&ftUserBegin, &ftUserEnd),
375 timeDiff(&ftKernelBegin, &ftKernelEnd));
376 }
377}
378
379#define BEGIN_TIMER beginTimer()
380#define END_TIMER endTimer()
381#define HAS_TIMER hasTimer()
382
383#else
384#define BEGIN_TIMER
385#define END_TIMER
386#define HAS_TIMER 0
387#endif
388
389/*
390** Used to prevent warnings about unused parameters
391*/
392#define UNUSED_PARAMETER(x) (void)(x)
393
394/*
drh5af06982018-01-10 00:53:55 +0000395** Number of elements in an array
396*/
397#define ArraySize(X) (int)(sizeof(X)/sizeof(X[0]))
398
399/*
drh2ce15c32017-07-11 13:34:40 +0000400** If the following flag is set, then command execution stops
401** at an error if we are not interactive.
402*/
403static int bail_on_error = 0;
404
405/*
406** Threat stdin as an interactive input if the following variable
407** is true. Otherwise, assume stdin is connected to a file or pipe.
408*/
409static int stdin_is_interactive = 1;
410
411/*
412** On Windows systems we have to know if standard output is a console
413** in order to translate UTF-8 into MBCS. The following variable is
414** true if translation is required.
415*/
416static int stdout_is_console = 1;
417
418/*
419** The following is the open SQLite database. We make a pointer
420** to this database a static variable so that it can be accessed
421** by the SIGINT handler to interrupt database processing.
422*/
423static sqlite3 *globalDb = 0;
424
425/*
426** True if an interrupt (Control-C) has been received.
427*/
428static volatile int seenInterrupt = 0;
429
430/*
431** This is the name of our program. It is set in main(), used
432** in a number of other places, mostly for error messages.
433*/
434static char *Argv0;
435
436/*
437** Prompt strings. Initialized in main. Settable with
438** .prompt main continue
439*/
440static char mainPrompt[20]; /* First line prompt. default: "sqlite> "*/
441static char continuePrompt[20]; /* Continuation prompt. default: " ...> " */
442
443/*
444** Render output like fprintf(). Except, if the output is going to the
445** console and if this is running on a Windows machine, translate the
446** output from UTF-8 into MBCS.
447*/
448#if defined(_WIN32) || defined(WIN32)
449void utf8_printf(FILE *out, const char *zFormat, ...){
450 va_list ap;
451 va_start(ap, zFormat);
452 if( stdout_is_console && (out==stdout || out==stderr) ){
453 char *z1 = sqlite3_vmprintf(zFormat, ap);
454 char *z2 = sqlite3_win32_utf8_to_mbcs_v2(z1, 0);
455 sqlite3_free(z1);
456 fputs(z2, out);
457 sqlite3_free(z2);
458 }else{
459 vfprintf(out, zFormat, ap);
460 }
461 va_end(ap);
462}
463#elif !defined(utf8_printf)
464# define utf8_printf fprintf
465#endif
466
467/*
468** Render output like fprintf(). This should not be used on anything that
469** includes string formatting (e.g. "%s").
470*/
471#if !defined(raw_printf)
472# define raw_printf fprintf
473#endif
474
drh4b5345c2018-04-24 13:07:40 +0000475/* Indicate out-of-memory and exit. */
476static void shell_out_of_memory(void){
477 raw_printf(stderr,"Error: out of memory\n");
478 exit(1);
479}
480
drhe3e25652021-12-16 13:29:28 +0000481/* Check a pointer to see if it is NULL. If it is NULL, exit with an
482** out-of-memory error.
483*/
484static void shell_check_oom(void *p){
485 if( p==0 ) shell_out_of_memory();
486}
487
drh2ce15c32017-07-11 13:34:40 +0000488/*
489** Write I/O traces to the following stream.
490*/
491#ifdef SQLITE_ENABLE_IOTRACE
492static FILE *iotrace = 0;
493#endif
494
495/*
496** This routine works like printf in that its first argument is a
497** format string and subsequent arguments are values to be substituted
498** in place of % fields. The result of formatting this string
499** is written to iotrace.
500*/
501#ifdef SQLITE_ENABLE_IOTRACE
502static void SQLITE_CDECL iotracePrintf(const char *zFormat, ...){
503 va_list ap;
504 char *z;
505 if( iotrace==0 ) return;
506 va_start(ap, zFormat);
507 z = sqlite3_vmprintf(zFormat, ap);
508 va_end(ap);
509 utf8_printf(iotrace, "%s", z);
510 sqlite3_free(z);
511}
512#endif
513
514/*
515** Output string zUtf to stream pOut as w characters. If w is negative,
516** then right-justify the text. W is the width in UTF-8 characters, not
517** in bytes. This is different from the %*.*s specification in printf
518** since with %*.*s the width is measured in bytes, not characters.
519*/
520static void utf8_width_print(FILE *pOut, int w, const char *zUtf){
521 int i;
522 int n;
523 int aw = w<0 ? -w : w;
drh2ce15c32017-07-11 13:34:40 +0000524 for(i=n=0; zUtf[i]; i++){
525 if( (zUtf[i]&0xc0)!=0x80 ){
526 n++;
527 if( n==aw ){
528 do{ i++; }while( (zUtf[i]&0xc0)==0x80 );
529 break;
530 }
531 }
532 }
533 if( n>=aw ){
534 utf8_printf(pOut, "%.*s", i, zUtf);
535 }else if( w<0 ){
536 utf8_printf(pOut, "%*s%s", aw-n, "", zUtf);
537 }else{
538 utf8_printf(pOut, "%s%*s", zUtf, aw-n, "");
539 }
540}
541
542
543/*
544** Determines if a string is a number of not.
545*/
546static int isNumber(const char *z, int *realnum){
547 if( *z=='-' || *z=='+' ) z++;
548 if( !IsDigit(*z) ){
549 return 0;
550 }
551 z++;
552 if( realnum ) *realnum = 0;
553 while( IsDigit(*z) ){ z++; }
554 if( *z=='.' ){
555 z++;
556 if( !IsDigit(*z) ) return 0;
557 while( IsDigit(*z) ){ z++; }
558 if( realnum ) *realnum = 1;
559 }
560 if( *z=='e' || *z=='E' ){
561 z++;
562 if( *z=='+' || *z=='-' ) z++;
563 if( !IsDigit(*z) ) return 0;
564 while( IsDigit(*z) ){ z++; }
565 if( realnum ) *realnum = 1;
566 }
567 return *z==0;
568}
569
570/*
571** Compute a string length that is limited to what can be stored in
572** lower 30 bits of a 32-bit signed integer.
573*/
574static int strlen30(const char *z){
575 const char *z2 = z;
576 while( *z2 ){ z2++; }
577 return 0x3fffffff & (int)(z2 - z);
578}
579
580/*
581** Return the length of a string in characters. Multibyte UTF8 characters
582** count as a single character.
583*/
584static int strlenChar(const char *z){
585 int n = 0;
586 while( *z ){
587 if( (0xc0&*(z++))!=0x80 ) n++;
588 }
589 return n;
590}
591
592/*
larrybrd96bcc72021-09-17 21:12:47 +0000593** Return open FILE * if zFile exists, can be opened for read
594** and is an ordinary file or a character stream source.
595** Otherwise return 0.
drhbbd620e2020-07-20 23:33:11 +0000596*/
larrybrd96bcc72021-09-17 21:12:47 +0000597static FILE * openChrSource(const char *zFile){
drhbbd620e2020-07-20 23:33:11 +0000598#ifdef _WIN32
larrybrd0007852021-09-13 23:11:46 +0000599 struct _stat x = {0};
larrybrd0007852021-09-13 23:11:46 +0000600# define STAT_CHR_SRC(mode) ((mode & (_S_IFCHR|_S_IFIFO|_S_IFREG))!=0)
larrybrd96bcc72021-09-17 21:12:47 +0000601 /* On Windows, open first, then check the stream nature. This order
602 ** is necessary because _stat() and sibs, when checking a named pipe,
603 ** effectively break the pipe as its supplier sees it. */
604 FILE *rv = fopen(zFile, "rb");
605 if( rv==0 ) return 0;
606 if( _fstat(_fileno(rv), &x) != 0
607 || !STAT_CHR_SRC(x.st_mode)){
608 fclose(rv);
609 rv = 0;
610 }
611 return rv;
drhbbd620e2020-07-20 23:33:11 +0000612#else
larrybrd0007852021-09-13 23:11:46 +0000613 struct stat x = {0};
614 int rc = stat(zFile, &x);
615# define STAT_CHR_SRC(mode) (S_ISREG(mode)||S_ISFIFO(mode)||S_ISCHR(mode))
larrybrd96bcc72021-09-17 21:12:47 +0000616 if( rc!=0 ) return 0;
617 if( STAT_CHR_SRC(x.st_mode) ){
618 return fopen(zFile, "rb");
619 }else{
620 return 0;
621 }
drhbbd620e2020-07-20 23:33:11 +0000622#endif
larrybrd0007852021-09-13 23:11:46 +0000623#undef STAT_CHR_SRC
624}
drhbbd620e2020-07-20 23:33:11 +0000625
626/*
drh2ce15c32017-07-11 13:34:40 +0000627** This routine reads a line of text from FILE in, stores
628** the text in memory obtained from malloc() and returns a pointer
629** to the text. NULL is returned at end of file, or if malloc()
630** fails.
631**
632** If zLine is not NULL then it is a malloced buffer returned from
633** a previous call to this routine that may be reused.
634*/
635static char *local_getline(char *zLine, FILE *in){
636 int nLine = zLine==0 ? 0 : 100;
637 int n = 0;
638
639 while( 1 ){
640 if( n+100>nLine ){
641 nLine = nLine*2 + 100;
642 zLine = realloc(zLine, nLine);
drhe3e25652021-12-16 13:29:28 +0000643 shell_check_oom(zLine);
drh2ce15c32017-07-11 13:34:40 +0000644 }
645 if( fgets(&zLine[n], nLine - n, in)==0 ){
646 if( n==0 ){
647 free(zLine);
648 return 0;
649 }
650 zLine[n] = 0;
651 break;
652 }
653 while( zLine[n] ) n++;
654 if( n>0 && zLine[n-1]=='\n' ){
655 n--;
656 if( n>0 && zLine[n-1]=='\r' ) n--;
657 zLine[n] = 0;
658 break;
659 }
660 }
661#if defined(_WIN32) || defined(WIN32)
662 /* For interactive input on Windows systems, translate the
663 ** multi-byte characterset characters into UTF-8. */
664 if( stdin_is_interactive && in==stdin ){
665 char *zTrans = sqlite3_win32_mbcs_to_utf8_v2(zLine, 0);
666 if( zTrans ){
667 int nTrans = strlen30(zTrans)+1;
668 if( nTrans>nLine ){
669 zLine = realloc(zLine, nTrans);
drhe3e25652021-12-16 13:29:28 +0000670 shell_check_oom(zLine);
drh2ce15c32017-07-11 13:34:40 +0000671 }
672 memcpy(zLine, zTrans, nTrans);
673 sqlite3_free(zTrans);
674 }
675 }
676#endif /* defined(_WIN32) || defined(WIN32) */
677 return zLine;
678}
679
680/*
681** Retrieve a single line of input text.
682**
683** If in==0 then read from standard input and prompt before each line.
684** If isContinuation is true, then a continuation prompt is appropriate.
685** If isContinuation is zero, then the main prompt should be used.
686**
687** If zPrior is not NULL then it is a buffer from a prior call to this
688** routine that can be reused.
689**
690** The result is stored in space obtained from malloc() and must either
691** be freed by the caller or else passed back into this routine via the
692** zPrior argument for reuse.
693*/
694static char *one_input_line(FILE *in, char *zPrior, int isContinuation){
695 char *zPrompt;
696 char *zResult;
697 if( in!=0 ){
698 zResult = local_getline(zPrior, in);
699 }else{
700 zPrompt = isContinuation ? continuePrompt : mainPrompt;
701#if SHELL_USE_LOCAL_GETLINE
702 printf("%s", zPrompt);
703 fflush(stdout);
704 zResult = local_getline(zPrior, stdin);
705#else
706 free(zPrior);
707 zResult = shell_readline(zPrompt);
708 if( zResult && *zResult ) shell_add_history(zResult);
709#endif
710 }
711 return zResult;
712}
drh5af06982018-01-10 00:53:55 +0000713
714
715/*
716** Return the value of a hexadecimal digit. Return -1 if the input
717** is not a hex digit.
718*/
719static int hexDigitValue(char c){
720 if( c>='0' && c<='9' ) return c - '0';
721 if( c>='a' && c<='f' ) return c - 'a' + 10;
722 if( c>='A' && c<='F' ) return c - 'A' + 10;
723 return -1;
724}
725
726/*
727** Interpret zArg as an integer value, possibly with suffixes.
728*/
729static sqlite3_int64 integerValue(const char *zArg){
730 sqlite3_int64 v = 0;
731 static const struct { char *zSuffix; int iMult; } aMult[] = {
732 { "KiB", 1024 },
733 { "MiB", 1024*1024 },
734 { "GiB", 1024*1024*1024 },
735 { "KB", 1000 },
736 { "MB", 1000000 },
737 { "GB", 1000000000 },
738 { "K", 1000 },
739 { "M", 1000000 },
740 { "G", 1000000000 },
741 };
742 int i;
743 int isNeg = 0;
744 if( zArg[0]=='-' ){
745 isNeg = 1;
746 zArg++;
747 }else if( zArg[0]=='+' ){
748 zArg++;
749 }
750 if( zArg[0]=='0' && zArg[1]=='x' ){
751 int x;
752 zArg += 2;
753 while( (x = hexDigitValue(zArg[0]))>=0 ){
754 v = (v<<4) + x;
755 zArg++;
756 }
757 }else{
758 while( IsDigit(zArg[0]) ){
759 v = v*10 + zArg[0] - '0';
760 zArg++;
761 }
762 }
763 for(i=0; i<ArraySize(aMult); i++){
764 if( sqlite3_stricmp(aMult[i].zSuffix, zArg)==0 ){
765 v *= aMult[i].iMult;
766 break;
767 }
768 }
769 return isNeg? -v : v;
770}
771
drh2ce15c32017-07-11 13:34:40 +0000772/*
773** A variable length string to which one can append text.
774*/
775typedef struct ShellText ShellText;
776struct ShellText {
777 char *z;
778 int n;
779 int nAlloc;
780};
781
782/*
783** Initialize and destroy a ShellText object
784*/
785static void initText(ShellText *p){
786 memset(p, 0, sizeof(*p));
787}
788static void freeText(ShellText *p){
789 free(p->z);
790 initText(p);
791}
792
793/* zIn is either a pointer to a NULL-terminated string in memory obtained
794** from malloc(), or a NULL pointer. The string pointed to by zAppend is
795** added to zIn, and the result returned in memory obtained from malloc().
796** zIn, if it was not NULL, is freed.
797**
798** If the third argument, quote, is not '\0', then it is used as a
799** quote character for zAppend.
800*/
801static void appendText(ShellText *p, char const *zAppend, char quote){
802 int len;
803 int i;
804 int nAppend = strlen30(zAppend);
805
806 len = nAppend+p->n+1;
807 if( quote ){
808 len += 2;
809 for(i=0; i<nAppend; i++){
810 if( zAppend[i]==quote ) len++;
811 }
812 }
813
drh11a9ad52021-10-04 18:21:14 +0000814 if( p->z==0 || p->n+len>=p->nAlloc ){
drh2ce15c32017-07-11 13:34:40 +0000815 p->nAlloc = p->nAlloc*2 + len + 20;
816 p->z = realloc(p->z, p->nAlloc);
drhe3e25652021-12-16 13:29:28 +0000817 shell_check_oom(p->z);
drh2ce15c32017-07-11 13:34:40 +0000818 }
819
820 if( quote ){
821 char *zCsr = p->z+p->n;
822 *zCsr++ = quote;
823 for(i=0; i<nAppend; i++){
824 *zCsr++ = zAppend[i];
825 if( zAppend[i]==quote ) *zCsr++ = quote;
826 }
827 *zCsr++ = quote;
828 p->n = (int)(zCsr - p->z);
829 *zCsr = '\0';
830 }else{
831 memcpy(p->z+p->n, zAppend, nAppend);
832 p->n += nAppend;
833 p->z[p->n] = '\0';
834 }
835}
836
837/*
838** Attempt to determine if identifier zName needs to be quoted, either
839** because it contains non-alphanumeric characters, or because it is an
840** SQLite keyword. Be conservative in this estimate: When in doubt assume
841** that quoting is required.
842**
843** Return '"' if quoting is required. Return 0 if no quoting is required.
844*/
845static char quoteChar(const char *zName){
drhfc0ec3e2018-04-25 19:02:48 +0000846 int i;
drh2ce15c32017-07-11 13:34:40 +0000847 if( !isalpha((unsigned char)zName[0]) && zName[0]!='_' ) return '"';
848 for(i=0; zName[i]; i++){
849 if( !isalnum((unsigned char)zName[i]) && zName[i]!='_' ) return '"';
850 }
drhfc0ec3e2018-04-25 19:02:48 +0000851 return sqlite3_keyword_check(zName, i) ? '"' : 0;
drh2ce15c32017-07-11 13:34:40 +0000852}
853
854/*
drh667a2a22018-01-02 00:04:37 +0000855** Construct a fake object name and column list to describe the structure
856** of the view, virtual table, or table valued function zSchema.zName.
drhceba7922018-01-01 21:28:25 +0000857*/
drh667a2a22018-01-02 00:04:37 +0000858static char *shellFakeSchema(
drhceba7922018-01-01 21:28:25 +0000859 sqlite3 *db, /* The database connection containing the vtab */
860 const char *zSchema, /* Schema of the database holding the vtab */
861 const char *zName /* The name of the virtual table */
862){
863 sqlite3_stmt *pStmt = 0;
864 char *zSql;
drh1d315cf2018-01-01 21:49:43 +0000865 ShellText s;
866 char cQuote;
867 char *zDiv = "(";
drh667a2a22018-01-02 00:04:37 +0000868 int nRow = 0;
drhceba7922018-01-01 21:28:25 +0000869
drh1d315cf2018-01-01 21:49:43 +0000870 zSql = sqlite3_mprintf("PRAGMA \"%w\".table_info=%Q;",
871 zSchema ? zSchema : "main", zName);
drhe3e25652021-12-16 13:29:28 +0000872 shell_check_oom(zSql);
drhceba7922018-01-01 21:28:25 +0000873 sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
874 sqlite3_free(zSql);
drh1d315cf2018-01-01 21:49:43 +0000875 initText(&s);
876 if( zSchema ){
877 cQuote = quoteChar(zSchema);
878 if( cQuote && sqlite3_stricmp(zSchema,"temp")==0 ) cQuote = 0;
879 appendText(&s, zSchema, cQuote);
880 appendText(&s, ".", 0);
drhceba7922018-01-01 21:28:25 +0000881 }
drh1d315cf2018-01-01 21:49:43 +0000882 cQuote = quoteChar(zName);
883 appendText(&s, zName, cQuote);
884 while( sqlite3_step(pStmt)==SQLITE_ROW ){
885 const char *zCol = (const char*)sqlite3_column_text(pStmt, 1);
drh667a2a22018-01-02 00:04:37 +0000886 nRow++;
drh1d315cf2018-01-01 21:49:43 +0000887 appendText(&s, zDiv, 0);
888 zDiv = ",";
drh621a5e02021-12-16 17:35:27 +0000889 if( zCol==0 ) zCol = "";
drh1d315cf2018-01-01 21:49:43 +0000890 cQuote = quoteChar(zCol);
891 appendText(&s, zCol, cQuote);
892 }
893 appendText(&s, ")", 0);
drhceba7922018-01-01 21:28:25 +0000894 sqlite3_finalize(pStmt);
drh667a2a22018-01-02 00:04:37 +0000895 if( nRow==0 ){
896 freeText(&s);
897 s.z = 0;
898 }
drh1d315cf2018-01-01 21:49:43 +0000899 return s.z;
drhceba7922018-01-01 21:28:25 +0000900}
901
902/*
drh667a2a22018-01-02 00:04:37 +0000903** SQL function: shell_module_schema(X)
904**
905** Return a fake schema for the table-valued function or eponymous virtual
906** table X.
907*/
908static void shellModuleSchema(
909 sqlite3_context *pCtx,
910 int nVal,
911 sqlite3_value **apVal
912){
drh511b1182021-12-16 13:56:04 +0000913 const char *zName;
914 char *zFake;
drhb9685182018-01-17 13:15:23 +0000915 UNUSED_PARAMETER(nVal);
drh511b1182021-12-16 13:56:04 +0000916 zName = (const char*)sqlite3_value_text(apVal[0]);
917 zFake = zName ? shellFakeSchema(sqlite3_context_db_handle(pCtx), 0, zName) : 0;
drh667a2a22018-01-02 00:04:37 +0000918 if( zFake ){
dandcfbff92018-01-08 17:05:32 +0000919 sqlite3_result_text(pCtx, sqlite3_mprintf("/* %s */", zFake),
drh667a2a22018-01-02 00:04:37 +0000920 -1, sqlite3_free);
dandcfbff92018-01-08 17:05:32 +0000921 free(zFake);
drh667a2a22018-01-02 00:04:37 +0000922 }
923}
924
925/*
drh2ce15c32017-07-11 13:34:40 +0000926** SQL function: shell_add_schema(S,X)
927**
928** Add the schema name X to the CREATE statement in S and return the result.
929** Examples:
930**
931** CREATE TABLE t1(x) -> CREATE TABLE xyz.t1(x);
932**
933** Also works on
934**
935** CREATE INDEX
936** CREATE UNIQUE INDEX
937** CREATE VIEW
938** CREATE TRIGGER
939** CREATE VIRTUAL TABLE
940**
941** This UDF is used by the .schema command to insert the schema name of
drh067b92b2020-06-19 15:24:12 +0000942** attached databases into the middle of the sqlite_schema.sql field.
drh2ce15c32017-07-11 13:34:40 +0000943*/
944static void shellAddSchemaName(
945 sqlite3_context *pCtx,
946 int nVal,
947 sqlite3_value **apVal
948){
949 static const char *aPrefix[] = {
950 "TABLE",
951 "INDEX",
952 "UNIQUE INDEX",
953 "VIEW",
954 "TRIGGER",
955 "VIRTUAL TABLE"
956 };
957 int i = 0;
958 const char *zIn = (const char*)sqlite3_value_text(apVal[0]);
959 const char *zSchema = (const char*)sqlite3_value_text(apVal[1]);
drh667a2a22018-01-02 00:04:37 +0000960 const char *zName = (const char*)sqlite3_value_text(apVal[2]);
drhceba7922018-01-01 21:28:25 +0000961 sqlite3 *db = sqlite3_context_db_handle(pCtx);
drhb9685182018-01-17 13:15:23 +0000962 UNUSED_PARAMETER(nVal);
drh2ce15c32017-07-11 13:34:40 +0000963 if( zIn!=0 && strncmp(zIn, "CREATE ", 7)==0 ){
drh37407122021-07-23 18:43:58 +0000964 for(i=0; i<ArraySize(aPrefix); i++){
drh2ce15c32017-07-11 13:34:40 +0000965 int n = strlen30(aPrefix[i]);
966 if( strncmp(zIn+7, aPrefix[i], n)==0 && zIn[n+7]==' ' ){
drhceba7922018-01-01 21:28:25 +0000967 char *z = 0;
drh667a2a22018-01-02 00:04:37 +0000968 char *zFake = 0;
drhceba7922018-01-01 21:28:25 +0000969 if( zSchema ){
970 char cQuote = quoteChar(zSchema);
971 if( cQuote && sqlite3_stricmp(zSchema,"temp")!=0 ){
972 z = sqlite3_mprintf("%.*s \"%w\".%s", n+7, zIn, zSchema, zIn+n+8);
973 }else{
974 z = sqlite3_mprintf("%.*s %s.%s", n+7, zIn, zSchema, zIn+n+8);
975 }
drh2ce15c32017-07-11 13:34:40 +0000976 }
drh667a2a22018-01-02 00:04:37 +0000977 if( zName
978 && aPrefix[i][0]=='V'
979 && (zFake = shellFakeSchema(db, zSchema, zName))!=0
980 ){
981 if( z==0 ){
dandcfbff92018-01-08 17:05:32 +0000982 z = sqlite3_mprintf("%s\n/* %s */", zIn, zFake);
drh667a2a22018-01-02 00:04:37 +0000983 }else{
dandcfbff92018-01-08 17:05:32 +0000984 z = sqlite3_mprintf("%z\n/* %s */", z, zFake);
drh667a2a22018-01-02 00:04:37 +0000985 }
dandcfbff92018-01-08 17:05:32 +0000986 free(zFake);
drhceba7922018-01-01 21:28:25 +0000987 }
988 if( z ){
989 sqlite3_result_text(pCtx, z, -1, sqlite3_free);
990 return;
991 }
drh2ce15c32017-07-11 13:34:40 +0000992 }
993 }
994 }
995 sqlite3_result_value(pCtx, apVal[0]);
996}
997
998/*
999** The source code for several run-time loadable extensions is inserted
1000** below by the ../tool/mkshellc.tcl script. Before processing that included
1001** code, we need to override some macros to make the included program code
1002** work here in the middle of this regular program.
1003*/
1004#define SQLITE_EXTENSION_INIT1
drh89997982017-07-11 18:11:33 +00001005#define SQLITE_EXTENSION_INIT2(X) (void)(X)
drh2ce15c32017-07-11 13:34:40 +00001006
mistachkinacae8c32018-01-05 20:08:46 +00001007#if defined(_WIN32) && defined(_MSC_VER)
drh03491a12018-01-07 21:58:17 +00001008INCLUDE test_windirent.h
mistachkindfdfd8c2018-01-04 22:46:08 +00001009INCLUDE test_windirent.c
1010#define dirent DIRENT
mistachkindfdfd8c2018-01-04 22:46:08 +00001011#endif
drh2ce15c32017-07-11 13:34:40 +00001012INCLUDE ../ext/misc/shathree.c
1013INCLUDE ../ext/misc/fileio.c
drh56eb09b2017-07-11 13:59:07 +00001014INCLUDE ../ext/misc/completion.c
drh8682e122018-01-07 20:38:10 +00001015INCLUDE ../ext/misc/appendvfs.c
drh50b910a2019-01-21 14:55:03 +00001016INCLUDE ../ext/misc/memtrace.c
drhf05dd032020-04-14 15:53:58 +00001017INCLUDE ../ext/misc/uint.c
drhbeb9def2020-06-22 19:12:23 +00001018INCLUDE ../ext/misc/decimal.c
drh8cda77d2020-06-24 15:06:29 +00001019INCLUDE ../ext/misc/ieee754.c
mistachkin72c38d82020-08-28 18:47:39 +00001020INCLUDE ../ext/misc/series.c
drh64689902021-06-03 13:51:31 +00001021INCLUDE ../ext/misc/regexp.c
dan72afc3c2017-12-05 18:32:40 +00001022#ifdef SQLITE_HAVE_ZLIB
dan9ebfaad2017-12-26 20:39:58 +00001023INCLUDE ../ext/misc/zipfile.c
dand1b51d42017-12-16 19:11:26 +00001024INCLUDE ../ext/misc/sqlar.c
dan72afc3c2017-12-05 18:32:40 +00001025#endif
dan43efc182017-12-19 17:42:13 +00001026INCLUDE ../ext/expert/sqlite3expert.h
1027INCLUDE ../ext/expert/sqlite3expert.c
drh2ce15c32017-07-11 13:34:40 +00001028
dan1b162162019-04-27 20:15:15 +00001029#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
dan68cb86e2019-04-20 20:57:28 +00001030INCLUDE ../ext/misc/dbdata.c
dan1b162162019-04-27 20:15:15 +00001031#endif
dan68cb86e2019-04-20 20:57:28 +00001032
drh2ce15c32017-07-11 13:34:40 +00001033#if defined(SQLITE_ENABLE_SESSION)
1034/*
1035** State information for a single open session
1036*/
1037typedef struct OpenSession OpenSession;
1038struct OpenSession {
1039 char *zName; /* Symbolic name for this session */
1040 int nFilter; /* Number of xFilter rejection GLOB patterns */
1041 char **azFilter; /* Array of xFilter rejection GLOB patterns */
1042 sqlite3_session *p; /* The open session */
1043};
1044#endif
1045
dan43efc182017-12-19 17:42:13 +00001046typedef struct ExpertInfo ExpertInfo;
1047struct ExpertInfo {
1048 sqlite3expert *pExpert;
1049 int bVerbose;
1050};
1051
drh4b5345c2018-04-24 13:07:40 +00001052/* A single line in the EQP output */
1053typedef struct EQPGraphRow EQPGraphRow;
1054struct EQPGraphRow {
drhe2ca99c2018-05-02 00:33:43 +00001055 int iEqpId; /* ID for this row */
1056 int iParentId; /* ID of the parent row */
drh4b5345c2018-04-24 13:07:40 +00001057 EQPGraphRow *pNext; /* Next row in sequence */
1058 char zText[1]; /* Text to display for this row */
1059};
1060
1061/* All EQP output is collected into an instance of the following */
1062typedef struct EQPGraph EQPGraph;
1063struct EQPGraph {
1064 EQPGraphRow *pRow; /* Linked list of all rows of the EQP output */
1065 EQPGraphRow *pLast; /* Last element of the pRow list */
1066 char zPrefix[100]; /* Graph prefix */
1067};
1068
larrybrcc4d55c2022-02-01 02:50:45 +00001069/* Parameters affecting columnar mode result display (defaulting together) */
1070typedef struct ColModeOpts {
1071 int iWrap; /* In columnar modes, wrap lines reaching this limit */
1072 u8 bQuote; /* Quote results for .mode box and table */
1073 u8 bWordWrap; /* In columnar modes, wrap at word boundaries */
1074} ColModeOpts;
1075#define ColModeOpts_default { 60, 0, 0 }
1076#define ColModeOpts_default_qbox { 60, 1, 0 }
larrybrcc4d55c2022-02-01 02:50:45 +00001077
drh2ce15c32017-07-11 13:34:40 +00001078/*
1079** State information about the database connection is contained in an
1080** instance of the following structure.
1081*/
1082typedef struct ShellState ShellState;
1083struct ShellState {
1084 sqlite3 *db; /* The database */
drh1fa6d9f2018-01-06 21:46:01 +00001085 u8 autoExplain; /* Automatically turn on .explain mode */
1086 u8 autoEQP; /* Run EXPLAIN QUERY PLAN prior to seach SQL stmt */
drhe2ca99c2018-05-02 00:33:43 +00001087 u8 autoEQPtest; /* autoEQP is in test mode */
drhb4e50392019-01-26 15:40:04 +00001088 u8 autoEQPtrace; /* autoEQP is in trace mode */
drh1fa6d9f2018-01-06 21:46:01 +00001089 u8 scanstatsOn; /* True to display scan stats before each finalize */
1090 u8 openMode; /* SHELL_OPEN_NORMAL, _APPENDVFS, or _ZIPFILE */
drh13c20932018-01-10 21:41:55 +00001091 u8 doXdgOpen; /* Invoke start/open/xdg-open in output_reset() */
drh4b5345c2018-04-24 13:07:40 +00001092 u8 nEqpLevel; /* Depth of the EQP output graph */
drh707821f2018-12-05 13:39:06 +00001093 u8 eTraceType; /* SHELL_TRACE_* value for type of trace */
drhb97e2ad2021-08-26 18:31:39 +00001094 u8 bSafeMode; /* True to prohibit unsafe operations */
1095 u8 bSafeModePersist; /* The long-term value of bSafeMode */
larrybrcc4d55c2022-02-01 02:50:45 +00001096 ColModeOpts cmOpts; /* Option values affecting columnar mode output */
drha6e6cf22021-01-09 19:10:04 +00001097 unsigned statsOn; /* True to display memory stats before each finalize */
drh4b5345c2018-04-24 13:07:40 +00001098 unsigned mEqpLines; /* Mask of veritical lines in the EQP output graph */
larrybrd48e88e2022-01-24 06:36:16 +00001099 int inputNesting; /* Track nesting level of .read and other redirects */
drh2ce15c32017-07-11 13:34:40 +00001100 int outCount; /* Revert to stdout when reaching zero */
1101 int cnt; /* Number of records displayed so far */
drh2c8ee022018-12-13 18:59:30 +00001102 int lineno; /* Line number of last line read from in */
drh0933aad2019-11-18 17:46:38 +00001103 int openFlags; /* Additional flags to open. (SQLITE_OPEN_NOFOLLOW) */
drh60379d42018-12-13 18:30:01 +00001104 FILE *in; /* Read commands from this stream */
drh2ce15c32017-07-11 13:34:40 +00001105 FILE *out; /* Write results here */
1106 FILE *traceOut; /* Output for sqlite3_trace() */
1107 int nErr; /* Number of errors seen */
1108 int mode; /* An output mode setting */
drh3c484e82018-01-10 22:27:21 +00001109 int modePrior; /* Saved mode */
drh2ce15c32017-07-11 13:34:40 +00001110 int cMode; /* temporary output mode for the current query */
1111 int normalMode; /* Output mode before ".explain on" */
1112 int writableSchema; /* True if PRAGMA writable_schema=ON */
1113 int showHeader; /* True to show column names in List or Column mode */
1114 int nCheck; /* Number of ".check" commands run */
drh3f83f592019-02-04 14:53:18 +00001115 unsigned nProgress; /* Number of progress callbacks encountered */
1116 unsigned mxProgress; /* Maximum progress callbacks before failing */
1117 unsigned flgProgress; /* Flags for the progress callback */
drh2ce15c32017-07-11 13:34:40 +00001118 unsigned shellFlgs; /* Various flags */
drh7a431002020-04-18 14:12:00 +00001119 unsigned priorShFlgs; /* Saved copy of flags */
drh6ca64482019-01-22 16:06:20 +00001120 sqlite3_int64 szMax; /* --maxsize argument to .open */
drh2ce15c32017-07-11 13:34:40 +00001121 char *zDestTable; /* Name of destination table when MODE_Insert */
drh13c20932018-01-10 21:41:55 +00001122 char *zTempFile; /* Temporary file that might need deleting */
drh2ce15c32017-07-11 13:34:40 +00001123 char zTestcase[30]; /* Name of current test case */
1124 char colSeparator[20]; /* Column separator character for several modes */
1125 char rowSeparator[20]; /* Row separator character for MODE_Ascii */
drh3c484e82018-01-10 22:27:21 +00001126 char colSepPrior[20]; /* Saved column separator */
1127 char rowSepPrior[20]; /* Saved row separator */
drh0285d982020-05-29 14:38:43 +00001128 int *colWidth; /* Requested width of each column in columnar modes */
1129 int *actualWidth; /* Actual width of each column */
1130 int nWidth; /* Number of slots in colWidth[] and actualWidth[] */
drh2ce15c32017-07-11 13:34:40 +00001131 char nullValue[20]; /* The text to print when a NULL comes back from
1132 ** the database */
1133 char outfile[FILENAME_MAX]; /* Filename for *out */
drh2ce15c32017-07-11 13:34:40 +00001134 sqlite3_stmt *pStmt; /* Current statement if any. */
1135 FILE *pLog; /* Write log output here */
drh37407122021-07-23 18:43:58 +00001136 struct AuxDb { /* Storage space for auxiliary database connections */
1137 sqlite3 *db; /* Connection pointer */
1138 const char *zDbFilename; /* Filename used to open the connection */
1139 char *zFreeOnClose; /* Free this memory allocation on close */
1140#if defined(SQLITE_ENABLE_SESSION)
1141 int nSession; /* Number of active sessions */
1142 OpenSession aSession[4]; /* Array of sessions. [0] is in focus. */
1143#endif
1144 } aAuxDb[5], /* Array of all database connections */
1145 *pAuxDb; /* Currently active database connection */
drh2ce15c32017-07-11 13:34:40 +00001146 int *aiIndent; /* Array of indents used in MODE_Explain */
1147 int nIndent; /* Size of array aiIndent[] */
1148 int iIndent; /* Index of current op in aiIndent[] */
drhb97e2ad2021-08-26 18:31:39 +00001149 char *zNonce; /* Nonce for temporary safe-mode excapes */
drh4b5345c2018-04-24 13:07:40 +00001150 EQPGraph sGraph; /* Information for the graphical EXPLAIN QUERY PLAN */
drhb97e2ad2021-08-26 18:31:39 +00001151 ExpertInfo expert; /* Valid if previous command was ".expert OPT..." */
drh2ce15c32017-07-11 13:34:40 +00001152};
1153
drh1fa6d9f2018-01-06 21:46:01 +00001154
drhada70452017-12-21 21:02:27 +00001155/* Allowed values for ShellState.autoEQP
1156*/
drhe2ca99c2018-05-02 00:33:43 +00001157#define AUTOEQP_off 0 /* Automatic EXPLAIN QUERY PLAN is off */
1158#define AUTOEQP_on 1 /* Automatic EQP is on */
1159#define AUTOEQP_trigger 2 /* On and also show plans for triggers */
1160#define AUTOEQP_full 3 /* Show full EXPLAIN */
drhada70452017-12-21 21:02:27 +00001161
drh1fa6d9f2018-01-06 21:46:01 +00001162/* Allowed values for ShellState.openMode
1163*/
drh60f34ae2018-10-30 13:19:49 +00001164#define SHELL_OPEN_UNSPEC 0 /* No open-mode specified */
1165#define SHELL_OPEN_NORMAL 1 /* Normal database file */
1166#define SHELL_OPEN_APPENDVFS 2 /* Use appendvfs */
1167#define SHELL_OPEN_ZIPFILE 3 /* Use the zipfile virtual table */
1168#define SHELL_OPEN_READONLY 4 /* Open a normal database read-only */
1169#define SHELL_OPEN_DESERIALIZE 5 /* Open using sqlite3_deserialize() */
drh33746482018-12-13 15:06:26 +00001170#define SHELL_OPEN_HEXDB 6 /* Use "dbtotxt" output as data source */
drh1fa6d9f2018-01-06 21:46:01 +00001171
drh707821f2018-12-05 13:39:06 +00001172/* Allowed values for ShellState.eTraceType
1173*/
1174#define SHELL_TRACE_PLAIN 0 /* Show input SQL text */
1175#define SHELL_TRACE_EXPANDED 1 /* Show expanded SQL text */
1176#define SHELL_TRACE_NORMALIZED 2 /* Show normalized SQL text */
1177
drh3f83f592019-02-04 14:53:18 +00001178/* Bits in the ShellState.flgProgress variable */
drhfc4eeef2019-02-05 19:48:46 +00001179#define SHELL_PROGRESS_QUIET 0x01 /* Omit announcing every progress callback */
1180#define SHELL_PROGRESS_RESET 0x02 /* Reset the count when the progres
1181 ** callback limit is reached, and for each
1182 ** top-level SQL statement */
1183#define SHELL_PROGRESS_ONCE 0x04 /* Cancel the --limit after firing once */
drh3f83f592019-02-04 14:53:18 +00001184
drh2ce15c32017-07-11 13:34:40 +00001185/*
1186** These are the allowed shellFlgs values
1187*/
drhb2a0f752017-08-28 15:51:35 +00001188#define SHFLG_Pagecache 0x00000001 /* The --pagecache option is used */
1189#define SHFLG_Lookaside 0x00000002 /* Lookaside memory is used */
1190#define SHFLG_Backslash 0x00000004 /* The --backslash option is used */
1191#define SHFLG_PreserveRowid 0x00000008 /* .dump preserves rowid values */
1192#define SHFLG_Newlines 0x00000010 /* .dump --newline flag */
1193#define SHFLG_CountChanges 0x00000020 /* .changes setting */
1194#define SHFLG_Echo 0x00000040 /* .echo or --echo setting */
larrybrae509122021-09-10 01:45:20 +00001195#define SHFLG_HeaderSet 0x00000080 /* showHeader has been specified */
drhc1962192020-10-12 16:54:28 +00001196#define SHFLG_DumpDataOnly 0x00000100 /* .dump show data only */
1197#define SHFLG_DumpNoSys 0x00000200 /* .dump omits system tables */
drh2ce15c32017-07-11 13:34:40 +00001198
1199/*
1200** Macros for testing and setting shellFlgs
1201*/
1202#define ShellHasFlag(P,X) (((P)->shellFlgs & (X))!=0)
1203#define ShellSetFlag(P,X) ((P)->shellFlgs|=(X))
1204#define ShellClearFlag(P,X) ((P)->shellFlgs&=(~(X)))
1205
1206/*
1207** These are the allowed modes.
1208*/
1209#define MODE_Line 0 /* One column per line. Blank line between records */
1210#define MODE_Column 1 /* One record per line in neat columns */
1211#define MODE_List 2 /* One record per line with a separator */
1212#define MODE_Semi 3 /* Same as MODE_List but append ";" to each line */
1213#define MODE_Html 4 /* Generate an XHTML table */
1214#define MODE_Insert 5 /* Generate SQL "insert" statements */
1215#define MODE_Quote 6 /* Quote values as for SQL */
1216#define MODE_Tcl 7 /* Generate ANSI-C or TCL quoted elements */
1217#define MODE_Csv 8 /* Quote strings, numbers are plain */
1218#define MODE_Explain 9 /* Like MODE_Column, but do not truncate data */
1219#define MODE_Ascii 10 /* Use ASCII unit and record separators (0x1F/0x1E) */
1220#define MODE_Pretty 11 /* Pretty-print schemas */
drh4b5345c2018-04-24 13:07:40 +00001221#define MODE_EQP 12 /* Converts EXPLAIN QUERY PLAN output into a graph */
drh30c54a02020-05-28 23:49:50 +00001222#define MODE_Json 13 /* Output JSON */
1223#define MODE_Markdown 14 /* Markdown formatting */
1224#define MODE_Table 15 /* MySQL-style table formatting */
drh0908e382020-06-04 18:05:39 +00001225#define MODE_Box 16 /* Unicode box-drawing characters */
drh5d88be82021-12-09 16:17:43 +00001226#define MODE_Count 17 /* Output only a count of the rows of output */
1227#define MODE_Off 18 /* No query output shown */
drh2ce15c32017-07-11 13:34:40 +00001228
1229static const char *modeDescr[] = {
1230 "line",
1231 "column",
1232 "list",
1233 "semi",
1234 "html",
1235 "insert",
1236 "quote",
1237 "tcl",
1238 "csv",
1239 "explain",
1240 "ascii",
1241 "prettyprint",
drh30c54a02020-05-28 23:49:50 +00001242 "eqp",
1243 "json",
1244 "markdown",
drh0908e382020-06-04 18:05:39 +00001245 "table",
drh5d88be82021-12-09 16:17:43 +00001246 "box",
1247 "count",
1248 "off"
drh2ce15c32017-07-11 13:34:40 +00001249};
1250
1251/*
1252** These are the column/row/line separators used by the various
1253** import/export modes.
1254*/
1255#define SEP_Column "|"
1256#define SEP_Row "\n"
1257#define SEP_Tab "\t"
1258#define SEP_Space " "
1259#define SEP_Comma ","
1260#define SEP_CrLf "\r\n"
1261#define SEP_Unit "\x1F"
1262#define SEP_Record "\x1E"
1263
1264/*
larrybrd48e88e2022-01-24 06:36:16 +00001265** Limit input nesting via .read or any other input redirect.
1266** It's not too expensive, so a generous allowance can be made.
1267*/
1268#define MAX_INPUT_NESTING 25
1269
1270/*
drh2ce15c32017-07-11 13:34:40 +00001271** A callback for the sqlite3_log() interface.
1272*/
1273static void shellLog(void *pArg, int iErrCode, const char *zMsg){
1274 ShellState *p = (ShellState*)pArg;
1275 if( p->pLog==0 ) return;
1276 utf8_printf(p->pLog, "(%d) %s\n", iErrCode, zMsg);
1277 fflush(p->pLog);
1278}
1279
1280/*
drh634c70f2018-01-10 16:50:18 +00001281** SQL function: shell_putsnl(X)
1282**
1283** Write the text X to the screen (or whatever output is being directed)
1284** adding a newline at the end, and then return X.
1285*/
1286static void shellPutsFunc(
1287 sqlite3_context *pCtx,
1288 int nVal,
1289 sqlite3_value **apVal
1290){
1291 ShellState *p = (ShellState*)sqlite3_user_data(pCtx);
drhb9685182018-01-17 13:15:23 +00001292 (void)nVal;
drh634c70f2018-01-10 16:50:18 +00001293 utf8_printf(p->out, "%s\n", sqlite3_value_text(apVal[0]));
1294 sqlite3_result_value(pCtx, apVal[0]);
1295}
1296
1297/*
drhb97e2ad2021-08-26 18:31:39 +00001298** If in safe mode, print an error message described by the arguments
1299** and exit immediately.
1300*/
1301static void failIfSafeMode(
1302 ShellState *p,
1303 const char *zErrMsg,
1304 ...
1305){
1306 if( p->bSafeMode ){
1307 va_list ap;
1308 char *zMsg;
1309 va_start(ap, zErrMsg);
1310 zMsg = sqlite3_vmprintf(zErrMsg, ap);
1311 va_end(ap);
1312 raw_printf(stderr, "line %d: ", p->lineno);
1313 utf8_printf(stderr, "%s\n", zMsg);
1314 exit(1);
1315 }
1316}
1317
1318/*
drh97913132018-01-11 00:04:00 +00001319** SQL function: edit(VALUE)
1320** edit(VALUE,EDITOR)
1321**
1322** These steps:
1323**
1324** (1) Write VALUE into a temporary file.
1325** (2) Run program EDITOR on that temporary file.
1326** (3) Read the temporary file back and return its content as the result.
1327** (4) Delete the temporary file
1328**
1329** If the EDITOR argument is omitted, use the value in the VISUAL
1330** environment variable. If still there is no EDITOR, through an error.
1331**
1332** Also throw an error if the EDITOR program returns a non-zero exit code.
1333*/
drh04a28c32018-01-31 01:38:44 +00001334#ifndef SQLITE_NOHAVE_SYSTEM
drh97913132018-01-11 00:04:00 +00001335static void editFunc(
1336 sqlite3_context *context,
1337 int argc,
1338 sqlite3_value **argv
1339){
1340 const char *zEditor;
1341 char *zTempFile = 0;
1342 sqlite3 *db;
1343 char *zCmd = 0;
1344 int bBin;
1345 int rc;
drhf018fd52018-08-06 02:08:53 +00001346 int hasCRNL = 0;
drh97913132018-01-11 00:04:00 +00001347 FILE *f = 0;
1348 sqlite3_int64 sz;
1349 sqlite3_int64 x;
1350 unsigned char *p = 0;
1351
1352 if( argc==2 ){
1353 zEditor = (const char*)sqlite3_value_text(argv[1]);
1354 }else{
1355 zEditor = getenv("VISUAL");
1356 }
1357 if( zEditor==0 ){
1358 sqlite3_result_error(context, "no editor for edit()", -1);
1359 return;
1360 }
1361 if( sqlite3_value_type(argv[0])==SQLITE_NULL ){
1362 sqlite3_result_error(context, "NULL input to edit()", -1);
1363 return;
1364 }
1365 db = sqlite3_context_db_handle(context);
1366 zTempFile = 0;
1367 sqlite3_file_control(db, 0, SQLITE_FCNTL_TEMPFILENAME, &zTempFile);
1368 if( zTempFile==0 ){
1369 sqlite3_uint64 r = 0;
1370 sqlite3_randomness(sizeof(r), &r);
1371 zTempFile = sqlite3_mprintf("temp%llx", r);
1372 if( zTempFile==0 ){
1373 sqlite3_result_error_nomem(context);
1374 return;
1375 }
1376 }
1377 bBin = sqlite3_value_type(argv[0])==SQLITE_BLOB;
drhf018fd52018-08-06 02:08:53 +00001378 /* When writing the file to be edited, do \n to \r\n conversions on systems
1379 ** that want \r\n line endings */
drh97913132018-01-11 00:04:00 +00001380 f = fopen(zTempFile, bBin ? "wb" : "w");
1381 if( f==0 ){
1382 sqlite3_result_error(context, "edit() cannot open temp file", -1);
1383 goto edit_func_end;
1384 }
1385 sz = sqlite3_value_bytes(argv[0]);
1386 if( bBin ){
dan4d02b5f2019-07-17 07:23:06 +00001387 x = fwrite(sqlite3_value_blob(argv[0]), 1, (size_t)sz, f);
drh97913132018-01-11 00:04:00 +00001388 }else{
drhf018fd52018-08-06 02:08:53 +00001389 const char *z = (const char*)sqlite3_value_text(argv[0]);
1390 /* Remember whether or not the value originally contained \r\n */
1391 if( z && strstr(z,"\r\n")!=0 ) hasCRNL = 1;
dan4d02b5f2019-07-17 07:23:06 +00001392 x = fwrite(sqlite3_value_text(argv[0]), 1, (size_t)sz, f);
drh97913132018-01-11 00:04:00 +00001393 }
1394 fclose(f);
1395 f = 0;
1396 if( x!=sz ){
1397 sqlite3_result_error(context, "edit() could not write the whole file", -1);
1398 goto edit_func_end;
1399 }
1400 zCmd = sqlite3_mprintf("%s \"%s\"", zEditor, zTempFile);
1401 if( zCmd==0 ){
1402 sqlite3_result_error_nomem(context);
1403 goto edit_func_end;
1404 }
1405 rc = system(zCmd);
1406 sqlite3_free(zCmd);
1407 if( rc ){
1408 sqlite3_result_error(context, "EDITOR returned non-zero", -1);
1409 goto edit_func_end;
1410 }
drhf018fd52018-08-06 02:08:53 +00001411 f = fopen(zTempFile, "rb");
drh97913132018-01-11 00:04:00 +00001412 if( f==0 ){
1413 sqlite3_result_error(context,
1414 "edit() cannot reopen temp file after edit", -1);
1415 goto edit_func_end;
1416 }
1417 fseek(f, 0, SEEK_END);
1418 sz = ftell(f);
1419 rewind(f);
drhee37f8b2019-08-23 23:05:32 +00001420 p = sqlite3_malloc64( sz+1 );
drh97913132018-01-11 00:04:00 +00001421 if( p==0 ){
1422 sqlite3_result_error_nomem(context);
1423 goto edit_func_end;
1424 }
dan4d02b5f2019-07-17 07:23:06 +00001425 x = fread(p, 1, (size_t)sz, f);
drh97913132018-01-11 00:04:00 +00001426 fclose(f);
1427 f = 0;
1428 if( x!=sz ){
1429 sqlite3_result_error(context, "could not read back the whole file", -1);
1430 goto edit_func_end;
1431 }
1432 if( bBin ){
mistachkinb71aa092018-01-23 00:05:18 +00001433 sqlite3_result_blob64(context, p, sz, sqlite3_free);
drh97913132018-01-11 00:04:00 +00001434 }else{
dan60bdcf52018-10-03 11:13:30 +00001435 sqlite3_int64 i, j;
drhf018fd52018-08-06 02:08:53 +00001436 if( hasCRNL ){
1437 /* If the original contains \r\n then do no conversions back to \n */
drhf018fd52018-08-06 02:08:53 +00001438 }else{
1439 /* If the file did not originally contain \r\n then convert any new
1440 ** \r\n back into \n */
1441 for(i=j=0; i<sz; i++){
1442 if( p[i]=='\r' && p[i+1]=='\n' ) i++;
1443 p[j++] = p[i];
1444 }
1445 sz = j;
1446 p[sz] = 0;
1447 }
mistachkinb71aa092018-01-23 00:05:18 +00001448 sqlite3_result_text64(context, (const char*)p, sz,
1449 sqlite3_free, SQLITE_UTF8);
drh97913132018-01-11 00:04:00 +00001450 }
1451 p = 0;
1452
1453edit_func_end:
1454 if( f ) fclose(f);
1455 unlink(zTempFile);
1456 sqlite3_free(zTempFile);
1457 sqlite3_free(p);
1458}
drh04a28c32018-01-31 01:38:44 +00001459#endif /* SQLITE_NOHAVE_SYSTEM */
drh97913132018-01-11 00:04:00 +00001460
1461/*
drh3c484e82018-01-10 22:27:21 +00001462** Save or restore the current output mode
1463*/
1464static void outputModePush(ShellState *p){
1465 p->modePrior = p->mode;
drh7a431002020-04-18 14:12:00 +00001466 p->priorShFlgs = p->shellFlgs;
drh3c484e82018-01-10 22:27:21 +00001467 memcpy(p->colSepPrior, p->colSeparator, sizeof(p->colSeparator));
1468 memcpy(p->rowSepPrior, p->rowSeparator, sizeof(p->rowSeparator));
1469}
1470static void outputModePop(ShellState *p){
1471 p->mode = p->modePrior;
drh7a431002020-04-18 14:12:00 +00001472 p->shellFlgs = p->priorShFlgs;
drh3c484e82018-01-10 22:27:21 +00001473 memcpy(p->colSeparator, p->colSepPrior, sizeof(p->colSeparator));
1474 memcpy(p->rowSeparator, p->rowSepPrior, sizeof(p->rowSeparator));
1475}
1476
1477/*
drh2ce15c32017-07-11 13:34:40 +00001478** Output the given string as a hex-encoded blob (eg. X'1234' )
1479*/
1480static void output_hex_blob(FILE *out, const void *pBlob, int nBlob){
1481 int i;
1482 char *zBlob = (char *)pBlob;
1483 raw_printf(out,"X'");
1484 for(i=0; i<nBlob; i++){ raw_printf(out,"%02x",zBlob[i]&0xff); }
1485 raw_printf(out,"'");
1486}
1487
1488/*
1489** Find a string that is not found anywhere in z[]. Return a pointer
1490** to that string.
1491**
1492** Try to use zA and zB first. If both of those are already found in z[]
1493** then make up some string and store it in the buffer zBuf.
1494*/
1495static const char *unused_string(
1496 const char *z, /* Result must not appear anywhere in z */
1497 const char *zA, const char *zB, /* Try these first */
1498 char *zBuf /* Space to store a generated string */
1499){
1500 unsigned i = 0;
1501 if( strstr(z, zA)==0 ) return zA;
1502 if( strstr(z, zB)==0 ) return zB;
1503 do{
1504 sqlite3_snprintf(20,zBuf,"(%s%u)", zA, i++);
1505 }while( strstr(z,zBuf)!=0 );
1506 return zBuf;
1507}
1508
1509/*
1510** Output the given string as a quoted string using SQL quoting conventions.
1511**
1512** See also: output_quoted_escaped_string()
1513*/
1514static void output_quoted_string(FILE *out, const char *z){
1515 int i;
1516 char c;
1517 setBinaryMode(out, 1);
1518 for(i=0; (c = z[i])!=0 && c!='\''; i++){}
1519 if( c==0 ){
1520 utf8_printf(out,"'%s'",z);
1521 }else{
1522 raw_printf(out, "'");
1523 while( *z ){
1524 for(i=0; (c = z[i])!=0 && c!='\''; i++){}
1525 if( c=='\'' ) i++;
1526 if( i ){
1527 utf8_printf(out, "%.*s", i, z);
1528 z += i;
1529 }
1530 if( c=='\'' ){
1531 raw_printf(out, "'");
1532 continue;
1533 }
1534 if( c==0 ){
1535 break;
1536 }
1537 z++;
1538 }
1539 raw_printf(out, "'");
1540 }
1541 setTextMode(out, 1);
1542}
1543
1544/*
1545** Output the given string as a quoted string using SQL quoting conventions.
1546** Additionallly , escape the "\n" and "\r" characters so that they do not
1547** get corrupted by end-of-line translation facilities in some operating
1548** systems.
1549**
1550** This is like output_quoted_string() but with the addition of the \r\n
1551** escape mechanism.
1552*/
1553static void output_quoted_escaped_string(FILE *out, const char *z){
1554 int i;
1555 char c;
1556 setBinaryMode(out, 1);
1557 for(i=0; (c = z[i])!=0 && c!='\'' && c!='\n' && c!='\r'; i++){}
1558 if( c==0 ){
1559 utf8_printf(out,"'%s'",z);
1560 }else{
1561 const char *zNL = 0;
1562 const char *zCR = 0;
1563 int nNL = 0;
1564 int nCR = 0;
1565 char zBuf1[20], zBuf2[20];
1566 for(i=0; z[i]; i++){
1567 if( z[i]=='\n' ) nNL++;
1568 if( z[i]=='\r' ) nCR++;
1569 }
1570 if( nNL ){
1571 raw_printf(out, "replace(");
1572 zNL = unused_string(z, "\\n", "\\012", zBuf1);
1573 }
1574 if( nCR ){
1575 raw_printf(out, "replace(");
1576 zCR = unused_string(z, "\\r", "\\015", zBuf2);
1577 }
1578 raw_printf(out, "'");
1579 while( *z ){
1580 for(i=0; (c = z[i])!=0 && c!='\n' && c!='\r' && c!='\''; i++){}
1581 if( c=='\'' ) i++;
1582 if( i ){
1583 utf8_printf(out, "%.*s", i, z);
1584 z += i;
1585 }
1586 if( c=='\'' ){
1587 raw_printf(out, "'");
1588 continue;
1589 }
1590 if( c==0 ){
1591 break;
1592 }
1593 z++;
1594 if( c=='\n' ){
1595 raw_printf(out, "%s", zNL);
1596 continue;
1597 }
1598 raw_printf(out, "%s", zCR);
1599 }
1600 raw_printf(out, "'");
1601 if( nCR ){
1602 raw_printf(out, ",'%s',char(13))", zCR);
1603 }
1604 if( nNL ){
1605 raw_printf(out, ",'%s',char(10))", zNL);
1606 }
1607 }
1608 setTextMode(out, 1);
1609}
1610
1611/*
1612** Output the given string as a quoted according to C or TCL quoting rules.
1613*/
1614static void output_c_string(FILE *out, const char *z){
1615 unsigned int c;
1616 fputc('"', out);
1617 while( (c = *(z++))!=0 ){
1618 if( c=='\\' ){
1619 fputc(c, out);
1620 fputc(c, out);
1621 }else if( c=='"' ){
1622 fputc('\\', out);
1623 fputc('"', out);
1624 }else if( c=='\t' ){
1625 fputc('\\', out);
1626 fputc('t', out);
1627 }else if( c=='\n' ){
1628 fputc('\\', out);
1629 fputc('n', out);
1630 }else if( c=='\r' ){
1631 fputc('\\', out);
1632 fputc('r', out);
1633 }else if( !isprint(c&0xff) ){
1634 raw_printf(out, "\\%03o", c&0xff);
1635 }else{
1636 fputc(c, out);
1637 }
1638 }
1639 fputc('"', out);
1640}
1641
1642/*
drh69c093d2020-05-29 00:21:43 +00001643** Output the given string as a quoted according to JSON quoting rules.
1644*/
1645static void output_json_string(FILE *out, const char *z, int n){
1646 unsigned int c;
1647 if( n<0 ) n = (int)strlen(z);
1648 fputc('"', out);
1649 while( n-- ){
1650 c = *(z++);
1651 if( c=='\\' || c=='"' ){
1652 fputc('\\', out);
1653 fputc(c, out);
1654 }else if( c<=0x1f ){
1655 fputc('\\', out);
1656 if( c=='\b' ){
1657 fputc('b', out);
1658 }else if( c=='\f' ){
1659 fputc('f', out);
1660 }else if( c=='\n' ){
1661 fputc('n', out);
1662 }else if( c=='\r' ){
1663 fputc('r', out);
1664 }else if( c=='\t' ){
1665 fputc('t', out);
1666 }else{
1667 raw_printf(out, "u%04x",c);
1668 }
1669 }else{
1670 fputc(c, out);
1671 }
1672 }
1673 fputc('"', out);
1674}
1675
1676/*
drh2ce15c32017-07-11 13:34:40 +00001677** Output the given string with characters that are special to
1678** HTML escaped.
1679*/
1680static void output_html_string(FILE *out, const char *z){
1681 int i;
1682 if( z==0 ) z = "";
1683 while( *z ){
1684 for(i=0; z[i]
1685 && z[i]!='<'
1686 && z[i]!='&'
1687 && z[i]!='>'
1688 && z[i]!='\"'
1689 && z[i]!='\'';
1690 i++){}
1691 if( i>0 ){
1692 utf8_printf(out,"%.*s",i,z);
1693 }
1694 if( z[i]=='<' ){
1695 raw_printf(out,"&lt;");
1696 }else if( z[i]=='&' ){
1697 raw_printf(out,"&amp;");
1698 }else if( z[i]=='>' ){
1699 raw_printf(out,"&gt;");
1700 }else if( z[i]=='\"' ){
1701 raw_printf(out,"&quot;");
1702 }else if( z[i]=='\'' ){
1703 raw_printf(out,"&#39;");
1704 }else{
1705 break;
1706 }
1707 z += i + 1;
1708 }
1709}
1710
1711/*
1712** If a field contains any character identified by a 1 in the following
1713** array, then the string must be quoted for CSV.
1714*/
1715static const char needCsvQuote[] = {
1716 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1717 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1718 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
1719 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1720 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1721 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1722 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1723 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
1724 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1725 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1726 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1727 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1728 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1729 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1730 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1731 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1732};
1733
1734/*
1735** Output a single term of CSV. Actually, p->colSeparator is used for
1736** the separator, which may or may not be a comma. p->nullValue is
1737** the null value. Strings are quoted if necessary. The separator
1738** is only issued if bSep is true.
1739*/
1740static void output_csv(ShellState *p, const char *z, int bSep){
1741 FILE *out = p->out;
1742 if( z==0 ){
1743 utf8_printf(out,"%s",p->nullValue);
1744 }else{
drh9cd0c3d2021-11-18 15:40:05 +00001745 unsigned i;
1746 for(i=0; z[i]; i++){
1747 if( needCsvQuote[((unsigned char*)z)[i]] ){
drh2ce15c32017-07-11 13:34:40 +00001748 i = 0;
1749 break;
1750 }
1751 }
drh9cd0c3d2021-11-18 15:40:05 +00001752 if( i==0 || strstr(z, p->colSeparator)!=0 ){
drh9b7affc2017-11-26 02:14:18 +00001753 char *zQuoted = sqlite3_mprintf("\"%w\"", z);
drhe3e25652021-12-16 13:29:28 +00001754 shell_check_oom(zQuoted);
drh9b7affc2017-11-26 02:14:18 +00001755 utf8_printf(out, "%s", zQuoted);
1756 sqlite3_free(zQuoted);
drh2ce15c32017-07-11 13:34:40 +00001757 }else{
1758 utf8_printf(out, "%s", z);
1759 }
1760 }
1761 if( bSep ){
1762 utf8_printf(p->out, "%s", p->colSeparator);
1763 }
1764}
1765
drh2ce15c32017-07-11 13:34:40 +00001766/*
1767** This routine runs when the user presses Ctrl-C
1768*/
1769static void interrupt_handler(int NotUsed){
1770 UNUSED_PARAMETER(NotUsed);
1771 seenInterrupt++;
1772 if( seenInterrupt>2 ) exit(1);
1773 if( globalDb ) sqlite3_interrupt(globalDb);
1774}
mistachkinb4bab902017-10-27 17:09:44 +00001775
1776#if (defined(_WIN32) || defined(WIN32)) && !defined(_WIN32_WCE)
1777/*
1778** This routine runs for console events (e.g. Ctrl-C) on Win32
1779*/
1780static BOOL WINAPI ConsoleCtrlHandler(
1781 DWORD dwCtrlType /* One of the CTRL_*_EVENT constants */
1782){
1783 if( dwCtrlType==CTRL_C_EVENT ){
1784 interrupt_handler(0);
1785 return TRUE;
1786 }
1787 return FALSE;
1788}
drh2ce15c32017-07-11 13:34:40 +00001789#endif
1790
1791#ifndef SQLITE_OMIT_AUTHORIZATION
1792/*
drhb97e2ad2021-08-26 18:31:39 +00001793** This authorizer runs in safe mode.
1794*/
1795static int safeModeAuth(
1796 void *pClientData,
1797 int op,
1798 const char *zA1,
1799 const char *zA2,
1800 const char *zA3,
1801 const char *zA4
1802){
1803 ShellState *p = (ShellState*)pClientData;
1804 static const char *azProhibitedFunctions[] = {
1805 "edit",
1806 "fts3_tokenizer",
1807 "load_extension",
1808 "readfile",
1809 "writefile",
1810 "zipfile",
1811 "zipfile_cds",
1812 };
1813 UNUSED_PARAMETER(zA2);
1814 UNUSED_PARAMETER(zA3);
1815 UNUSED_PARAMETER(zA4);
1816 switch( op ){
1817 case SQLITE_ATTACH: {
1818 failIfSafeMode(p, "cannot run ATTACH in safe mode");
1819 break;
1820 }
1821 case SQLITE_FUNCTION: {
1822 int i;
1823 for(i=0; i<ArraySize(azProhibitedFunctions); i++){
1824 if( sqlite3_stricmp(zA1, azProhibitedFunctions[i])==0 ){
1825 failIfSafeMode(p, "cannot use the %s() function in safe mode",
1826 azProhibitedFunctions[i]);
1827 }
1828 }
1829 break;
1830 }
1831 }
1832 return SQLITE_OK;
1833}
1834
1835/*
drh2ce15c32017-07-11 13:34:40 +00001836** When the ".auth ON" is set, the following authorizer callback is
1837** invoked. It always returns SQLITE_OK.
1838*/
1839static int shellAuth(
1840 void *pClientData,
1841 int op,
1842 const char *zA1,
1843 const char *zA2,
1844 const char *zA3,
1845 const char *zA4
1846){
1847 ShellState *p = (ShellState*)pClientData;
1848 static const char *azAction[] = { 0,
1849 "CREATE_INDEX", "CREATE_TABLE", "CREATE_TEMP_INDEX",
1850 "CREATE_TEMP_TABLE", "CREATE_TEMP_TRIGGER", "CREATE_TEMP_VIEW",
1851 "CREATE_TRIGGER", "CREATE_VIEW", "DELETE",
1852 "DROP_INDEX", "DROP_TABLE", "DROP_TEMP_INDEX",
1853 "DROP_TEMP_TABLE", "DROP_TEMP_TRIGGER", "DROP_TEMP_VIEW",
1854 "DROP_TRIGGER", "DROP_VIEW", "INSERT",
1855 "PRAGMA", "READ", "SELECT",
1856 "TRANSACTION", "UPDATE", "ATTACH",
1857 "DETACH", "ALTER_TABLE", "REINDEX",
1858 "ANALYZE", "CREATE_VTABLE", "DROP_VTABLE",
1859 "FUNCTION", "SAVEPOINT", "RECURSIVE"
1860 };
1861 int i;
1862 const char *az[4];
1863 az[0] = zA1;
1864 az[1] = zA2;
1865 az[2] = zA3;
1866 az[3] = zA4;
1867 utf8_printf(p->out, "authorizer: %s", azAction[op]);
1868 for(i=0; i<4; i++){
1869 raw_printf(p->out, " ");
1870 if( az[i] ){
1871 output_c_string(p->out, az[i]);
1872 }else{
1873 raw_printf(p->out, "NULL");
1874 }
1875 }
1876 raw_printf(p->out, "\n");
drhb97e2ad2021-08-26 18:31:39 +00001877 if( p->bSafeMode ) (void)safeModeAuth(pClientData, op, zA1, zA2, zA3, zA4);
drh2ce15c32017-07-11 13:34:40 +00001878 return SQLITE_OK;
1879}
1880#endif
1881
1882/*
1883** Print a schema statement. Part of MODE_Semi and MODE_Pretty output.
1884**
1885** This routine converts some CREATE TABLE statements for shadow tables
1886** in FTS3/4/5 into CREATE TABLE IF NOT EXISTS statements.
1887*/
1888static void printSchemaLine(FILE *out, const char *z, const char *zTail){
drh0a0536a2019-05-09 18:13:30 +00001889 if( z==0 ) return;
1890 if( zTail==0 ) return;
drh2ce15c32017-07-11 13:34:40 +00001891 if( sqlite3_strglob("CREATE TABLE ['\"]*", z)==0 ){
1892 utf8_printf(out, "CREATE TABLE IF NOT EXISTS %s%s", z+13, zTail);
1893 }else{
1894 utf8_printf(out, "%s%s", z, zTail);
1895 }
1896}
1897static void printSchemaLineN(FILE *out, char *z, int n, const char *zTail){
1898 char c = z[n];
1899 z[n] = 0;
1900 printSchemaLine(out, z, zTail);
1901 z[n] = c;
1902}
1903
1904/*
drh11be81d2018-01-06 15:46:20 +00001905** Return true if string z[] has nothing but whitespace and comments to the
1906** end of the first line.
1907*/
1908static int wsToEol(const char *z){
1909 int i;
1910 for(i=0; z[i]; i++){
1911 if( z[i]=='\n' ) return 1;
1912 if( IsSpace(z[i]) ) continue;
1913 if( z[i]=='-' && z[i+1]=='-' ) return 1;
1914 return 0;
1915 }
1916 return 1;
1917}
drh4b5345c2018-04-24 13:07:40 +00001918
1919/*
1920** Add a new entry to the EXPLAIN QUERY PLAN data
1921*/
drhe2ca99c2018-05-02 00:33:43 +00001922static void eqp_append(ShellState *p, int iEqpId, int p2, const char *zText){
drh4b5345c2018-04-24 13:07:40 +00001923 EQPGraphRow *pNew;
1924 int nText = strlen30(zText);
drhe2ca99c2018-05-02 00:33:43 +00001925 if( p->autoEQPtest ){
1926 utf8_printf(p->out, "%d,%d,%s\n", iEqpId, p2, zText);
1927 }
drh4b5345c2018-04-24 13:07:40 +00001928 pNew = sqlite3_malloc64( sizeof(*pNew) + nText );
drhe3e25652021-12-16 13:29:28 +00001929 shell_check_oom(pNew);
drhe2ca99c2018-05-02 00:33:43 +00001930 pNew->iEqpId = iEqpId;
1931 pNew->iParentId = p2;
drh4b5345c2018-04-24 13:07:40 +00001932 memcpy(pNew->zText, zText, nText+1);
1933 pNew->pNext = 0;
1934 if( p->sGraph.pLast ){
1935 p->sGraph.pLast->pNext = pNew;
1936 }else{
1937 p->sGraph.pRow = pNew;
1938 }
1939 p->sGraph.pLast = pNew;
1940}
1941
1942/*
1943** Free and reset the EXPLAIN QUERY PLAN data that has been collected
1944** in p->sGraph.
1945*/
1946static void eqp_reset(ShellState *p){
1947 EQPGraphRow *pRow, *pNext;
1948 for(pRow = p->sGraph.pRow; pRow; pRow = pNext){
1949 pNext = pRow->pNext;
1950 sqlite3_free(pRow);
1951 }
1952 memset(&p->sGraph, 0, sizeof(p->sGraph));
1953}
1954
drhe2ca99c2018-05-02 00:33:43 +00001955/* Return the next EXPLAIN QUERY PLAN line with iEqpId that occurs after
drh4b5345c2018-04-24 13:07:40 +00001956** pOld, or return the first such line if pOld is NULL
1957*/
drhe2ca99c2018-05-02 00:33:43 +00001958static EQPGraphRow *eqp_next_row(ShellState *p, int iEqpId, EQPGraphRow *pOld){
drh4b5345c2018-04-24 13:07:40 +00001959 EQPGraphRow *pRow = pOld ? pOld->pNext : p->sGraph.pRow;
drhe2ca99c2018-05-02 00:33:43 +00001960 while( pRow && pRow->iParentId!=iEqpId ) pRow = pRow->pNext;
drh4b5345c2018-04-24 13:07:40 +00001961 return pRow;
1962}
1963
drhe2ca99c2018-05-02 00:33:43 +00001964/* Render a single level of the graph that has iEqpId as its parent. Called
drh4b5345c2018-04-24 13:07:40 +00001965** recursively to render sublevels.
1966*/
drhe2ca99c2018-05-02 00:33:43 +00001967static void eqp_render_level(ShellState *p, int iEqpId){
drh4b5345c2018-04-24 13:07:40 +00001968 EQPGraphRow *pRow, *pNext;
drh4b5345c2018-04-24 13:07:40 +00001969 int n = strlen30(p->sGraph.zPrefix);
1970 char *z;
drhe2ca99c2018-05-02 00:33:43 +00001971 for(pRow = eqp_next_row(p, iEqpId, 0); pRow; pRow = pNext){
1972 pNext = eqp_next_row(p, iEqpId, pRow);
drh4b5345c2018-04-24 13:07:40 +00001973 z = pRow->zText;
drhe2754c12019-08-26 12:50:01 +00001974 utf8_printf(p->out, "%s%s%s\n", p->sGraph.zPrefix,
1975 pNext ? "|--" : "`--", z);
drhe2188f02018-05-07 11:37:34 +00001976 if( n<(int)sizeof(p->sGraph.zPrefix)-7 ){
drh4b5345c2018-04-24 13:07:40 +00001977 memcpy(&p->sGraph.zPrefix[n], pNext ? "| " : " ", 4);
drhe2ca99c2018-05-02 00:33:43 +00001978 eqp_render_level(p, pRow->iEqpId);
drh4b5345c2018-04-24 13:07:40 +00001979 p->sGraph.zPrefix[n] = 0;
1980 }
1981 }
1982}
1983
1984/*
1985** Display and reset the EXPLAIN QUERY PLAN data
1986*/
1987static void eqp_render(ShellState *p){
1988 EQPGraphRow *pRow = p->sGraph.pRow;
1989 if( pRow ){
1990 if( pRow->zText[0]=='-' ){
1991 if( pRow->pNext==0 ){
1992 eqp_reset(p);
1993 return;
1994 }
1995 utf8_printf(p->out, "%s\n", pRow->zText+3);
1996 p->sGraph.pRow = pRow->pNext;
1997 sqlite3_free(pRow);
1998 }else{
1999 utf8_printf(p->out, "QUERY PLAN\n");
2000 }
2001 p->sGraph.zPrefix[0] = 0;
2002 eqp_render_level(p, 0);
2003 eqp_reset(p);
2004 }
2005}
drh11be81d2018-01-06 15:46:20 +00002006
drh569b1d92019-02-05 20:51:41 +00002007#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
drh11be81d2018-01-06 15:46:20 +00002008/*
drh3f83f592019-02-04 14:53:18 +00002009** Progress handler callback.
2010*/
2011static int progress_handler(void *pClientData) {
2012 ShellState *p = (ShellState*)pClientData;
2013 p->nProgress++;
2014 if( p->nProgress>=p->mxProgress && p->mxProgress>0 ){
2015 raw_printf(p->out, "Progress limit reached (%u)\n", p->nProgress);
drhfc4eeef2019-02-05 19:48:46 +00002016 if( p->flgProgress & SHELL_PROGRESS_RESET ) p->nProgress = 0;
2017 if( p->flgProgress & SHELL_PROGRESS_ONCE ) p->mxProgress = 0;
drh3f83f592019-02-04 14:53:18 +00002018 return 1;
2019 }
drhfc4eeef2019-02-05 19:48:46 +00002020 if( (p->flgProgress & SHELL_PROGRESS_QUIET)==0 ){
drh3f83f592019-02-04 14:53:18 +00002021 raw_printf(p->out, "Progress %u\n", p->nProgress);
2022 }
2023 return 0;
2024}
drh569b1d92019-02-05 20:51:41 +00002025#endif /* SQLITE_OMIT_PROGRESS_CALLBACK */
drh3f83f592019-02-04 14:53:18 +00002026
2027/*
drh30c54a02020-05-28 23:49:50 +00002028** Print N dashes
2029*/
2030static void print_dashes(FILE *out, int N){
2031 const char zDash[] = "--------------------------------------------------";
2032 const int nDash = sizeof(zDash) - 1;
2033 while( N>nDash ){
2034 fputs(zDash, out);
2035 N -= nDash;
2036 }
2037 raw_printf(out, "%.*s", N, zDash);
2038}
2039
2040/*
drh0908e382020-06-04 18:05:39 +00002041** Print a markdown or table-style row separator using ascii-art
drh30c54a02020-05-28 23:49:50 +00002042*/
2043static void print_row_separator(
2044 ShellState *p,
2045 int nArg,
2046 const char *zSep
2047){
2048 int i;
drh0908e382020-06-04 18:05:39 +00002049 if( nArg>0 ){
drh30c54a02020-05-28 23:49:50 +00002050 fputs(zSep, p->out);
drh0908e382020-06-04 18:05:39 +00002051 print_dashes(p->out, p->actualWidth[0]+2);
2052 for(i=1; i<nArg; i++){
2053 fputs(zSep, p->out);
2054 print_dashes(p->out, p->actualWidth[i]+2);
2055 }
2056 fputs(zSep, p->out);
drh30c54a02020-05-28 23:49:50 +00002057 }
drh30c54a02020-05-28 23:49:50 +00002058 fputs("\n", p->out);
2059}
2060
2061/*
drh2ce15c32017-07-11 13:34:40 +00002062** This is the callback routine that the shell
2063** invokes for each row of a query result.
2064*/
2065static int shell_callback(
2066 void *pArg,
2067 int nArg, /* Number of result columns */
2068 char **azArg, /* Text of each result column */
2069 char **azCol, /* Column names */
drhd6f25242020-05-29 12:31:53 +00002070 int *aiType /* Column types. Might be NULL */
drh2ce15c32017-07-11 13:34:40 +00002071){
2072 int i;
2073 ShellState *p = (ShellState*)pArg;
2074
drhb3c45232017-08-28 14:33:27 +00002075 if( azArg==0 ) return 0;
drh2ce15c32017-07-11 13:34:40 +00002076 switch( p->cMode ){
drh5d88be82021-12-09 16:17:43 +00002077 case MODE_Count:
2078 case MODE_Off: {
2079 break;
2080 }
drh2ce15c32017-07-11 13:34:40 +00002081 case MODE_Line: {
2082 int w = 5;
2083 if( azArg==0 ) break;
2084 for(i=0; i<nArg; i++){
2085 int len = strlen30(azCol[i] ? azCol[i] : "");
2086 if( len>w ) w = len;
2087 }
2088 if( p->cnt++>0 ) utf8_printf(p->out, "%s", p->rowSeparator);
2089 for(i=0; i<nArg; i++){
2090 utf8_printf(p->out,"%*s = %s%s", w, azCol[i],
2091 azArg[i] ? azArg[i] : p->nullValue, p->rowSeparator);
2092 }
2093 break;
2094 }
drh8c748632020-05-29 16:15:58 +00002095 case MODE_Explain: {
2096 static const int aExplainWidth[] = {4, 13, 4, 4, 4, 13, 2, 13};
2097 if( nArg>ArraySize(aExplainWidth) ){
2098 nArg = ArraySize(aExplainWidth);
drh2ce15c32017-07-11 13:34:40 +00002099 }
2100 if( p->cnt++==0 ){
2101 for(i=0; i<nArg; i++){
drh8c748632020-05-29 16:15:58 +00002102 int w = aExplainWidth[i];
2103 utf8_width_print(p->out, w, azCol[i]);
2104 fputs(i==nArg-1 ? "\n" : " ", p->out);
drh2ce15c32017-07-11 13:34:40 +00002105 }
drhe566ceb2020-05-30 15:34:49 +00002106 for(i=0; i<nArg; i++){
2107 int w = aExplainWidth[i];
2108 print_dashes(p->out, w);
2109 fputs(i==nArg-1 ? "\n" : " ", p->out);
2110 }
drh2ce15c32017-07-11 13:34:40 +00002111 }
2112 if( azArg==0 ) break;
2113 for(i=0; i<nArg; i++){
drh8c748632020-05-29 16:15:58 +00002114 int w = aExplainWidth[i];
drhaa556b02021-01-13 12:59:20 +00002115 if( i==nArg-1 ) w = 0;
drh8c748632020-05-29 16:15:58 +00002116 if( azArg[i] && strlenChar(azArg[i])>w ){
2117 w = strlenChar(azArg[i]);
drh2ce15c32017-07-11 13:34:40 +00002118 }
drh8c748632020-05-29 16:15:58 +00002119 if( i==1 && p->aiIndent && p->pStmt ){
2120 if( p->iIndent<p->nIndent ){
2121 utf8_printf(p->out, "%*.s", p->aiIndent[p->iIndent], "");
drh2ce15c32017-07-11 13:34:40 +00002122 }
drh8c748632020-05-29 16:15:58 +00002123 p->iIndent++;
drh2ce15c32017-07-11 13:34:40 +00002124 }
2125 utf8_width_print(p->out, w, azArg[i] ? azArg[i] : p->nullValue);
drh8c748632020-05-29 16:15:58 +00002126 fputs(i==nArg-1 ? "\n" : " ", p->out);
drh2ce15c32017-07-11 13:34:40 +00002127 }
2128 break;
2129 }
2130 case MODE_Semi: { /* .schema and .fullschema output */
2131 printSchemaLine(p->out, azArg[0], ";\n");
2132 break;
2133 }
2134 case MODE_Pretty: { /* .schema and .fullschema with --indent */
2135 char *z;
2136 int j;
2137 int nParen = 0;
2138 char cEnd = 0;
2139 char c;
2140 int nLine = 0;
2141 assert( nArg==1 );
2142 if( azArg[0]==0 ) break;
2143 if( sqlite3_strlike("CREATE VIEW%", azArg[0], 0)==0
2144 || sqlite3_strlike("CREATE TRIG%", azArg[0], 0)==0
2145 ){
2146 utf8_printf(p->out, "%s;\n", azArg[0]);
2147 break;
2148 }
2149 z = sqlite3_mprintf("%s", azArg[0]);
drhe3e25652021-12-16 13:29:28 +00002150 shell_check_oom(z);
drh2ce15c32017-07-11 13:34:40 +00002151 j = 0;
2152 for(i=0; IsSpace(z[i]); i++){}
2153 for(; (c = z[i])!=0; i++){
2154 if( IsSpace(c) ){
drhc3cbd672017-10-05 19:12:10 +00002155 if( z[j-1]=='\r' ) z[j-1] = '\n';
drh2ce15c32017-07-11 13:34:40 +00002156 if( IsSpace(z[j-1]) || z[j-1]=='(' ) continue;
2157 }else if( (c=='(' || c==')') && j>0 && IsSpace(z[j-1]) ){
2158 j--;
2159 }
2160 z[j++] = c;
2161 }
2162 while( j>0 && IsSpace(z[j-1]) ){ j--; }
2163 z[j] = 0;
2164 if( strlen30(z)>=79 ){
drhe2754c12019-08-26 12:50:01 +00002165 for(i=j=0; (c = z[i])!=0; i++){ /* Copy from z[i] back to z[j] */
drh2ce15c32017-07-11 13:34:40 +00002166 if( c==cEnd ){
2167 cEnd = 0;
2168 }else if( c=='"' || c=='\'' || c=='`' ){
2169 cEnd = c;
2170 }else if( c=='[' ){
2171 cEnd = ']';
drh11be81d2018-01-06 15:46:20 +00002172 }else if( c=='-' && z[i+1]=='-' ){
2173 cEnd = '\n';
drh2ce15c32017-07-11 13:34:40 +00002174 }else if( c=='(' ){
2175 nParen++;
2176 }else if( c==')' ){
2177 nParen--;
2178 if( nLine>0 && nParen==0 && j>0 ){
2179 printSchemaLineN(p->out, z, j, "\n");
2180 j = 0;
2181 }
2182 }
2183 z[j++] = c;
drh11be81d2018-01-06 15:46:20 +00002184 if( nParen==1 && cEnd==0
2185 && (c=='(' || c=='\n' || (c==',' && !wsToEol(z+i+1)))
2186 ){
drh2ce15c32017-07-11 13:34:40 +00002187 if( c=='\n' ) j--;
2188 printSchemaLineN(p->out, z, j, "\n ");
2189 j = 0;
2190 nLine++;
2191 while( IsSpace(z[i+1]) ){ i++; }
2192 }
2193 }
2194 z[j] = 0;
2195 }
2196 printSchemaLine(p->out, z, ";\n");
2197 sqlite3_free(z);
2198 break;
2199 }
2200 case MODE_List: {
2201 if( p->cnt++==0 && p->showHeader ){
2202 for(i=0; i<nArg; i++){
2203 utf8_printf(p->out,"%s%s",azCol[i],
2204 i==nArg-1 ? p->rowSeparator : p->colSeparator);
2205 }
2206 }
2207 if( azArg==0 ) break;
2208 for(i=0; i<nArg; i++){
2209 char *z = azArg[i];
2210 if( z==0 ) z = p->nullValue;
2211 utf8_printf(p->out, "%s", z);
2212 if( i<nArg-1 ){
2213 utf8_printf(p->out, "%s", p->colSeparator);
2214 }else{
2215 utf8_printf(p->out, "%s", p->rowSeparator);
2216 }
2217 }
2218 break;
2219 }
2220 case MODE_Html: {
2221 if( p->cnt++==0 && p->showHeader ){
2222 raw_printf(p->out,"<TR>");
2223 for(i=0; i<nArg; i++){
2224 raw_printf(p->out,"<TH>");
2225 output_html_string(p->out, azCol[i]);
2226 raw_printf(p->out,"</TH>\n");
2227 }
2228 raw_printf(p->out,"</TR>\n");
2229 }
2230 if( azArg==0 ) break;
2231 raw_printf(p->out,"<TR>");
2232 for(i=0; i<nArg; i++){
2233 raw_printf(p->out,"<TD>");
2234 output_html_string(p->out, azArg[i] ? azArg[i] : p->nullValue);
2235 raw_printf(p->out,"</TD>\n");
2236 }
2237 raw_printf(p->out,"</TR>\n");
2238 break;
2239 }
2240 case MODE_Tcl: {
2241 if( p->cnt++==0 && p->showHeader ){
2242 for(i=0; i<nArg; i++){
2243 output_c_string(p->out,azCol[i] ? azCol[i] : "");
2244 if(i<nArg-1) utf8_printf(p->out, "%s", p->colSeparator);
2245 }
2246 utf8_printf(p->out, "%s", p->rowSeparator);
2247 }
2248 if( azArg==0 ) break;
2249 for(i=0; i<nArg; i++){
2250 output_c_string(p->out, azArg[i] ? azArg[i] : p->nullValue);
2251 if(i<nArg-1) utf8_printf(p->out, "%s", p->colSeparator);
2252 }
2253 utf8_printf(p->out, "%s", p->rowSeparator);
2254 break;
2255 }
2256 case MODE_Csv: {
2257 setBinaryMode(p->out, 1);
2258 if( p->cnt++==0 && p->showHeader ){
2259 for(i=0; i<nArg; i++){
2260 output_csv(p, azCol[i] ? azCol[i] : "", i<nArg-1);
2261 }
2262 utf8_printf(p->out, "%s", p->rowSeparator);
2263 }
2264 if( nArg>0 ){
2265 for(i=0; i<nArg; i++){
2266 output_csv(p, azArg[i], i<nArg-1);
2267 }
2268 utf8_printf(p->out, "%s", p->rowSeparator);
2269 }
2270 setTextMode(p->out, 1);
2271 break;
2272 }
2273 case MODE_Insert: {
2274 if( azArg==0 ) break;
2275 utf8_printf(p->out,"INSERT INTO %s",p->zDestTable);
2276 if( p->showHeader ){
2277 raw_printf(p->out,"(");
2278 for(i=0; i<nArg; i++){
2279 if( i>0 ) raw_printf(p->out, ",");
2280 if( quoteChar(azCol[i]) ){
2281 char *z = sqlite3_mprintf("\"%w\"", azCol[i]);
drhe3e25652021-12-16 13:29:28 +00002282 shell_check_oom(z);
drh2ce15c32017-07-11 13:34:40 +00002283 utf8_printf(p->out, "%s", z);
2284 sqlite3_free(z);
2285 }else{
2286 raw_printf(p->out, "%s", azCol[i]);
2287 }
2288 }
2289 raw_printf(p->out,")");
2290 }
2291 p->cnt++;
2292 for(i=0; i<nArg; i++){
2293 raw_printf(p->out, i>0 ? "," : " VALUES(");
2294 if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){
2295 utf8_printf(p->out,"NULL");
2296 }else if( aiType && aiType[i]==SQLITE_TEXT ){
2297 if( ShellHasFlag(p, SHFLG_Newlines) ){
2298 output_quoted_string(p->out, azArg[i]);
2299 }else{
2300 output_quoted_escaped_string(p->out, azArg[i]);
2301 }
2302 }else if( aiType && aiType[i]==SQLITE_INTEGER ){
2303 utf8_printf(p->out,"%s", azArg[i]);
2304 }else if( aiType && aiType[i]==SQLITE_FLOAT ){
2305 char z[50];
2306 double r = sqlite3_column_double(p->pStmt, i);
drh2f1f8802018-06-13 17:19:20 +00002307 sqlite3_uint64 ur;
2308 memcpy(&ur,&r,sizeof(r));
2309 if( ur==0x7ff0000000000000LL ){
2310 raw_printf(p->out, "1e999");
2311 }else if( ur==0xfff0000000000000LL ){
2312 raw_printf(p->out, "-1e999");
2313 }else{
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**
2947** * For each "Goto", if the jump destination is earlier in the program
2948** and ends on one of:
2949** Yield SeekGt SeekLt RowSetRead Rewind
2950** or if the P1 parameter is one instead of zero,
2951** then indent all opcodes between the earlier instruction
2952** and "Goto" by 2 spaces.
2953*/
2954static void explain_data_prepare(ShellState *p, sqlite3_stmt *pSql){
2955 const char *zSql; /* The text of the SQL statement */
2956 const char *z; /* Used to check if this is an EXPLAIN */
2957 int *abYield = 0; /* True if op is an OP_Yield */
2958 int nAlloc = 0; /* Allocated size of p->aiIndent[], abYield */
2959 int iOp; /* Index of operation in p->aiIndent[] */
2960
drhf1949b62018-06-07 17:32:59 +00002961 const char *azNext[] = { "Next", "Prev", "VPrev", "VNext", "SorterNext", 0 };
drh2ce15c32017-07-11 13:34:40 +00002962 const char *azYield[] = { "Yield", "SeekLT", "SeekGT", "RowSetRead",
2963 "Rewind", 0 };
2964 const char *azGoto[] = { "Goto", 0 };
2965
2966 /* Try to figure out if this is really an EXPLAIN statement. If this
2967 ** cannot be verified, return early. */
2968 if( sqlite3_column_count(pSql)!=8 ){
2969 p->cMode = p->mode;
2970 return;
2971 }
2972 zSql = sqlite3_sql(pSql);
2973 if( zSql==0 ) return;
2974 for(z=zSql; *z==' ' || *z=='\t' || *z=='\n' || *z=='\f' || *z=='\r'; z++);
2975 if( sqlite3_strnicmp(z, "explain", 7) ){
2976 p->cMode = p->mode;
2977 return;
2978 }
2979
2980 for(iOp=0; SQLITE_ROW==sqlite3_step(pSql); iOp++){
2981 int i;
2982 int iAddr = sqlite3_column_int(pSql, 0);
2983 const char *zOp = (const char*)sqlite3_column_text(pSql, 1);
2984
2985 /* Set p2 to the P2 field of the current opcode. Then, assuming that
2986 ** p2 is an instruction address, set variable p2op to the index of that
2987 ** instruction in the aiIndent[] array. p2 and p2op may be different if
2988 ** the current instruction is part of a sub-program generated by an
2989 ** SQL trigger or foreign key. */
2990 int p2 = sqlite3_column_int(pSql, 3);
2991 int p2op = (p2 + (iOp-iAddr));
2992
2993 /* Grow the p->aiIndent array as required */
2994 if( iOp>=nAlloc ){
2995 if( iOp==0 ){
2996 /* Do further verfication that this is explain output. Abort if
2997 ** it is not */
2998 static const char *explainCols[] = {
2999 "addr", "opcode", "p1", "p2", "p3", "p4", "p5", "comment" };
3000 int jj;
3001 for(jj=0; jj<ArraySize(explainCols); jj++){
3002 if( strcmp(sqlite3_column_name(pSql,jj),explainCols[jj])!=0 ){
3003 p->cMode = p->mode;
3004 sqlite3_reset(pSql);
3005 return;
3006 }
3007 }
3008 }
3009 nAlloc += 100;
3010 p->aiIndent = (int*)sqlite3_realloc64(p->aiIndent, nAlloc*sizeof(int));
drhe3e25652021-12-16 13:29:28 +00003011 shell_check_oom(p->aiIndent);
drh2ce15c32017-07-11 13:34:40 +00003012 abYield = (int*)sqlite3_realloc64(abYield, nAlloc*sizeof(int));
drhe3e25652021-12-16 13:29:28 +00003013 shell_check_oom(abYield);
drh2ce15c32017-07-11 13:34:40 +00003014 }
3015 abYield[iOp] = str_in_array(zOp, azYield);
3016 p->aiIndent[iOp] = 0;
3017 p->nIndent = iOp+1;
3018
3019 if( str_in_array(zOp, azNext) ){
3020 for(i=p2op; i<iOp; i++) p->aiIndent[i] += 2;
3021 }
3022 if( str_in_array(zOp, azGoto) && p2op<p->nIndent
3023 && (abYield[p2op] || sqlite3_column_int(pSql, 2))
3024 ){
3025 for(i=p2op; i<iOp; i++) p->aiIndent[i] += 2;
3026 }
3027 }
3028
3029 p->iIndent = 0;
3030 sqlite3_free(abYield);
3031 sqlite3_reset(pSql);
3032}
3033
3034/*
3035** Free the array allocated by explain_data_prepare().
3036*/
3037static void explain_data_delete(ShellState *p){
3038 sqlite3_free(p->aiIndent);
3039 p->aiIndent = 0;
3040 p->nIndent = 0;
3041 p->iIndent = 0;
3042}
3043
3044/*
3045** Disable and restore .wheretrace and .selecttrace settings.
3046*/
drhc0622a42020-12-04 01:17:57 +00003047static unsigned int savedSelectTrace;
3048static unsigned int savedWhereTrace;
drh2ce15c32017-07-11 13:34:40 +00003049static void disable_debug_trace_modes(void){
drh0a2fb792020-12-04 16:58:20 +00003050 unsigned int zero = 0;
drhc0622a42020-12-04 01:17:57 +00003051 sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 0, &savedSelectTrace);
drh0a2fb792020-12-04 16:58:20 +00003052 sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 1, &zero);
drhc0622a42020-12-04 01:17:57 +00003053 sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 2, &savedWhereTrace);
drh0a2fb792020-12-04 16:58:20 +00003054 sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 3, &zero);
drh2ce15c32017-07-11 13:34:40 +00003055}
3056static void restore_debug_trace_modes(void){
drhc0622a42020-12-04 01:17:57 +00003057 sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 1, &savedSelectTrace);
3058 sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 3, &savedWhereTrace);
drh2ce15c32017-07-11 13:34:40 +00003059}
3060
drh9cb02642019-02-28 20:10:52 +00003061/* Create the TEMP table used to store parameter bindings */
3062static void bind_table_init(ShellState *p){
drh346f4e22019-03-25 21:35:41 +00003063 int wrSchema = 0;
drh4b86e202020-01-19 20:37:26 +00003064 int defensiveMode = 0;
3065 sqlite3_db_config(p->db, SQLITE_DBCONFIG_DEFENSIVE, -1, &defensiveMode);
3066 sqlite3_db_config(p->db, SQLITE_DBCONFIG_DEFENSIVE, 0, 0);
drh346f4e22019-03-25 21:35:41 +00003067 sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, -1, &wrSchema);
3068 sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, 1, 0);
drh9cb02642019-02-28 20:10:52 +00003069 sqlite3_exec(p->db,
drh65c29fd2019-03-25 21:56:26 +00003070 "CREATE TABLE IF NOT EXISTS temp.sqlite_parameters(\n"
drh9cb02642019-02-28 20:10:52 +00003071 " key TEXT PRIMARY KEY,\n"
larrybrdabada62021-04-04 12:52:58 +00003072 " value\n"
drh9cb02642019-02-28 20:10:52 +00003073 ") WITHOUT ROWID;",
3074 0, 0, 0);
drh346f4e22019-03-25 21:35:41 +00003075 sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, wrSchema, 0);
drh4b86e202020-01-19 20:37:26 +00003076 sqlite3_db_config(p->db, SQLITE_DBCONFIG_DEFENSIVE, defensiveMode, 0);
drh9cb02642019-02-28 20:10:52 +00003077}
3078
drh8b738d02019-02-25 18:43:54 +00003079/*
3080** Bind parameters on a prepared statement.
3081**
3082** Parameter bindings are taken from a TEMP table of the form:
3083**
drh1cb02632019-03-25 22:05:22 +00003084** CREATE TEMP TABLE sqlite_parameters(key TEXT PRIMARY KEY, value)
drh8b738d02019-02-25 18:43:54 +00003085** WITHOUT ROWID;
3086**
drh91654b22020-04-02 13:21:10 +00003087** No bindings occur if this table does not exist. The name of the table
3088** begins with "sqlite_" so that it will not collide with ordinary application
3089** tables. The table must be in the TEMP schema.
drh8b738d02019-02-25 18:43:54 +00003090*/
3091static void bind_prepared_stmt(ShellState *pArg, sqlite3_stmt *pStmt){
3092 int nVar;
3093 int i;
3094 int rc;
3095 sqlite3_stmt *pQ = 0;
3096
3097 nVar = sqlite3_bind_parameter_count(pStmt);
3098 if( nVar==0 ) return; /* Nothing to do */
drh65c29fd2019-03-25 21:56:26 +00003099 if( sqlite3_table_column_metadata(pArg->db, "TEMP", "sqlite_parameters",
drh8b738d02019-02-25 18:43:54 +00003100 "key", 0, 0, 0, 0, 0)!=SQLITE_OK ){
3101 return; /* Parameter table does not exist */
3102 }
3103 rc = sqlite3_prepare_v2(pArg->db,
drh65c29fd2019-03-25 21:56:26 +00003104 "SELECT value FROM temp.sqlite_parameters"
drh8b738d02019-02-25 18:43:54 +00003105 " WHERE key=?1", -1, &pQ, 0);
3106 if( rc || pQ==0 ) return;
3107 for(i=1; i<=nVar; i++){
3108 char zNum[30];
3109 const char *zVar = sqlite3_bind_parameter_name(pStmt, i);
3110 if( zVar==0 ){
3111 sqlite3_snprintf(sizeof(zNum),zNum,"?%d",i);
3112 zVar = zNum;
3113 }
3114 sqlite3_bind_text(pQ, 1, zVar, -1, SQLITE_STATIC);
3115 if( sqlite3_step(pQ)==SQLITE_ROW ){
3116 sqlite3_bind_value(pStmt, i, sqlite3_column_value(pQ, 0));
3117 }else{
3118 sqlite3_bind_null(pStmt, i);
3119 }
3120 sqlite3_reset(pQ);
3121 }
3122 sqlite3_finalize(pQ);
3123}
3124
drh30c54a02020-05-28 23:49:50 +00003125/*
drh0908e382020-06-04 18:05:39 +00003126** UTF8 box-drawing characters. Imagine box lines like this:
3127**
3128** 1
3129** |
3130** 4 --+-- 2
3131** |
3132** 3
3133**
3134** Each box characters has between 2 and 4 of the lines leading from
3135** the center. The characters are here identified by the numbers of
3136** their corresponding lines.
3137*/
3138#define BOX_24 "\342\224\200" /* U+2500 --- */
3139#define BOX_13 "\342\224\202" /* U+2502 | */
3140#define BOX_23 "\342\224\214" /* U+250c ,- */
3141#define BOX_34 "\342\224\220" /* U+2510 -, */
3142#define BOX_12 "\342\224\224" /* U+2514 '- */
3143#define BOX_14 "\342\224\230" /* U+2518 -' */
3144#define BOX_123 "\342\224\234" /* U+251c |- */
3145#define BOX_134 "\342\224\244" /* U+2524 -| */
3146#define BOX_234 "\342\224\254" /* U+252c -,- */
3147#define BOX_124 "\342\224\264" /* U+2534 -'- */
3148#define BOX_1234 "\342\224\274" /* U+253c -|- */
3149
3150/* Draw horizontal line N characters long using unicode box
3151** characters
3152*/
3153static void print_box_line(FILE *out, int N){
3154 const char zDash[] =
3155 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24
3156 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24;
3157 const int nDash = sizeof(zDash) - 1;
3158 N *= 3;
3159 while( N>nDash ){
3160 utf8_printf(out, zDash);
3161 N -= nDash;
3162 }
3163 utf8_printf(out, "%.*s", N, zDash);
3164}
3165
3166/*
3167** Draw a horizontal separator for a MODE_Box table.
3168*/
3169static void print_box_row_separator(
3170 ShellState *p,
3171 int nArg,
3172 const char *zSep1,
3173 const char *zSep2,
3174 const char *zSep3
3175){
3176 int i;
3177 if( nArg>0 ){
3178 utf8_printf(p->out, "%s", zSep1);
3179 print_box_line(p->out, p->actualWidth[0]+2);
3180 for(i=1; i<nArg; i++){
3181 utf8_printf(p->out, "%s", zSep2);
3182 print_box_line(p->out, p->actualWidth[i]+2);
3183 }
3184 utf8_printf(p->out, "%s", zSep3);
3185 }
3186 fputs("\n", p->out);
3187}
3188
drh09a39ed2022-01-30 21:09:03 +00003189/*
3190** z[] is a line of text that is to be displayed the .mode box or table or
3191** similar tabular formats. z[] might contain control characters such
3192** as \n, \t, \f, or \r.
3193**
3194** Compute characters to display on the first line of z[]. Stop at the
3195** first \r, \n, or \f. Expand \t into spaces. Return a copy (obtained
larrybrcc4d55c2022-02-01 02:50:45 +00003196** from malloc()) of that first line, which caller should free sometime.
3197** Write anything to display on the next line into *pzTail. If this is
3198** the last line, write a NULL into *pzTail. (*pzTail is not allocated.)
drh09a39ed2022-01-30 21:09:03 +00003199*/
3200static char *translateForDisplayAndDup(
drhca1776b2022-02-01 12:28:17 +00003201 const unsigned char *z, /* Input text to be transformed */
3202 const unsigned char **pzTail, /* OUT: Tail of the input for next line */
3203 int mxWidth, /* Max width. 0 means no limit */
3204 u8 bWordWrap /* If true, avoid breaking mid-word */
drh09a39ed2022-01-30 21:09:03 +00003205){
drhca1776b2022-02-01 12:28:17 +00003206 int i; /* Input bytes consumed */
3207 int j; /* Output bytes generated */
3208 int k; /* Input bytes to be displayed */
3209 int n; /* Output column number */
3210 unsigned char *zOut; /* Output text */
3211
drh09a39ed2022-01-30 21:09:03 +00003212 if( z==0 ){
3213 *pzTail = 0;
3214 return 0;
3215 }
3216 if( mxWidth<0 ) mxWidth = -mxWidth;
3217 if( mxWidth==0 ) mxWidth = 1000000;
drhca1776b2022-02-01 12:28:17 +00003218 i = j = n = 0;
drh09a39ed2022-01-30 21:09:03 +00003219 while( n<mxWidth ){
3220 if( z[i]>=' ' ){
3221 n++;
drhb6172192022-01-31 10:55:50 +00003222 do{ i++; j++; }while( (z[i]&0xc0)==0x80 );
drh09a39ed2022-01-30 21:09:03 +00003223 continue;
3224 }
3225 if( z[i]=='\t' ){
drhb6172192022-01-31 10:55:50 +00003226 do{
3227 n++;
3228 j++;
3229 }while( (n&7)!=0 && n<mxWidth );
drh09a39ed2022-01-30 21:09:03 +00003230 i++;
3231 continue;
3232 }
3233 break;
3234 }
drhca1776b2022-02-01 12:28:17 +00003235 if( n>=mxWidth && bWordWrap ){
3236 /* Perhaps try to back up to a better place to break the line */
3237 for(k=i; k>i/2; k--){
3238 if( isspace(z[k-1]) ) break;
3239 }
3240 if( k<=i/2 ){
3241 for(k=i; k>i/2; k--){
drhe66532a2022-02-01 13:17:11 +00003242 if( isalnum(z[k-1])!=isalnum(z[k]) && (z[k]&0xc0)!=0x80 ) break;
drhca1776b2022-02-01 12:28:17 +00003243 }
3244 }
3245 if( k<=i/2 ){
3246 k = i;
3247 }else{
3248 i = k;
3249 while( z[i]==' ' ) i++;
3250 }
3251 }else{
3252 k = i;
larrybrcc4d55c2022-02-01 02:50:45 +00003253 }
drh09a39ed2022-01-30 21:09:03 +00003254 if( n>=mxWidth && z[i]>=' ' ){
3255 *pzTail = &z[i];
3256 }else if( z[i]=='\r' && z[i+1]=='\n' ){
3257 *pzTail = z[i+2] ? &z[i+2] : 0;
drhb6172192022-01-31 10:55:50 +00003258 }else if( z[i]==0 || z[i+1]==0 ){
drh09a39ed2022-01-30 21:09:03 +00003259 *pzTail = 0;
3260 }else{
3261 *pzTail = &z[i+1];
3262 }
drhb6172192022-01-31 10:55:50 +00003263 zOut = malloc( j+1 );
drh09a39ed2022-01-30 21:09:03 +00003264 shell_check_oom(zOut);
drhb6172192022-01-31 10:55:50 +00003265 i = j = n = 0;
drhca1776b2022-02-01 12:28:17 +00003266 while( i<k ){
drh09a39ed2022-01-30 21:09:03 +00003267 if( z[i]>=' ' ){
drhb6172192022-01-31 10:55:50 +00003268 n++;
3269 do{ zOut[j++] = z[i++]; }while( (z[i]&0xc0)==0x80 );
drh09a39ed2022-01-30 21:09:03 +00003270 continue;
3271 }
3272 if( z[i]=='\t' ){
3273 do{
drhb6172192022-01-31 10:55:50 +00003274 n++;
3275 zOut[j++] = ' ';
drh09a39ed2022-01-30 21:09:03 +00003276 }while( (n&7)!=0 && n<mxWidth );
3277 i++;
3278 continue;
3279 }
3280 break;
3281 }
drhb6172192022-01-31 10:55:50 +00003282 zOut[j] = 0;
drh09a39ed2022-01-30 21:09:03 +00003283 return (char*)zOut;
3284}
3285
drhe40f2862022-01-31 14:14:29 +00003286/* Extract the value of the i-th current column for pStmt as an SQL literal
3287** value. Memory is obtained from sqlite3_malloc64() and must be freed by
3288** the caller.
3289*/
3290static char *quoted_column(sqlite3_stmt *pStmt, int i){
3291 switch( sqlite3_column_type(pStmt, i) ){
3292 case SQLITE_NULL: {
3293 return sqlite3_mprintf("NULL");
3294 }
3295 case SQLITE_INTEGER:
3296 case SQLITE_FLOAT: {
3297 return sqlite3_mprintf("%s",sqlite3_column_text(pStmt,i));
3298 }
3299 case SQLITE_TEXT: {
3300 return sqlite3_mprintf("%Q",sqlite3_column_text(pStmt,i));
3301 }
3302 case SQLITE_BLOB: {
3303 int j;
3304 sqlite3_str *pStr = sqlite3_str_new(0);
3305 const unsigned char *a = sqlite3_column_blob(pStmt,i);
3306 int n = sqlite3_column_bytes(pStmt,i);
3307 sqlite3_str_append(pStr, "x'", 2);
3308 for(j=0; j<n; j++){
3309 sqlite3_str_appendf(pStr, "%02x", a[j]);
3310 }
3311 sqlite3_str_append(pStr, "'", 1);
3312 return sqlite3_str_finish(pStr);
3313 }
3314 }
3315 return 0; /* Not reached */
3316}
drh0908e382020-06-04 18:05:39 +00003317
3318/*
drh30c54a02020-05-28 23:49:50 +00003319** Run a prepared statement and output the result in one of the
drh0908e382020-06-04 18:05:39 +00003320** table-oriented formats: MODE_Column, MODE_Markdown, MODE_Table,
3321** or MODE_Box.
drh30c54a02020-05-28 23:49:50 +00003322**
3323** This is different from ordinary exec_prepared_stmt() in that
3324** it has to run the entire query and gather the results into memory
3325** first, in order to determine column widths, before providing
3326** any output.
3327*/
drh8c748632020-05-29 16:15:58 +00003328static void exec_prepared_stmt_columnar(
3329 ShellState *p, /* Pointer to ShellState */
3330 sqlite3_stmt *pStmt /* Statment to run */
drh30c54a02020-05-28 23:49:50 +00003331){
drhf82ce382020-08-06 16:45:22 +00003332 sqlite3_int64 nRow = 0;
drh8c748632020-05-29 16:15:58 +00003333 int nColumn = 0;
3334 char **azData = 0;
drhf82ce382020-08-06 16:45:22 +00003335 sqlite3_int64 nAlloc = 0;
drh09a39ed2022-01-30 21:09:03 +00003336 char *abRowDiv = 0;
3337 const unsigned char *uz;
drh8c748632020-05-29 16:15:58 +00003338 const char *z;
drhe40f2862022-01-31 14:14:29 +00003339 char **azQuoted = 0;
drh8c748632020-05-29 16:15:58 +00003340 int rc;
drhf82ce382020-08-06 16:45:22 +00003341 sqlite3_int64 i, nData;
3342 int j, nTotal, w, n;
drh0908e382020-06-04 18:05:39 +00003343 const char *colSep = 0;
3344 const char *rowSep = 0;
drh09a39ed2022-01-30 21:09:03 +00003345 const unsigned char **azNextLine = 0;
3346 int bNextLine = 0;
3347 int bMultiLineRowExists = 0;
drhca1776b2022-02-01 12:28:17 +00003348 int bw = p->cmOpts.bWordWrap;
drh30c54a02020-05-28 23:49:50 +00003349
drhf82ce382020-08-06 16:45:22 +00003350 rc = sqlite3_step(pStmt);
3351 if( rc!=SQLITE_ROW ) return;
3352 nColumn = sqlite3_column_count(pStmt);
3353 nAlloc = nColumn*4;
drh01a8ad22021-03-20 23:15:52 +00003354 if( nAlloc<=0 ) nAlloc = 1;
drhf82ce382020-08-06 16:45:22 +00003355 azData = sqlite3_malloc64( nAlloc*sizeof(char*) );
drhe3e25652021-12-16 13:29:28 +00003356 shell_check_oom(azData);
drh09a39ed2022-01-30 21:09:03 +00003357 azNextLine = sqlite3_malloc64( nColumn*sizeof(char*) );
drh5dce6f92022-01-31 16:29:06 +00003358 shell_check_oom((void*)azNextLine);
3359 memset((void*)azNextLine, 0, nColumn*sizeof(char*) );
larrybrcc4d55c2022-02-01 02:50:45 +00003360 if( p->cmOpts.bQuote ){
drhe40f2862022-01-31 14:14:29 +00003361 azQuoted = sqlite3_malloc64( nColumn*sizeof(char*) );
3362 shell_check_oom(azQuoted);
3363 memset(azQuoted, 0, nColumn*sizeof(char*) );
3364 }
drh09a39ed2022-01-30 21:09:03 +00003365 abRowDiv = sqlite3_malloc64( nAlloc/nColumn );
3366 shell_check_oom(abRowDiv);
drh8c748632020-05-29 16:15:58 +00003367 if( nColumn>p->nWidth ){
drh76fc88f2021-10-02 16:39:16 +00003368 p->colWidth = realloc(p->colWidth, (nColumn+1)*2*sizeof(int));
drhe3e25652021-12-16 13:29:28 +00003369 shell_check_oom(p->colWidth);
drh8c748632020-05-29 16:15:58 +00003370 for(i=p->nWidth; i<nColumn; i++) p->colWidth[i] = 0;
3371 p->nWidth = nColumn;
3372 p->actualWidth = &p->colWidth[nColumn];
3373 }
3374 memset(p->actualWidth, 0, nColumn*sizeof(int));
3375 for(i=0; i<nColumn; i++){
3376 w = p->colWidth[i];
3377 if( w<0 ) w = -w;
3378 p->actualWidth[i] = w;
3379 }
drh09a39ed2022-01-30 21:09:03 +00003380 for(i=0; i<nColumn; i++){
drh47741b82022-01-31 22:14:53 +00003381 const unsigned char *zNotUsed;
3382 int wx = p->colWidth[i];
larrybrcc4d55c2022-02-01 02:50:45 +00003383 if( wx==0 ){
3384 wx = p->cmOpts.iWrap;
larrybrcc4d55c2022-02-01 02:50:45 +00003385 }
drh47741b82022-01-31 22:14:53 +00003386 if( wx<0 ) wx = -wx;
3387 uz = (const unsigned char*)sqlite3_column_name(pStmt,i);
larrybrcc4d55c2022-02-01 02:50:45 +00003388 azData[i] = translateForDisplayAndDup(uz, &zNotUsed, wx, bw);
drh09a39ed2022-01-30 21:09:03 +00003389 }
3390 do{
3391 int useNextLine = bNextLine;
3392 bNextLine = 0;
3393 if( (nRow+2)*nColumn >= nAlloc ){
3394 nAlloc *= 2;
3395 azData = sqlite3_realloc64(azData, nAlloc*sizeof(char*));
3396 shell_check_oom(azData);
3397 abRowDiv = sqlite3_realloc64(abRowDiv, nAlloc/nColumn);
3398 shell_check_oom(abRowDiv);
3399 }
3400 abRowDiv[nRow] = 1;
3401 nRow++;
3402 for(i=0; i<nColumn; i++){
drh5dce6f92022-01-31 16:29:06 +00003403 int wx = p->colWidth[i];
larrybrcc4d55c2022-02-01 02:50:45 +00003404 if( wx==0 ){
3405 wx = p->cmOpts.iWrap;
larrybrcc4d55c2022-02-01 02:50:45 +00003406 }
drh47741b82022-01-31 22:14:53 +00003407 if( wx<0 ) wx = -wx;
drh09a39ed2022-01-30 21:09:03 +00003408 if( useNextLine ){
3409 uz = azNextLine[i];
larrybrcc4d55c2022-02-01 02:50:45 +00003410 }else if( p->cmOpts.bQuote ){
drhe40f2862022-01-31 14:14:29 +00003411 sqlite3_free(azQuoted[i]);
3412 azQuoted[i] = quoted_column(pStmt,i);
3413 uz = (const unsigned char*)azQuoted[i];
drh09a39ed2022-01-30 21:09:03 +00003414 }else{
3415 uz = (const unsigned char*)sqlite3_column_text(pStmt,i);
3416 }
larrybrcc4d55c2022-02-01 02:50:45 +00003417 azData[nRow*nColumn + i]
3418 = translateForDisplayAndDup(uz, &azNextLine[i], wx, bw);
drh09a39ed2022-01-30 21:09:03 +00003419 if( azNextLine[i] ){
3420 bNextLine = 1;
3421 abRowDiv[nRow-1] = 0;
3422 bMultiLineRowExists = 1;
3423 }
3424 }
3425 }while( bNextLine || sqlite3_step(pStmt)==SQLITE_ROW );
drh8c748632020-05-29 16:15:58 +00003426 nTotal = nColumn*(nRow+1);
3427 for(i=0; i<nTotal; i++){
3428 z = azData[i];
3429 if( z==0 ) z = p->nullValue;
3430 n = strlenChar(z);
3431 j = i%nColumn;
3432 if( n>p->actualWidth[j] ) p->actualWidth[j] = n;
3433 }
drh99942982020-06-15 20:05:37 +00003434 if( seenInterrupt ) goto columnar_end;
drh01a8ad22021-03-20 23:15:52 +00003435 if( nColumn==0 ) goto columnar_end;
drh0908e382020-06-04 18:05:39 +00003436 switch( p->cMode ){
3437 case MODE_Column: {
3438 colSep = " ";
3439 rowSep = "\n";
3440 if( p->showHeader ){
3441 for(i=0; i<nColumn; i++){
3442 w = p->actualWidth[i];
3443 if( p->colWidth[i]<0 ) w = -w;
3444 utf8_width_print(p->out, w, azData[i]);
3445 fputs(i==nColumn-1?"\n":" ", p->out);
3446 }
3447 for(i=0; i<nColumn; i++){
3448 print_dashes(p->out, p->actualWidth[i]);
3449 fputs(i==nColumn-1?"\n":" ", p->out);
3450 }
3451 }
3452 break;
3453 }
3454 case MODE_Table: {
3455 colSep = " | ";
3456 rowSep = " |\n";
3457 print_row_separator(p, nColumn, "+");
3458 fputs("| ", p->out);
drh8c748632020-05-29 16:15:58 +00003459 for(i=0; i<nColumn; i++){
3460 w = p->actualWidth[i];
drh0908e382020-06-04 18:05:39 +00003461 n = strlenChar(azData[i]);
3462 utf8_printf(p->out, "%*s%s%*s", (w-n)/2, "", azData[i], (w-n+1)/2, "");
3463 fputs(i==nColumn-1?" |\n":" | ", p->out);
drh8c748632020-05-29 16:15:58 +00003464 }
drh0908e382020-06-04 18:05:39 +00003465 print_row_separator(p, nColumn, "+");
3466 break;
3467 }
3468 case MODE_Markdown: {
3469 colSep = " | ";
3470 rowSep = " |\n";
3471 fputs("| ", p->out);
drh8c748632020-05-29 16:15:58 +00003472 for(i=0; i<nColumn; i++){
drh0908e382020-06-04 18:05:39 +00003473 w = p->actualWidth[i];
3474 n = strlenChar(azData[i]);
3475 utf8_printf(p->out, "%*s%s%*s", (w-n)/2, "", azData[i], (w-n+1)/2, "");
3476 fputs(i==nColumn-1?" |\n":" | ", p->out);
drh8c748632020-05-29 16:15:58 +00003477 }
drh0908e382020-06-04 18:05:39 +00003478 print_row_separator(p, nColumn, "|");
3479 break;
drh8c748632020-05-29 16:15:58 +00003480 }
drh0908e382020-06-04 18:05:39 +00003481 case MODE_Box: {
3482 colSep = " " BOX_13 " ";
3483 rowSep = " " BOX_13 "\n";
3484 print_box_row_separator(p, nColumn, BOX_23, BOX_234, BOX_34);
3485 utf8_printf(p->out, BOX_13 " ");
3486 for(i=0; i<nColumn; i++){
3487 w = p->actualWidth[i];
3488 n = strlenChar(azData[i]);
3489 utf8_printf(p->out, "%*s%s%*s%s",
3490 (w-n)/2, "", azData[i], (w-n+1)/2, "",
3491 i==nColumn-1?" "BOX_13"\n":" "BOX_13" ");
3492 }
3493 print_box_row_separator(p, nColumn, BOX_123, BOX_1234, BOX_134);
3494 break;
drh8c748632020-05-29 16:15:58 +00003495 }
drh8c748632020-05-29 16:15:58 +00003496 }
3497 for(i=nColumn, j=0; i<nTotal; i++, j++){
drh0908e382020-06-04 18:05:39 +00003498 if( j==0 && p->cMode!=MODE_Column ){
3499 utf8_printf(p->out, "%s", p->cMode==MODE_Box?BOX_13" ":"| ");
3500 }
drh8c748632020-05-29 16:15:58 +00003501 z = azData[i];
3502 if( z==0 ) z = p->nullValue;
3503 w = p->actualWidth[j];
3504 if( p->colWidth[j]<0 ) w = -w;
3505 utf8_width_print(p->out, w, z);
3506 if( j==nColumn-1 ){
drh0908e382020-06-04 18:05:39 +00003507 utf8_printf(p->out, "%s", rowSep);
drh09a39ed2022-01-30 21:09:03 +00003508 if( bMultiLineRowExists && abRowDiv[i/nColumn-1] && i+1<nTotal ){
3509 if( p->cMode==MODE_Table ){
3510 print_row_separator(p, nColumn, "+");
3511 }else if( p->cMode==MODE_Box ){
3512 print_box_row_separator(p, nColumn, BOX_123, BOX_1234, BOX_134);
drh5aabdae2022-02-01 00:00:08 +00003513 }else if( p->cMode==MODE_Column ){
3514 raw_printf(p->out, "\n");
drh09a39ed2022-01-30 21:09:03 +00003515 }
3516 }
drh8c748632020-05-29 16:15:58 +00003517 j = -1;
drhdd853c32020-06-16 17:34:40 +00003518 if( seenInterrupt ) goto columnar_end;
drh8c748632020-05-29 16:15:58 +00003519 }else{
drh0908e382020-06-04 18:05:39 +00003520 utf8_printf(p->out, "%s", colSep);
drh8c748632020-05-29 16:15:58 +00003521 }
3522 }
3523 if( p->cMode==MODE_Table ){
3524 print_row_separator(p, nColumn, "+");
drh0908e382020-06-04 18:05:39 +00003525 }else if( p->cMode==MODE_Box ){
3526 print_box_row_separator(p, nColumn, BOX_12, BOX_124, BOX_14);
drh8c748632020-05-29 16:15:58 +00003527 }
drh99942982020-06-15 20:05:37 +00003528columnar_end:
drhdd853c32020-06-16 17:34:40 +00003529 if( seenInterrupt ){
3530 utf8_printf(p->out, "Interrupt\n");
3531 }
drhf82ce382020-08-06 16:45:22 +00003532 nData = (nRow+1)*nColumn;
3533 for(i=0; i<nData; i++) free(azData[i]);
3534 sqlite3_free(azData);
drh5dce6f92022-01-31 16:29:06 +00003535 sqlite3_free((void*)azNextLine);
drh09a39ed2022-01-30 21:09:03 +00003536 sqlite3_free(abRowDiv);
drhe40f2862022-01-31 14:14:29 +00003537 if( azQuoted ){
3538 for(i=0; i<nColumn; i++) sqlite3_free(azQuoted[i]);
3539 sqlite3_free(azQuoted);
3540 }
drh30c54a02020-05-28 23:49:50 +00003541}
drh30c54a02020-05-28 23:49:50 +00003542
drh2ce15c32017-07-11 13:34:40 +00003543/*
3544** Run a prepared statement
3545*/
3546static void exec_prepared_stmt(
3547 ShellState *pArg, /* Pointer to ShellState */
drha10b9992018-03-09 15:24:33 +00003548 sqlite3_stmt *pStmt /* Statment to run */
drh2ce15c32017-07-11 13:34:40 +00003549){
3550 int rc;
drh5d88be82021-12-09 16:17:43 +00003551 sqlite3_uint64 nRow = 0;
drh2ce15c32017-07-11 13:34:40 +00003552
drh8c748632020-05-29 16:15:58 +00003553 if( pArg->cMode==MODE_Column
3554 || pArg->cMode==MODE_Table
drh0908e382020-06-04 18:05:39 +00003555 || pArg->cMode==MODE_Box
drh8c748632020-05-29 16:15:58 +00003556 || pArg->cMode==MODE_Markdown
3557 ){
3558 exec_prepared_stmt_columnar(pArg, pStmt);
3559 return;
3560 }
3561
drh2ce15c32017-07-11 13:34:40 +00003562 /* perform the first step. this will tell us if we
3563 ** have a result set or not and how wide it is.
3564 */
3565 rc = sqlite3_step(pStmt);
3566 /* if we have a result set... */
3567 if( SQLITE_ROW == rc ){
drha10b9992018-03-09 15:24:33 +00003568 /* allocate space for col name ptr, value ptr, and type */
3569 int nCol = sqlite3_column_count(pStmt);
3570 void *pData = sqlite3_malloc64(3*nCol*sizeof(const char*) + 1);
3571 if( !pData ){
drhe85e1da2021-10-01 21:01:07 +00003572 shell_out_of_memory();
drh2ce15c32017-07-11 13:34:40 +00003573 }else{
drha10b9992018-03-09 15:24:33 +00003574 char **azCols = (char **)pData; /* Names of result columns */
3575 char **azVals = &azCols[nCol]; /* Results */
3576 int *aiTypes = (int *)&azVals[nCol]; /* Result types */
3577 int i, x;
3578 assert(sizeof(int) <= sizeof(char *));
3579 /* save off ptrs to column names */
3580 for(i=0; i<nCol; i++){
3581 azCols[i] = (char *)sqlite3_column_name(pStmt, i);
3582 }
drh2ce15c32017-07-11 13:34:40 +00003583 do{
drh5d88be82021-12-09 16:17:43 +00003584 nRow++;
drha10b9992018-03-09 15:24:33 +00003585 /* extract the data and data types */
3586 for(i=0; i<nCol; i++){
3587 aiTypes[i] = x = sqlite3_column_type(pStmt, i);
drh5d1bf4f2022-01-02 20:54:33 +00003588 if( x==SQLITE_BLOB
3589 && pArg
3590 && (pArg->cMode==MODE_Insert || pArg->cMode==MODE_Quote)
3591 ){
drha10b9992018-03-09 15:24:33 +00003592 azVals[i] = "";
3593 }else{
3594 azVals[i] = (char*)sqlite3_column_text(pStmt, i);
3595 }
3596 if( !azVals[i] && (aiTypes[i]!=SQLITE_NULL) ){
3597 rc = SQLITE_NOMEM;
3598 break; /* from for */
3599 }
3600 } /* end for */
3601
3602 /* if data and types extracted successfully... */
3603 if( SQLITE_ROW == rc ){
3604 /* call the supplied callback with the result row data */
3605 if( shell_callback(pArg, nCol, azVals, azCols, aiTypes) ){
3606 rc = SQLITE_ABORT;
3607 }else{
3608 rc = sqlite3_step(pStmt);
3609 }
3610 }
3611 } while( SQLITE_ROW == rc );
3612 sqlite3_free(pData);
drh0908e382020-06-04 18:05:39 +00003613 if( pArg->cMode==MODE_Json ){
drh30c54a02020-05-28 23:49:50 +00003614 fputs("]\n", pArg->out);
drh5d88be82021-12-09 16:17:43 +00003615 }else if( pArg->cMode==MODE_Count ){
mistachkinc158c072021-12-31 19:08:20 +00003616 char zBuf[200];
3617 sqlite3_snprintf(sizeof(zBuf), zBuf, "%llu row%s\n",
3618 nRow, nRow!=1 ? "s" : "");
3619 printf("%s", zBuf);
drh30c54a02020-05-28 23:49:50 +00003620 }
drh2ce15c32017-07-11 13:34:40 +00003621 }
3622 }
3623}
3624
dan6b046be2018-01-09 15:25:55 +00003625#ifndef SQLITE_OMIT_VIRTUALTABLE
drh2ce15c32017-07-11 13:34:40 +00003626/*
dan43efc182017-12-19 17:42:13 +00003627** This function is called to process SQL if the previous shell command
3628** was ".expert". It passes the SQL in the second argument directly to
3629** the sqlite3expert object.
3630**
3631** If successful, SQLITE_OK is returned. Otherwise, an SQLite error
3632** code. In this case, (*pzErr) may be set to point to a buffer containing
3633** an English language error message. It is the responsibility of the
3634** caller to eventually free this buffer using sqlite3_free().
3635*/
3636static int expertHandleSQL(
3637 ShellState *pState,
3638 const char *zSql,
3639 char **pzErr
3640){
3641 assert( pState->expert.pExpert );
3642 assert( pzErr==0 || *pzErr==0 );
3643 return sqlite3_expert_sql(pState->expert.pExpert, zSql, pzErr);
3644}
3645
3646/*
3647** This function is called either to silently clean up the object
3648** created by the ".expert" command (if bCancel==1), or to generate a
3649** report from it and then clean it up (if bCancel==0).
3650**
3651** If successful, SQLITE_OK is returned. Otherwise, an SQLite error
3652** code. In this case, (*pzErr) may be set to point to a buffer containing
3653** an English language error message. It is the responsibility of the
3654** caller to eventually free this buffer using sqlite3_free().
3655*/
3656static int expertFinish(
3657 ShellState *pState,
3658 int bCancel,
3659 char **pzErr
3660){
3661 int rc = SQLITE_OK;
3662 sqlite3expert *p = pState->expert.pExpert;
3663 assert( p );
3664 assert( bCancel || pzErr==0 || *pzErr==0 );
3665 if( bCancel==0 ){
3666 FILE *out = pState->out;
3667 int bVerbose = pState->expert.bVerbose;
3668
3669 rc = sqlite3_expert_analyze(p, pzErr);
3670 if( rc==SQLITE_OK ){
3671 int nQuery = sqlite3_expert_count(p);
3672 int i;
3673
3674 if( bVerbose ){
3675 const char *zCand = sqlite3_expert_report(p,0,EXPERT_REPORT_CANDIDATES);
3676 raw_printf(out, "-- Candidates -----------------------------\n");
3677 raw_printf(out, "%s\n", zCand);
3678 }
3679 for(i=0; i<nQuery; i++){
3680 const char *zSql = sqlite3_expert_report(p, i, EXPERT_REPORT_SQL);
3681 const char *zIdx = sqlite3_expert_report(p, i, EXPERT_REPORT_INDEXES);
3682 const char *zEQP = sqlite3_expert_report(p, i, EXPERT_REPORT_PLAN);
3683 if( zIdx==0 ) zIdx = "(no new indexes)\n";
3684 if( bVerbose ){
3685 raw_printf(out, "-- Query %d --------------------------------\n",i+1);
3686 raw_printf(out, "%s\n\n", zSql);
3687 }
3688 raw_printf(out, "%s\n", zIdx);
3689 raw_printf(out, "%s\n", zEQP);
3690 }
3691 }
3692 }
3693 sqlite3_expert_destroy(p);
3694 pState->expert.pExpert = 0;
3695 return rc;
3696}
3697
dan6b046be2018-01-09 15:25:55 +00003698/*
3699** Implementation of ".expert" dot command.
3700*/
3701static int expertDotCommand(
3702 ShellState *pState, /* Current shell tool state */
3703 char **azArg, /* Array of arguments passed to dot command */
3704 int nArg /* Number of entries in azArg[] */
3705){
3706 int rc = SQLITE_OK;
3707 char *zErr = 0;
3708 int i;
3709 int iSample = 0;
3710
3711 assert( pState->expert.pExpert==0 );
3712 memset(&pState->expert, 0, sizeof(ExpertInfo));
3713
3714 for(i=1; rc==SQLITE_OK && i<nArg; i++){
3715 char *z = azArg[i];
3716 int n;
3717 if( z[0]=='-' && z[1]=='-' ) z++;
3718 n = strlen30(z);
3719 if( n>=2 && 0==strncmp(z, "-verbose", n) ){
3720 pState->expert.bVerbose = 1;
3721 }
3722 else if( n>=2 && 0==strncmp(z, "-sample", n) ){
3723 if( i==(nArg-1) ){
3724 raw_printf(stderr, "option requires an argument: %s\n", z);
3725 rc = SQLITE_ERROR;
3726 }else{
3727 iSample = (int)integerValue(azArg[++i]);
3728 if( iSample<0 || iSample>100 ){
3729 raw_printf(stderr, "value out of range: %s\n", azArg[i]);
3730 rc = SQLITE_ERROR;
3731 }
3732 }
3733 }
3734 else{
3735 raw_printf(stderr, "unknown option: %s\n", z);
3736 rc = SQLITE_ERROR;
3737 }
3738 }
3739
3740 if( rc==SQLITE_OK ){
3741 pState->expert.pExpert = sqlite3_expert_new(pState->db, &zErr);
3742 if( pState->expert.pExpert==0 ){
drhe0adf602021-12-16 14:26:16 +00003743 raw_printf(stderr, "sqlite3_expert_new: %s\n", zErr ? zErr : "out of memory");
dan6b046be2018-01-09 15:25:55 +00003744 rc = SQLITE_ERROR;
3745 }else{
3746 sqlite3_expert_config(
3747 pState->expert.pExpert, EXPERT_CONFIG_SAMPLE, iSample
3748 );
3749 }
3750 }
drhe0adf602021-12-16 14:26:16 +00003751 sqlite3_free(zErr);
dan6b046be2018-01-09 15:25:55 +00003752
3753 return rc;
3754}
3755#endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */
dan43efc182017-12-19 17:42:13 +00003756
3757/*
drh2ce15c32017-07-11 13:34:40 +00003758** Execute a statement or set of statements. Print
3759** any result rows/columns depending on the current mode
3760** set via the supplied callback.
3761**
3762** This is very similar to SQLite's built-in sqlite3_exec()
3763** function except it takes a slightly different callback
3764** and callback data argument.
3765*/
3766static int shell_exec(
drh2ce15c32017-07-11 13:34:40 +00003767 ShellState *pArg, /* Pointer to ShellState */
drha10b9992018-03-09 15:24:33 +00003768 const char *zSql, /* SQL to be evaluated */
drh2ce15c32017-07-11 13:34:40 +00003769 char **pzErrMsg /* Error msg written here */
3770){
3771 sqlite3_stmt *pStmt = NULL; /* Statement to execute. */
3772 int rc = SQLITE_OK; /* Return Code */
3773 int rc2;
3774 const char *zLeftover; /* Tail of unprocessed SQL */
drha10b9992018-03-09 15:24:33 +00003775 sqlite3 *db = pArg->db;
drh2ce15c32017-07-11 13:34:40 +00003776
3777 if( pzErrMsg ){
3778 *pzErrMsg = NULL;
3779 }
3780
dan6b046be2018-01-09 15:25:55 +00003781#ifndef SQLITE_OMIT_VIRTUALTABLE
dan43efc182017-12-19 17:42:13 +00003782 if( pArg->expert.pExpert ){
3783 rc = expertHandleSQL(pArg, zSql, pzErrMsg);
3784 return expertFinish(pArg, (rc!=SQLITE_OK), pzErrMsg);
3785 }
dan6b046be2018-01-09 15:25:55 +00003786#endif
dan43efc182017-12-19 17:42:13 +00003787
drh2ce15c32017-07-11 13:34:40 +00003788 while( zSql[0] && (SQLITE_OK == rc) ){
3789 static const char *zStmtSql;
3790 rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zLeftover);
3791 if( SQLITE_OK != rc ){
3792 if( pzErrMsg ){
drh633c7982022-02-08 12:13:16 +00003793 *pzErrMsg = save_err_msg(db, "in prepare", rc, zSql);
drh2ce15c32017-07-11 13:34:40 +00003794 }
3795 }else{
3796 if( !pStmt ){
3797 /* this happens for a comment or white-space */
3798 zSql = zLeftover;
3799 while( IsSpace(zSql[0]) ) zSql++;
3800 continue;
3801 }
3802 zStmtSql = sqlite3_sql(pStmt);
3803 if( zStmtSql==0 ) zStmtSql = "";
3804 while( IsSpace(zStmtSql[0]) ) zStmtSql++;
3805
3806 /* save off the prepared statment handle and reset row count */
3807 if( pArg ){
3808 pArg->pStmt = pStmt;
3809 pArg->cnt = 0;
3810 }
3811
3812 /* echo the sql statement if echo on */
3813 if( pArg && ShellHasFlag(pArg, SHFLG_Echo) ){
3814 utf8_printf(pArg->out, "%s\n", zStmtSql ? zStmtSql : zSql);
3815 }
3816
3817 /* Show the EXPLAIN QUERY PLAN if .eqp is on */
drh39c5c4a2019-03-06 14:53:27 +00003818 if( pArg && pArg->autoEQP && sqlite3_stmt_isexplain(pStmt)==0 ){
drh2ce15c32017-07-11 13:34:40 +00003819 sqlite3_stmt *pExplain;
3820 char *zEQP;
drhada70452017-12-21 21:02:27 +00003821 int triggerEQP = 0;
drh2ce15c32017-07-11 13:34:40 +00003822 disable_debug_trace_modes();
drhada70452017-12-21 21:02:27 +00003823 sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, -1, &triggerEQP);
3824 if( pArg->autoEQP>=AUTOEQP_trigger ){
3825 sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, 1, 0);
3826 }
drh2ce15c32017-07-11 13:34:40 +00003827 zEQP = sqlite3_mprintf("EXPLAIN QUERY PLAN %s", zStmtSql);
drhe3e25652021-12-16 13:29:28 +00003828 shell_check_oom(zEQP);
drh2ce15c32017-07-11 13:34:40 +00003829 rc = sqlite3_prepare_v2(db, zEQP, -1, &pExplain, 0);
3830 if( rc==SQLITE_OK ){
3831 while( sqlite3_step(pExplain)==SQLITE_ROW ){
drh4b5345c2018-04-24 13:07:40 +00003832 const char *zEQPLine = (const char*)sqlite3_column_text(pExplain,3);
drhe2ca99c2018-05-02 00:33:43 +00003833 int iEqpId = sqlite3_column_int(pExplain, 0);
3834 int iParentId = sqlite3_column_int(pExplain, 1);
drh7e088a62020-05-02 00:01:39 +00003835 if( zEQPLine==0 ) zEQPLine = "";
drh4b5345c2018-04-24 13:07:40 +00003836 if( zEQPLine[0]=='-' ) eqp_render(pArg);
drhe2ca99c2018-05-02 00:33:43 +00003837 eqp_append(pArg, iEqpId, iParentId, zEQPLine);
drh2ce15c32017-07-11 13:34:40 +00003838 }
drh4b5345c2018-04-24 13:07:40 +00003839 eqp_render(pArg);
drh2ce15c32017-07-11 13:34:40 +00003840 }
3841 sqlite3_finalize(pExplain);
3842 sqlite3_free(zEQP);
drhada70452017-12-21 21:02:27 +00003843 if( pArg->autoEQP>=AUTOEQP_full ){
drh2ce15c32017-07-11 13:34:40 +00003844 /* Also do an EXPLAIN for ".eqp full" mode */
3845 zEQP = sqlite3_mprintf("EXPLAIN %s", zStmtSql);
drhe3e25652021-12-16 13:29:28 +00003846 shell_check_oom(zEQP);
drh2ce15c32017-07-11 13:34:40 +00003847 rc = sqlite3_prepare_v2(db, zEQP, -1, &pExplain, 0);
3848 if( rc==SQLITE_OK ){
3849 pArg->cMode = MODE_Explain;
3850 explain_data_prepare(pArg, pExplain);
drha10b9992018-03-09 15:24:33 +00003851 exec_prepared_stmt(pArg, pExplain);
drh2ce15c32017-07-11 13:34:40 +00003852 explain_data_delete(pArg);
3853 }
3854 sqlite3_finalize(pExplain);
3855 sqlite3_free(zEQP);
3856 }
drh51efe092018-03-20 12:04:38 +00003857 if( pArg->autoEQP>=AUTOEQP_trigger && triggerEQP==0 ){
3858 sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, 0, 0);
3859 /* Reprepare pStmt before reactiving trace modes */
3860 sqlite3_finalize(pStmt);
3861 sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
drh3c49eaf2018-06-07 15:23:43 +00003862 if( pArg ) pArg->pStmt = pStmt;
drh51efe092018-03-20 12:04:38 +00003863 }
drh2ce15c32017-07-11 13:34:40 +00003864 restore_debug_trace_modes();
3865 }
3866
3867 if( pArg ){
3868 pArg->cMode = pArg->mode;
drh4b5345c2018-04-24 13:07:40 +00003869 if( pArg->autoExplain ){
drh39c5c4a2019-03-06 14:53:27 +00003870 if( sqlite3_stmt_isexplain(pStmt)==1 ){
drh4b5345c2018-04-24 13:07:40 +00003871 pArg->cMode = MODE_Explain;
3872 }
drh39c5c4a2019-03-06 14:53:27 +00003873 if( sqlite3_stmt_isexplain(pStmt)==2 ){
drh4b5345c2018-04-24 13:07:40 +00003874 pArg->cMode = MODE_EQP;
3875 }
drh2ce15c32017-07-11 13:34:40 +00003876 }
3877
3878 /* If the shell is currently in ".explain" mode, gather the extra
3879 ** data required to add indents to the output.*/
3880 if( pArg->cMode==MODE_Explain ){
3881 explain_data_prepare(pArg, pStmt);
3882 }
3883 }
3884
drh8b738d02019-02-25 18:43:54 +00003885 bind_prepared_stmt(pArg, pStmt);
drha10b9992018-03-09 15:24:33 +00003886 exec_prepared_stmt(pArg, pStmt);
drh2ce15c32017-07-11 13:34:40 +00003887 explain_data_delete(pArg);
drh4b5345c2018-04-24 13:07:40 +00003888 eqp_render(pArg);
drh2ce15c32017-07-11 13:34:40 +00003889
3890 /* print usage stats if stats on */
3891 if( pArg && pArg->statsOn ){
3892 display_stats(db, pArg, 0);
3893 }
3894
3895 /* print loop-counters if required */
3896 if( pArg && pArg->scanstatsOn ){
3897 display_scanstats(db, pArg);
3898 }
3899
3900 /* Finalize the statement just executed. If this fails, save a
3901 ** copy of the error message. Otherwise, set zSql to point to the
3902 ** next statement to execute. */
3903 rc2 = sqlite3_finalize(pStmt);
3904 if( rc!=SQLITE_NOMEM ) rc = rc2;
3905 if( rc==SQLITE_OK ){
3906 zSql = zLeftover;
3907 while( IsSpace(zSql[0]) ) zSql++;
3908 }else if( pzErrMsg ){
drh633c7982022-02-08 12:13:16 +00003909 *pzErrMsg = save_err_msg(db, "stepping", rc, 0);
drh2ce15c32017-07-11 13:34:40 +00003910 }
3911
3912 /* clear saved stmt handle */
3913 if( pArg ){
3914 pArg->pStmt = NULL;
3915 }
3916 }
3917 } /* end while */
3918
3919 return rc;
3920}
3921
3922/*
3923** Release memory previously allocated by tableColumnList().
3924*/
3925static void freeColumnList(char **azCol){
3926 int i;
3927 for(i=1; azCol[i]; i++){
3928 sqlite3_free(azCol[i]);
3929 }
3930 /* azCol[0] is a static string */
3931 sqlite3_free(azCol);
3932}
3933
3934/*
3935** Return a list of pointers to strings which are the names of all
3936** columns in table zTab. The memory to hold the names is dynamically
3937** allocated and must be released by the caller using a subsequent call
3938** to freeColumnList().
3939**
3940** The azCol[0] entry is usually NULL. However, if zTab contains a rowid
3941** value that needs to be preserved, then azCol[0] is filled in with the
3942** name of the rowid column.
3943**
3944** The first regular column in the table is azCol[1]. The list is terminated
3945** by an entry with azCol[i]==0.
3946*/
3947static char **tableColumnList(ShellState *p, const char *zTab){
3948 char **azCol = 0;
3949 sqlite3_stmt *pStmt;
3950 char *zSql;
3951 int nCol = 0;
3952 int nAlloc = 0;
3953 int nPK = 0; /* Number of PRIMARY KEY columns seen */
3954 int isIPK = 0; /* True if one PRIMARY KEY column of type INTEGER */
3955 int preserveRowid = ShellHasFlag(p, SHFLG_PreserveRowid);
3956 int rc;
3957
3958 zSql = sqlite3_mprintf("PRAGMA table_info=%Q", zTab);
drhe3e25652021-12-16 13:29:28 +00003959 shell_check_oom(zSql);
drh2ce15c32017-07-11 13:34:40 +00003960 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
3961 sqlite3_free(zSql);
3962 if( rc ) return 0;
3963 while( sqlite3_step(pStmt)==SQLITE_ROW ){
3964 if( nCol>=nAlloc-2 ){
3965 nAlloc = nAlloc*2 + nCol + 10;
3966 azCol = sqlite3_realloc(azCol, nAlloc*sizeof(azCol[0]));
drhe3e25652021-12-16 13:29:28 +00003967 shell_check_oom(azCol);
drh2ce15c32017-07-11 13:34:40 +00003968 }
3969 azCol[++nCol] = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 1));
drhe3e25652021-12-16 13:29:28 +00003970 shell_check_oom(azCol[nCol]);
drh2ce15c32017-07-11 13:34:40 +00003971 if( sqlite3_column_int(pStmt, 5) ){
3972 nPK++;
3973 if( nPK==1
3974 && sqlite3_stricmp((const char*)sqlite3_column_text(pStmt,2),
3975 "INTEGER")==0
3976 ){
3977 isIPK = 1;
3978 }else{
3979 isIPK = 0;
3980 }
3981 }
3982 }
3983 sqlite3_finalize(pStmt);
drh4c6cddc2017-10-12 10:28:30 +00003984 if( azCol==0 ) return 0;
drh2ce15c32017-07-11 13:34:40 +00003985 azCol[0] = 0;
3986 azCol[nCol+1] = 0;
3987
3988 /* The decision of whether or not a rowid really needs to be preserved
3989 ** is tricky. We never need to preserve a rowid for a WITHOUT ROWID table
3990 ** or a table with an INTEGER PRIMARY KEY. We are unable to preserve
3991 ** rowids on tables where the rowid is inaccessible because there are other
3992 ** columns in the table named "rowid", "_rowid_", and "oid".
3993 */
3994 if( preserveRowid && isIPK ){
3995 /* If a single PRIMARY KEY column with type INTEGER was seen, then it
3996 ** might be an alise for the ROWID. But it might also be a WITHOUT ROWID
3997 ** table or a INTEGER PRIMARY KEY DESC column, neither of which are
3998 ** ROWID aliases. To distinguish these cases, check to see if
3999 ** there is a "pk" entry in "PRAGMA index_list". There will be
4000 ** no "pk" index if the PRIMARY KEY really is an alias for the ROWID.
4001 */
4002 zSql = sqlite3_mprintf("SELECT 1 FROM pragma_index_list(%Q)"
4003 " WHERE origin='pk'", zTab);
drhe3e25652021-12-16 13:29:28 +00004004 shell_check_oom(zSql);
drh2ce15c32017-07-11 13:34:40 +00004005 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
4006 sqlite3_free(zSql);
4007 if( rc ){
4008 freeColumnList(azCol);
4009 return 0;
4010 }
4011 rc = sqlite3_step(pStmt);
4012 sqlite3_finalize(pStmt);
4013 preserveRowid = rc==SQLITE_ROW;
4014 }
4015 if( preserveRowid ){
4016 /* Only preserve the rowid if we can find a name to use for the
4017 ** rowid */
4018 static char *azRowid[] = { "rowid", "_rowid_", "oid" };
4019 int i, j;
4020 for(j=0; j<3; j++){
4021 for(i=1; i<=nCol; i++){
4022 if( sqlite3_stricmp(azRowid[j],azCol[i])==0 ) break;
4023 }
4024 if( i>nCol ){
4025 /* At this point, we know that azRowid[j] is not the name of any
4026 ** ordinary column in the table. Verify that azRowid[j] is a valid
4027 ** name for the rowid before adding it to azCol[0]. WITHOUT ROWID
4028 ** tables will fail this last check */
4029 rc = sqlite3_table_column_metadata(p->db,0,zTab,azRowid[j],0,0,0,0,0);
4030 if( rc==SQLITE_OK ) azCol[0] = azRowid[j];
4031 break;
4032 }
4033 }
4034 }
4035 return azCol;
4036}
4037
4038/*
4039** Toggle the reverse_unordered_selects setting.
4040*/
4041static void toggleSelectOrder(sqlite3 *db){
4042 sqlite3_stmt *pStmt = 0;
4043 int iSetting = 0;
4044 char zStmt[100];
4045 sqlite3_prepare_v2(db, "PRAGMA reverse_unordered_selects", -1, &pStmt, 0);
4046 if( sqlite3_step(pStmt)==SQLITE_ROW ){
4047 iSetting = sqlite3_column_int(pStmt, 0);
4048 }
4049 sqlite3_finalize(pStmt);
4050 sqlite3_snprintf(sizeof(zStmt), zStmt,
4051 "PRAGMA reverse_unordered_selects(%d)", !iSetting);
4052 sqlite3_exec(db, zStmt, 0, 0, 0);
4053}
4054
4055/*
4056** This is a different callback routine used for dumping the database.
4057** Each row received by this callback consists of a table name,
4058** the table type ("index" or "table") and SQL to create the table.
4059** This routine should print text sufficient to recreate the table.
4060*/
4061static int dump_callback(void *pArg, int nArg, char **azArg, char **azNotUsed){
4062 int rc;
4063 const char *zTable;
4064 const char *zType;
4065 const char *zSql;
4066 ShellState *p = (ShellState *)pArg;
mistachkina00a0162020-10-18 18:35:34 +00004067 int dataOnly;
4068 int noSys;
drh2ce15c32017-07-11 13:34:40 +00004069
4070 UNUSED_PARAMETER(azNotUsed);
drhb3c45232017-08-28 14:33:27 +00004071 if( nArg!=3 || azArg==0 ) return 0;
drh2ce15c32017-07-11 13:34:40 +00004072 zTable = azArg[0];
4073 zType = azArg[1];
4074 zSql = azArg[2];
mistachkina00a0162020-10-18 18:35:34 +00004075 dataOnly = (p->shellFlgs & SHFLG_DumpDataOnly)!=0;
4076 noSys = (p->shellFlgs & SHFLG_DumpNoSys)!=0;
drh2ce15c32017-07-11 13:34:40 +00004077
drhc1962192020-10-12 16:54:28 +00004078 if( strcmp(zTable, "sqlite_sequence")==0 && !noSys ){
4079 if( !dataOnly ) raw_printf(p->out, "DELETE FROM sqlite_sequence;\n");
4080 }else if( sqlite3_strglob("sqlite_stat?", zTable)==0 && !noSys ){
4081 if( !dataOnly ) raw_printf(p->out, "ANALYZE sqlite_schema;\n");
drh2ce15c32017-07-11 13:34:40 +00004082 }else if( strncmp(zTable, "sqlite_", 7)==0 ){
4083 return 0;
drhc1962192020-10-12 16:54:28 +00004084 }else if( dataOnly ){
4085 /* no-op */
drh2ce15c32017-07-11 13:34:40 +00004086 }else if( strncmp(zSql, "CREATE VIRTUAL TABLE", 20)==0 ){
4087 char *zIns;
4088 if( !p->writableSchema ){
4089 raw_printf(p->out, "PRAGMA writable_schema=ON;\n");
4090 p->writableSchema = 1;
4091 }
4092 zIns = sqlite3_mprintf(
drh067b92b2020-06-19 15:24:12 +00004093 "INSERT INTO sqlite_schema(type,name,tbl_name,rootpage,sql)"
drh2ce15c32017-07-11 13:34:40 +00004094 "VALUES('table','%q','%q',0,'%q');",
4095 zTable, zTable, zSql);
drhe3e25652021-12-16 13:29:28 +00004096 shell_check_oom(zIns);
drh2ce15c32017-07-11 13:34:40 +00004097 utf8_printf(p->out, "%s\n", zIns);
4098 sqlite3_free(zIns);
4099 return 0;
4100 }else{
4101 printSchemaLine(p->out, zSql, ";\n");
4102 }
4103
4104 if( strcmp(zType, "table")==0 ){
4105 ShellText sSelect;
4106 ShellText sTable;
4107 char **azCol;
4108 int i;
4109 char *savedDestTable;
4110 int savedMode;
4111
4112 azCol = tableColumnList(p, zTable);
4113 if( azCol==0 ){
4114 p->nErr++;
4115 return 0;
4116 }
4117
4118 /* Always quote the table name, even if it appears to be pure ascii,
4119 ** in case it is a keyword. Ex: INSERT INTO "table" ... */
4120 initText(&sTable);
4121 appendText(&sTable, zTable, quoteChar(zTable));
4122 /* If preserving the rowid, add a column list after the table name.
4123 ** In other words: "INSERT INTO tab(rowid,a,b,c,...) VALUES(...)"
4124 ** instead of the usual "INSERT INTO tab VALUES(...)".
4125 */
4126 if( azCol[0] ){
4127 appendText(&sTable, "(", 0);
4128 appendText(&sTable, azCol[0], 0);
4129 for(i=1; azCol[i]; i++){
4130 appendText(&sTable, ",", 0);
4131 appendText(&sTable, azCol[i], quoteChar(azCol[i]));
4132 }
4133 appendText(&sTable, ")", 0);
4134 }
4135
4136 /* Build an appropriate SELECT statement */
4137 initText(&sSelect);
4138 appendText(&sSelect, "SELECT ", 0);
4139 if( azCol[0] ){
4140 appendText(&sSelect, azCol[0], 0);
4141 appendText(&sSelect, ",", 0);
4142 }
4143 for(i=1; azCol[i]; i++){
4144 appendText(&sSelect, azCol[i], quoteChar(azCol[i]));
4145 if( azCol[i+1] ){
4146 appendText(&sSelect, ",", 0);
4147 }
4148 }
4149 freeColumnList(azCol);
4150 appendText(&sSelect, " FROM ", 0);
4151 appendText(&sSelect, zTable, quoteChar(zTable));
4152
4153 savedDestTable = p->zDestTable;
4154 savedMode = p->mode;
4155 p->zDestTable = sTable.z;
4156 p->mode = p->cMode = MODE_Insert;
drha10b9992018-03-09 15:24:33 +00004157 rc = shell_exec(p, sSelect.z, 0);
drh2ce15c32017-07-11 13:34:40 +00004158 if( (rc&0xff)==SQLITE_CORRUPT ){
4159 raw_printf(p->out, "/****** CORRUPTION ERROR *******/\n");
4160 toggleSelectOrder(p->db);
drha10b9992018-03-09 15:24:33 +00004161 shell_exec(p, sSelect.z, 0);
drh2ce15c32017-07-11 13:34:40 +00004162 toggleSelectOrder(p->db);
4163 }
4164 p->zDestTable = savedDestTable;
4165 p->mode = savedMode;
4166 freeText(&sTable);
4167 freeText(&sSelect);
4168 if( rc ) p->nErr++;
4169 }
4170 return 0;
4171}
4172
4173/*
4174** Run zQuery. Use dump_callback() as the callback routine so that
4175** the contents of the query are output as SQL statements.
4176**
4177** If we get a SQLITE_CORRUPT error, rerun the query after appending
4178** "ORDER BY rowid DESC" to the end.
4179*/
4180static int run_schema_dump_query(
4181 ShellState *p,
4182 const char *zQuery
4183){
4184 int rc;
4185 char *zErr = 0;
4186 rc = sqlite3_exec(p->db, zQuery, dump_callback, p, &zErr);
4187 if( rc==SQLITE_CORRUPT ){
4188 char *zQ2;
4189 int len = strlen30(zQuery);
4190 raw_printf(p->out, "/****** CORRUPTION ERROR *******/\n");
4191 if( zErr ){
4192 utf8_printf(p->out, "/****** %s ******/\n", zErr);
4193 sqlite3_free(zErr);
4194 zErr = 0;
4195 }
4196 zQ2 = malloc( len+100 );
4197 if( zQ2==0 ) return rc;
4198 sqlite3_snprintf(len+100, zQ2, "%s ORDER BY rowid DESC", zQuery);
4199 rc = sqlite3_exec(p->db, zQ2, dump_callback, p, &zErr);
4200 if( rc ){
4201 utf8_printf(p->out, "/****** ERROR: %s ******/\n", zErr);
4202 }else{
4203 rc = SQLITE_CORRUPT;
4204 }
4205 sqlite3_free(zErr);
4206 free(zQ2);
4207 }
4208 return rc;
4209}
4210
4211/*
drh98aa2ab2018-09-26 16:53:51 +00004212** Text of help messages.
4213**
4214** The help text for each individual command begins with a line that starts
4215** with ".". Subsequent lines are supplimental information.
4216**
4217** There must be two or more spaces between the end of the command and the
4218** start of the description of what that command does.
drh2ce15c32017-07-11 13:34:40 +00004219*/
drh98aa2ab2018-09-26 16:53:51 +00004220static const char *(azHelp[]) = {
drhe37c0e12018-01-06 19:19:50 +00004221#if defined(SQLITE_HAVE_ZLIB) && !defined(SQLITE_OMIT_VIRTUALTABLE)
drh98aa2ab2018-09-26 16:53:51 +00004222 ".archive ... Manage SQL archives",
4223 " Each command must have exactly one of the following options:",
4224 " -c, --create Create a new archive",
drhe2754c12019-08-26 12:50:01 +00004225 " -u, --update Add or update files with changed mtime",
4226 " -i, --insert Like -u but always add even if unchanged",
larrybr47061b92021-11-01 17:22:52 +00004227 " -r, --remove Remove files from archive",
drh98aa2ab2018-09-26 16:53:51 +00004228 " -t, --list List contents of archive",
4229 " -x, --extract Extract files from archive",
4230 " Optional arguments:",
4231 " -v, --verbose Print each filename as it is processed",
drhe2754c12019-08-26 12:50:01 +00004232 " -f FILE, --file FILE Use archive FILE (default is current db)",
4233 " -a FILE, --append FILE Open FILE using the apndvfs VFS",
4234 " -C DIR, --directory DIR Read/extract files from directory DIR",
larrybr8f09f4b2021-11-02 00:18:11 +00004235 " -g, --glob Use glob matching for names in archive",
drh98aa2ab2018-09-26 16:53:51 +00004236 " -n, --dryrun Show the SQL that would have occurred",
4237 " Examples:",
drhe2754c12019-08-26 12:50:01 +00004238 " .ar -cf ARCHIVE foo bar # Create ARCHIVE from files foo and bar",
4239 " .ar -tf ARCHIVE # List members of ARCHIVE",
4240 " .ar -xvf ARCHIVE # Verbosely extract files from ARCHIVE",
drh98aa2ab2018-09-26 16:53:51 +00004241 " See also:",
larrybrbd0d62c2021-06-13 08:23:28 +00004242 " http://sqlite.org/cli.html#sqlite_archive_support",
drhe37c0e12018-01-06 19:19:50 +00004243#endif
drh2ce15c32017-07-11 13:34:40 +00004244#ifndef SQLITE_OMIT_AUTHORIZATION
drh98aa2ab2018-09-26 16:53:51 +00004245 ".auth ON|OFF Show authorizer callbacks",
drh2ce15c32017-07-11 13:34:40 +00004246#endif
drh98aa2ab2018-09-26 16:53:51 +00004247 ".backup ?DB? FILE Backup DB (default \"main\") to FILE",
larrybra7919ad2022-02-19 21:25:48 +00004248 " Options:",
drh98aa2ab2018-09-26 16:53:51 +00004249 " --append Use the appendvfs",
drhe2754c12019-08-26 12:50:01 +00004250 " --async Write to FILE without journal and fsync()",
drh98aa2ab2018-09-26 16:53:51 +00004251 ".bail on|off Stop after hitting an error. Default OFF",
4252 ".binary on|off Turn binary output on or off. Default OFF",
4253 ".cd DIRECTORY Change the working directory to DIRECTORY",
4254 ".changes on|off Show number of rows changed by SQL",
4255 ".check GLOB Fail if output since .testcase does not match",
4256 ".clone NEWDB Clone data into NEWDB from the existing database",
drh37407122021-07-23 18:43:58 +00004257 ".connection [close] [#] Open or close an auxiliary database connection",
drh98aa2ab2018-09-26 16:53:51 +00004258 ".databases List names and files of attached databases",
4259 ".dbconfig ?op? ?val? List or change sqlite3_db_config() options",
4260 ".dbinfo ?DB? Show status information about the database",
larrybr7bdbe592021-03-15 12:56:00 +00004261 ".dump ?OBJECTS? Render database content as SQL",
drheb7f2a02018-09-26 18:02:32 +00004262 " Options:",
drhc1962192020-10-12 16:54:28 +00004263 " --data-only Output only INSERT statements",
drheb7f2a02018-09-26 18:02:32 +00004264 " --newlines Allow unescaped newline characters in output",
drhc1962192020-10-12 16:54:28 +00004265 " --nosys Omit system tables (ex: \"sqlite_stat1\")",
4266 " --preserve-rowids Include ROWID values in the output",
larrybr7bdbe592021-03-15 12:56:00 +00004267 " OBJECTS is a LIKE pattern for tables, indexes, triggers or views to dump",
drh8e9297f2020-03-25 12:50:13 +00004268 " Additional LIKE patterns can be given in subsequent arguments",
drh98aa2ab2018-09-26 16:53:51 +00004269 ".echo on|off Turn command echo on or off",
drhb4e50392019-01-26 15:40:04 +00004270 ".eqp on|off|full|... Enable or disable automatic EXPLAIN QUERY PLAN",
4271 " Other Modes:",
4272#ifdef SQLITE_DEBUG
4273 " test Show raw EXPLAIN QUERY PLAN output",
drhe2754c12019-08-26 12:50:01 +00004274 " trace Like \"full\" but enable \"PRAGMA vdbe_trace\"",
drhb4e50392019-01-26 15:40:04 +00004275#endif
4276 " trigger Like \"full\" but also show trigger bytecode",
drhe2754c12019-08-26 12:50:01 +00004277 ".excel Display the output of next command in spreadsheet",
drh7a431002020-04-18 14:12:00 +00004278 " --bom Put a UTF8 byte-order mark on intermediate file",
drheb7f2a02018-09-26 18:02:32 +00004279 ".exit ?CODE? Exit this program with return-code CODE",
drhe2754c12019-08-26 12:50:01 +00004280 ".expert EXPERIMENTAL. Suggest indexes for queries",
drh978256f2019-11-02 00:00:14 +00004281 ".explain ?on|off|auto? Change the EXPLAIN formatting mode. Default: auto",
drhd985f722019-06-05 14:29:53 +00004282 ".filectrl CMD ... Run various sqlite3_file_control() operations",
drh541ef2c2020-04-20 16:21:30 +00004283 " --schema SCHEMA Use SCHEMA instead of \"main\"",
4284 " --help Show CMD details",
drh98aa2ab2018-09-26 16:53:51 +00004285 ".fullschema ?--indent? Show schema and the content of sqlite_stat tables",
4286 ".headers on|off Turn display of headers on or off",
4287 ".help ?-all? ?PATTERN? Show help text for PATTERN",
4288 ".import FILE TABLE Import data from FILE into TABLE",
drhccb37812020-03-09 15:39:39 +00004289 " Options:",
4290 " --ascii Use \\037 and \\036 as column and row separators",
4291 " --csv Use , and \\n as column and row separators",
4292 " --skip N Skip the first N rows of input",
larrybr738d7b92022-01-13 21:22:54 +00004293 " --schema S Target table to be S.TABLE",
drhccb37812020-03-09 15:39:39 +00004294 " -v \"Verbose\" - increase auxiliary output",
4295 " Notes:",
4296 " * If TABLE does not exist, it is created. The first row of input",
4297 " determines the column names.",
4298 " * If neither --csv or --ascii are used, the input mode is derived",
4299 " from the \".mode\" output mode",
4300 " * If FILE begins with \"|\" then it is a command that generates the",
4301 " input text.",
drh2ce15c32017-07-11 13:34:40 +00004302#ifndef SQLITE_OMIT_TEST_CONTROL
drh98aa2ab2018-09-26 16:53:51 +00004303 ".imposter INDEX TABLE Create imposter table TABLE on index INDEX",
drh2ce15c32017-07-11 13:34:40 +00004304#endif
drh98aa2ab2018-09-26 16:53:51 +00004305 ".indexes ?TABLE? Show names of indexes",
4306 " If TABLE is specified, only show indexes for",
4307 " tables matching TABLE using the LIKE operator.",
drh2ce15c32017-07-11 13:34:40 +00004308#ifdef SQLITE_ENABLE_IOTRACE
drh98aa2ab2018-09-26 16:53:51 +00004309 ".iotrace FILE Enable I/O diagnostic logging to FILE",
drh2ce15c32017-07-11 13:34:40 +00004310#endif
drh98aa2ab2018-09-26 16:53:51 +00004311 ".limit ?LIMIT? ?VAL? Display or change the value of an SQLITE_LIMIT",
4312 ".lint OPTIONS Report potential schema issues.",
4313 " Options:",
4314 " fkey-indexes Find missing foreign key indexes",
drh2ce15c32017-07-11 13:34:40 +00004315#ifndef SQLITE_OMIT_LOAD_EXTENSION
drh98aa2ab2018-09-26 16:53:51 +00004316 ".load FILE ?ENTRY? Load an extension library",
drh2ce15c32017-07-11 13:34:40 +00004317#endif
drh98aa2ab2018-09-26 16:53:51 +00004318 ".log FILE|off Turn logging on or off. FILE can be stderr/stdout",
drh47741b82022-01-31 22:14:53 +00004319 ".mode MODE ?OPTIONS? Set output mode",
drh98aa2ab2018-09-26 16:53:51 +00004320 " MODE is one of:",
drhe40f2862022-01-31 14:14:29 +00004321 " ascii Columns/rows delimited by 0x1F and 0x1E",
4322 " box Tables using unicode box-drawing characters",
4323 " csv Comma-separated values",
4324 " column Output in columns. (See .width)",
4325 " html HTML <table> code",
4326 " insert SQL insert statements for TABLE",
4327 " json Results in a JSON array",
4328 " line One value per line",
4329 " list Values delimited by \"|\"",
4330 " markdown Markdown table format",
4331 " qbox Shorthand for \"box --width 60 --quote\"",
4332 " quote Escape answers as for SQL",
4333 " table ASCII-art table",
4334 " tabs Tab-separated values",
4335 " tcl TCL list elements",
larrybrcc4d55c2022-02-01 02:50:45 +00004336 " OPTIONS: (for columnar modes or insert mode):",
4337 " --wrap N Wrap output lines to no longer than N characters",
drhca1776b2022-02-01 12:28:17 +00004338 " --wordwrap B Wrap or not at word boundaries per B (on/off)",
4339 " --ww Shorthand for \"--wordwrap 1\"",
larrybrcc4d55c2022-02-01 02:50:45 +00004340 " --quote Quote output text as SQL literals",
4341 " --noquote Do not quote output text",
4342 " TABLE The name of SQL table used for \"insert\" mode",
4343 ".nonce STRING Suspend safe mode for one command if nonce matches",
drh98aa2ab2018-09-26 16:53:51 +00004344 ".nullvalue STRING Use STRING in place of NULL values",
drh7a431002020-04-18 14:12:00 +00004345 ".once ?OPTIONS? ?FILE? Output for the next SQL command only to FILE",
drh98aa2ab2018-09-26 16:53:51 +00004346 " If FILE begins with '|' then open as a pipe",
drh7a431002020-04-18 14:12:00 +00004347 " --bom Put a UTF8 byte-order mark at the beginning",
4348 " -e Send output to the system text editor",
4349 " -x Send output as CSV to a spreadsheet (same as \".excel\")",
drh98aa2ab2018-09-26 16:53:51 +00004350 ".open ?OPTIONS? ?FILE? Close existing database and reopen FILE",
4351 " Options:",
drh60f34ae2018-10-30 13:19:49 +00004352 " --append Use appendvfs to append database to the end of FILE",
drh8d889af2021-05-08 17:18:23 +00004353#ifndef SQLITE_OMIT_DESERIALIZE
drhd10c3ca2021-05-08 11:57:35 +00004354 " --deserialize Load into memory using sqlite3_deserialize()",
drhe2754c12019-08-26 12:50:01 +00004355 " --hexdb Load the output of \"dbtotxt\" as an in-memory db",
drh6ca64482019-01-22 16:06:20 +00004356 " --maxsize N Maximum size for --hexdb or --deserialized database",
drha751f392018-10-30 15:31:22 +00004357#endif
drh60f34ae2018-10-30 13:19:49 +00004358 " --new Initialize FILE to an empty database",
drh0933aad2019-11-18 17:46:38 +00004359 " --nofollow Do not follow symbolic links",
drh60f34ae2018-10-30 13:19:49 +00004360 " --readonly Open FILE readonly",
4361 " --zip FILE is a ZIP archive",
drh98aa2ab2018-09-26 16:53:51 +00004362 ".output ?FILE? Send output to FILE or stdout if FILE is omitted",
drh7a431002020-04-18 14:12:00 +00004363 " If FILE begins with '|' then open it as a pipe.",
4364 " Options:",
4365 " --bom Prefix output with a UTF8 byte-order mark",
4366 " -e Send output to the system text editor",
4367 " -x Send output as CSV to a spreadsheet",
drh9cb02642019-02-28 20:10:52 +00004368 ".parameter CMD ... Manage SQL parameter bindings",
4369 " clear Erase all bindings",
4370 " init Initialize the TEMP table that holds bindings",
4371 " list List the current parameter bindings",
4372 " set PARAMETER VALUE Given SQL parameter PARAMETER a value of VALUE",
drhe2754c12019-08-26 12:50:01 +00004373 " PARAMETER should start with one of: $ : @ ?",
drh9cb02642019-02-28 20:10:52 +00004374 " unset PARAMETER Remove PARAMETER from the binding table",
drh98aa2ab2018-09-26 16:53:51 +00004375 ".print STRING... Print literal STRING",
drh569b1d92019-02-05 20:51:41 +00004376#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
drh3f83f592019-02-04 14:53:18 +00004377 ".progress N Invoke progress handler after every N opcodes",
4378 " --limit N Interrupt after N progress callbacks",
4379 " --once Do no more than one progress interrupt",
4380 " --quiet|-q No output except at interrupts",
4381 " --reset Reset the count for each input and interrupt",
drh569b1d92019-02-05 20:51:41 +00004382#endif
drh98aa2ab2018-09-26 16:53:51 +00004383 ".prompt MAIN CONTINUE Replace the standard prompts",
4384 ".quit Exit this program",
larrybra2ba25b2021-12-28 05:08:38 +00004385 ".read FILE Read input from FILE or command output",
4386 " If FILE begins with \"|\", it is a command that generates the input.",
dan1b162162019-04-27 20:15:15 +00004387#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
dan42ebb012019-04-27 18:47:03 +00004388 ".recover Recover as much data as possible from corrupt db.",
drhe2754c12019-08-26 12:50:01 +00004389 " --freelist-corrupt Assume the freelist is corrupt",
4390 " --recovery-db NAME Store recovery metadata in database file NAME",
4391 " --lost-and-found TABLE Alternative name for the lost-and-found table",
dan8cce6b82019-09-14 16:44:51 +00004392 " --no-rowids Do not attempt to recover rowid values",
4393 " that are not also INTEGER PRIMARY KEYs",
dan1b162162019-04-27 20:15:15 +00004394#endif
drh98aa2ab2018-09-26 16:53:51 +00004395 ".restore ?DB? FILE Restore content of DB (default \"main\") from FILE",
larrybra7919ad2022-02-19 21:25:48 +00004396 ".save ?OPTIONS? FILE Write database to FILE (an alias for .backup ...)",
drh98aa2ab2018-09-26 16:53:51 +00004397 ".scanstats on|off Turn sqlite3_stmt_scanstatus() metrics on or off",
4398 ".schema ?PATTERN? Show the CREATE statements matching PATTERN",
drhbbb29ec2020-10-12 14:56:47 +00004399 " Options:",
4400 " --indent Try to pretty-print the schema",
4401 " --nosys Omit objects whose names start with \"sqlite_\"",
drheb7f2a02018-09-26 18:02:32 +00004402 ".selftest ?OPTIONS? Run tests defined in the SELFTEST table",
4403 " Options:",
4404 " --init Create a new SELFTEST table",
4405 " -v Verbose output",
drh98aa2ab2018-09-26 16:53:51 +00004406 ".separator COL ?ROW? Change the column and row separators",
drh2ce15c32017-07-11 13:34:40 +00004407#if defined(SQLITE_ENABLE_SESSION)
drheb7f2a02018-09-26 18:02:32 +00004408 ".session ?NAME? CMD ... Create or control sessions",
4409 " Subcommands:",
4410 " attach TABLE Attach TABLE",
4411 " changeset FILE Write a changeset into FILE",
4412 " close Close one session",
4413 " enable ?BOOLEAN? Set or query the enable bit",
4414 " filter GLOB... Reject tables matching GLOBs",
4415 " indirect ?BOOLEAN? Mark or query the indirect status",
4416 " isempty Query whether the session is empty",
4417 " list List currently open session names",
4418 " open DB NAME Open a new session on DB",
4419 " patchset FILE Write a patchset into FILE",
4420 " If ?NAME? is omitted, the first defined session is used.",
drh2ce15c32017-07-11 13:34:40 +00004421#endif
drheb7f2a02018-09-26 18:02:32 +00004422 ".sha3sum ... Compute a SHA3 hash of database content",
4423 " Options:",
drh067b92b2020-06-19 15:24:12 +00004424 " --schema Also hash the sqlite_schema table",
drheb7f2a02018-09-26 18:02:32 +00004425 " --sha3-224 Use the sha3-224 algorithm",
drhe2754c12019-08-26 12:50:01 +00004426 " --sha3-256 Use the sha3-256 algorithm (default)",
drheb7f2a02018-09-26 18:02:32 +00004427 " --sha3-384 Use the sha3-384 algorithm",
4428 " --sha3-512 Use the sha3-512 algorithm",
4429 " Any other argument is a LIKE pattern for tables to hash",
drh04a28c32018-01-31 01:38:44 +00004430#ifndef SQLITE_NOHAVE_SYSTEM
drh98aa2ab2018-09-26 16:53:51 +00004431 ".shell CMD ARGS... Run CMD ARGS... in a system shell",
drh04a28c32018-01-31 01:38:44 +00004432#endif
drh98aa2ab2018-09-26 16:53:51 +00004433 ".show Show the current values for various settings",
drha6e6cf22021-01-09 19:10:04 +00004434 ".stats ?ARG? Show stats or turn stats on or off",
4435 " off Turn off automatic stat display",
4436 " on Turn on automatic stat display",
4437 " stmt Show statement stats",
4438 " vmstep Show the virtual machine step count only",
drh04a28c32018-01-31 01:38:44 +00004439#ifndef SQLITE_NOHAVE_SYSTEM
drh98aa2ab2018-09-26 16:53:51 +00004440 ".system CMD ARGS... Run CMD ARGS... in a system shell",
drh04a28c32018-01-31 01:38:44 +00004441#endif
drh98aa2ab2018-09-26 16:53:51 +00004442 ".tables ?TABLE? List names of tables matching LIKE pattern TABLE",
4443 ".testcase NAME Begin redirecting output to 'testcase-out.txt'",
drhd985f722019-06-05 14:29:53 +00004444 ".testctrl CMD ... Run various sqlite3_test_control() operations",
4445 " Run \".testctrl\" with no arguments for details",
drh98aa2ab2018-09-26 16:53:51 +00004446 ".timeout MS Try opening locked tables for MS milliseconds",
4447 ".timer on|off Turn SQL timer on or off",
drh707821f2018-12-05 13:39:06 +00004448#ifndef SQLITE_OMIT_TRACE
4449 ".trace ?OPTIONS? Output each SQL statement as it is run",
4450 " FILE Send output to FILE",
4451 " stdout Send output to stdout",
4452 " stderr Send output to stderr",
4453 " off Disable tracing",
4454 " --expanded Expand query parameters",
4455#ifdef SQLITE_ENABLE_NORMALIZE
4456 " --normalized Normal the SQL statements",
4457#endif
4458 " --plain Show SQL as it is input",
4459 " --stmt Trace statement execution (SQLITE_TRACE_STMT)",
4460 " --profile Profile statements (SQLITE_TRACE_PROFILE)",
4461 " --row Trace each row (SQLITE_TRACE_ROW)",
4462 " --close Trace connection close (SQLITE_TRACE_CLOSE)",
4463#endif /* SQLITE_OMIT_TRACE */
drhcc5979d2019-08-16 22:58:29 +00004464#ifdef SQLITE_DEBUG
4465 ".unmodule NAME ... Unregister virtual table modules",
drh5df84282019-08-17 19:45:25 +00004466 " --allexcept Unregister everything except those named",
drhcc5979d2019-08-16 22:58:29 +00004467#endif
drh98aa2ab2018-09-26 16:53:51 +00004468 ".vfsinfo ?AUX? Information about the top-level VFS",
4469 ".vfslist List all available VFSes",
4470 ".vfsname ?AUX? Print the name of the VFS stack",
drh7da29a32020-05-29 19:17:20 +00004471 ".width NUM1 NUM2 ... Set minimum column widths for columnar output",
drh98aa2ab2018-09-26 16:53:51 +00004472 " Negative values right-justify",
4473};
4474
4475/*
4476** Output help text.
4477**
4478** zPattern describes the set of commands for which help text is provided.
4479** If zPattern is NULL, then show all commands, but only give a one-line
4480** description of each.
4481**
4482** Return the number of matches.
4483*/
4484static int showHelp(FILE *out, const char *zPattern){
drhe93f8262018-10-11 16:53:37 +00004485 int i = 0;
4486 int j = 0;
drh98aa2ab2018-09-26 16:53:51 +00004487 int n = 0;
4488 char *zPat;
drh488cddf2018-10-06 14:38:17 +00004489 if( zPattern==0
4490 || zPattern[0]=='0'
4491 || strcmp(zPattern,"-a")==0
4492 || strcmp(zPattern,"-all")==0
drh7a431002020-04-18 14:12:00 +00004493 || strcmp(zPattern,"--all")==0
drh488cddf2018-10-06 14:38:17 +00004494 ){
drh98aa2ab2018-09-26 16:53:51 +00004495 /* Show all commands, but only one line per command */
drh488cddf2018-10-06 14:38:17 +00004496 if( zPattern==0 ) zPattern = "";
drh98aa2ab2018-09-26 16:53:51 +00004497 for(i=0; i<ArraySize(azHelp); i++){
drh488cddf2018-10-06 14:38:17 +00004498 if( azHelp[i][0]=='.' || zPattern[0] ){
drh98aa2ab2018-09-26 16:53:51 +00004499 utf8_printf(out, "%s\n", azHelp[i]);
4500 n++;
4501 }
4502 }
4503 }else{
4504 /* Look for commands that for which zPattern is an exact prefix */
4505 zPat = sqlite3_mprintf(".%s*", zPattern);
drhe3e25652021-12-16 13:29:28 +00004506 shell_check_oom(zPat);
drh98aa2ab2018-09-26 16:53:51 +00004507 for(i=0; i<ArraySize(azHelp); i++){
4508 if( sqlite3_strglob(zPat, azHelp[i])==0 ){
4509 utf8_printf(out, "%s\n", azHelp[i]);
drheb7f2a02018-09-26 18:02:32 +00004510 j = i+1;
drh98aa2ab2018-09-26 16:53:51 +00004511 n++;
4512 }
4513 }
4514 sqlite3_free(zPat);
drheb7f2a02018-09-26 18:02:32 +00004515 if( n ){
4516 if( n==1 ){
4517 /* when zPattern is a prefix of exactly one command, then include the
4518 ** details of that command, which should begin at offset j */
4519 while( j<ArraySize(azHelp)-1 && azHelp[j][0]!='.' ){
4520 utf8_printf(out, "%s\n", azHelp[j]);
4521 j++;
4522 }
4523 }
4524 return n;
4525 }
4526 /* Look for commands that contain zPattern anywhere. Show the complete
4527 ** text of all commands that match. */
drh98aa2ab2018-09-26 16:53:51 +00004528 zPat = sqlite3_mprintf("%%%s%%", zPattern);
drhe3e25652021-12-16 13:29:28 +00004529 shell_check_oom(zPat);
drh98aa2ab2018-09-26 16:53:51 +00004530 for(i=0; i<ArraySize(azHelp); i++){
4531 if( azHelp[i][0]=='.' ) j = i;
4532 if( sqlite3_strlike(zPat, azHelp[i], 0)==0 ){
4533 utf8_printf(out, "%s\n", azHelp[j]);
4534 while( j<ArraySize(azHelp)-1 && azHelp[j+1][0]!='.' ){
4535 j++;
4536 utf8_printf(out, "%s\n", azHelp[j]);
4537 }
4538 i = j;
4539 n++;
4540 }
4541 }
4542 sqlite3_free(zPat);
4543 }
4544 return n;
4545}
drh2ce15c32017-07-11 13:34:40 +00004546
drh2ce15c32017-07-11 13:34:40 +00004547/* Forward reference */
drh60379d42018-12-13 18:30:01 +00004548static int process_input(ShellState *p);
drh2ce15c32017-07-11 13:34:40 +00004549
4550/*
4551** Read the content of file zName into memory obtained from sqlite3_malloc64()
4552** and return a pointer to the buffer. The caller is responsible for freeing
4553** the memory.
4554**
4555** If parameter pnByte is not NULL, (*pnByte) is set to the number of bytes
4556** read.
4557**
4558** For convenience, a nul-terminator byte is always appended to the data read
4559** from the file before the buffer is returned. This byte is not included in
4560** the final value of (*pnByte), if applicable.
4561**
4562** NULL is returned if any error is encountered. The final value of *pnByte
4563** is undefined in this case.
4564*/
4565static char *readFile(const char *zName, int *pnByte){
4566 FILE *in = fopen(zName, "rb");
4567 long nIn;
4568 size_t nRead;
4569 char *pBuf;
4570 if( in==0 ) return 0;
4571 fseek(in, 0, SEEK_END);
4572 nIn = ftell(in);
4573 rewind(in);
4574 pBuf = sqlite3_malloc64( nIn+1 );
drh1dbb1472018-10-11 10:37:24 +00004575 if( pBuf==0 ){ fclose(in); return 0; }
drh2ce15c32017-07-11 13:34:40 +00004576 nRead = fread(pBuf, nIn, 1, in);
4577 fclose(in);
4578 if( nRead!=1 ){
4579 sqlite3_free(pBuf);
4580 return 0;
4581 }
4582 pBuf[nIn] = 0;
4583 if( pnByte ) *pnByte = nIn;
4584 return pBuf;
4585}
4586
4587#if defined(SQLITE_ENABLE_SESSION)
4588/*
4589** Close a single OpenSession object and release all of its associated
4590** resources.
4591*/
4592static void session_close(OpenSession *pSession){
4593 int i;
4594 sqlite3session_delete(pSession->p);
4595 sqlite3_free(pSession->zName);
4596 for(i=0; i<pSession->nFilter; i++){
4597 sqlite3_free(pSession->azFilter[i]);
4598 }
4599 sqlite3_free(pSession->azFilter);
4600 memset(pSession, 0, sizeof(OpenSession));
4601}
4602#endif
4603
4604/*
4605** Close all OpenSession objects and release all associated resources.
4606*/
4607#if defined(SQLITE_ENABLE_SESSION)
drh37407122021-07-23 18:43:58 +00004608static void session_close_all(ShellState *p, int i){
4609 int j;
4610 struct AuxDb *pAuxDb = i<0 ? p->pAuxDb : &p->aAuxDb[i];
4611 for(j=0; j<pAuxDb->nSession; j++){
4612 session_close(&pAuxDb->aSession[j]);
drh2ce15c32017-07-11 13:34:40 +00004613 }
drh37407122021-07-23 18:43:58 +00004614 pAuxDb->nSession = 0;
drh2ce15c32017-07-11 13:34:40 +00004615}
4616#else
drh37407122021-07-23 18:43:58 +00004617# define session_close_all(X,Y)
drh2ce15c32017-07-11 13:34:40 +00004618#endif
4619
4620/*
4621** Implementation of the xFilter function for an open session. Omit
4622** any tables named by ".session filter" but let all other table through.
4623*/
4624#if defined(SQLITE_ENABLE_SESSION)
4625static int session_filter(void *pCtx, const char *zTab){
4626 OpenSession *pSession = (OpenSession*)pCtx;
4627 int i;
4628 for(i=0; i<pSession->nFilter; i++){
4629 if( sqlite3_strglob(pSession->azFilter[i], zTab)==0 ) return 0;
4630 }
4631 return 1;
4632}
4633#endif
4634
4635/*
drh1fa6d9f2018-01-06 21:46:01 +00004636** Try to deduce the type of file for zName based on its content. Return
4637** one of the SHELL_OPEN_* constants.
drh1bf208c2018-03-09 21:54:01 +00004638**
4639** If the file does not exist or is empty but its name looks like a ZIP
4640** archive and the dfltZip flag is true, then assume it is a ZIP archive.
4641** Otherwise, assume an ordinary database regardless of the filename if
4642** the type cannot be determined from content.
drh1fa6d9f2018-01-06 21:46:01 +00004643*/
drhfc97c1c2018-05-14 00:41:12 +00004644int deduceDatabaseType(const char *zName, int dfltZip){
drh1fa6d9f2018-01-06 21:46:01 +00004645 FILE *f = fopen(zName, "rb");
4646 size_t n;
4647 int rc = SHELL_OPEN_UNSPEC;
4648 char zBuf[100];
drh1bf208c2018-03-09 21:54:01 +00004649 if( f==0 ){
drhbe4ccb22018-05-17 20:04:24 +00004650 if( dfltZip && sqlite3_strlike("%.zip",zName,0)==0 ){
4651 return SHELL_OPEN_ZIPFILE;
4652 }else{
4653 return SHELL_OPEN_NORMAL;
4654 }
drh1bf208c2018-03-09 21:54:01 +00004655 }
drh2b3c4af2018-10-30 14:36:21 +00004656 n = fread(zBuf, 16, 1, f);
4657 if( n==1 && memcmp(zBuf, "SQLite format 3", 16)==0 ){
4658 fclose(f);
4659 return SHELL_OPEN_NORMAL;
4660 }
drh1fa6d9f2018-01-06 21:46:01 +00004661 fseek(f, -25, SEEK_END);
4662 n = fread(zBuf, 25, 1, f);
4663 if( n==1 && memcmp(zBuf, "Start-Of-SQLite3-", 17)==0 ){
4664 rc = SHELL_OPEN_APPENDVFS;
4665 }else{
4666 fseek(f, -22, SEEK_END);
4667 n = fread(zBuf, 22, 1, f);
4668 if( n==1 && zBuf[0]==0x50 && zBuf[1]==0x4b && zBuf[2]==0x05
4669 && zBuf[3]==0x06 ){
4670 rc = SHELL_OPEN_ZIPFILE;
drh1bf208c2018-03-09 21:54:01 +00004671 }else if( n==0 && dfltZip && sqlite3_strlike("%.zip",zName,0)==0 ){
mistachkina3926f42018-05-14 12:23:04 +00004672 rc = SHELL_OPEN_ZIPFILE;
drh1fa6d9f2018-01-06 21:46:01 +00004673 }
4674 }
4675 fclose(f);
4676 return rc;
4677}
4678
drh8d889af2021-05-08 17:18:23 +00004679#ifndef SQLITE_OMIT_DESERIALIZE
drh33746482018-12-13 15:06:26 +00004680/*
4681** Reconstruct an in-memory database using the output from the "dbtotxt"
drh37407122021-07-23 18:43:58 +00004682** program. Read content from the file in p->aAuxDb[].zDbFilename.
4683** If p->aAuxDb[].zDbFilename is 0, then read from standard input.
drh33746482018-12-13 15:06:26 +00004684*/
4685static unsigned char *readHexDb(ShellState *p, int *pnData){
4686 unsigned char *a = 0;
drh2c8ee022018-12-13 18:59:30 +00004687 int nLine;
drh33746482018-12-13 15:06:26 +00004688 int n = 0;
4689 int pgsz = 0;
4690 int iOffset = 0;
4691 int j, k;
4692 int rc;
4693 FILE *in;
drh37407122021-07-23 18:43:58 +00004694 const char *zDbFilename = p->pAuxDb->zDbFilename;
drh3ea557e2019-04-23 15:30:58 +00004695 unsigned int x[16];
drh2c8ee022018-12-13 18:59:30 +00004696 char zLine[1000];
drh37407122021-07-23 18:43:58 +00004697 if( zDbFilename ){
4698 in = fopen(zDbFilename, "r");
drh33746482018-12-13 15:06:26 +00004699 if( in==0 ){
drh37407122021-07-23 18:43:58 +00004700 utf8_printf(stderr, "cannot open \"%s\" for reading\n", zDbFilename);
drh33746482018-12-13 15:06:26 +00004701 return 0;
4702 }
drh2c8ee022018-12-13 18:59:30 +00004703 nLine = 0;
drh33746482018-12-13 15:06:26 +00004704 }else{
drh60379d42018-12-13 18:30:01 +00004705 in = p->in;
drh2c8ee022018-12-13 18:59:30 +00004706 nLine = p->lineno;
drh5bf46442019-05-03 02:41:36 +00004707 if( in==0 ) in = stdin;
drh33746482018-12-13 15:06:26 +00004708 }
4709 *pnData = 0;
drh2c8ee022018-12-13 18:59:30 +00004710 nLine++;
drh33746482018-12-13 15:06:26 +00004711 if( fgets(zLine, sizeof(zLine), in)==0 ) goto readHexDb_error;
4712 rc = sscanf(zLine, "| size %d pagesize %d", &n, &pgsz);
4713 if( rc!=2 ) goto readHexDb_error;
drh68feae52019-05-09 11:18:41 +00004714 if( n<0 ) goto readHexDb_error;
drh09ea1252019-07-17 15:05:16 +00004715 if( pgsz<512 || pgsz>65536 || (pgsz&(pgsz-1))!=0 ) goto readHexDb_error;
4716 n = (n+pgsz-1)&~(pgsz-1); /* Round n up to the next multiple of pgsz */
drh68feae52019-05-09 11:18:41 +00004717 a = sqlite3_malloc( n ? n : 1 );
drhe3e25652021-12-16 13:29:28 +00004718 shell_check_oom(a);
drh33746482018-12-13 15:06:26 +00004719 memset(a, 0, n);
4720 if( pgsz<512 || pgsz>65536 || (pgsz & (pgsz-1))!=0 ){
4721 utf8_printf(stderr, "invalid pagesize\n");
4722 goto readHexDb_error;
4723 }
drh2c8ee022018-12-13 18:59:30 +00004724 for(nLine++; fgets(zLine, sizeof(zLine), in)!=0; nLine++){
drh33746482018-12-13 15:06:26 +00004725 rc = sscanf(zLine, "| page %d offset %d", &j, &k);
4726 if( rc==2 ){
4727 iOffset = k;
4728 continue;
4729 }
4730 if( strncmp(zLine, "| end ", 6)==0 ){
4731 break;
4732 }
drh3ea557e2019-04-23 15:30:58 +00004733 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 +00004734 &j, &x[0], &x[1], &x[2], &x[3], &x[4], &x[5], &x[6], &x[7],
4735 &x[8], &x[9], &x[10], &x[11], &x[12], &x[13], &x[14], &x[15]);
4736 if( rc==17 ){
4737 k = iOffset+j;
drh82978ac2021-10-01 17:06:44 +00004738 if( k+16<=n && k>=0 ){
drh3ea557e2019-04-23 15:30:58 +00004739 int ii;
4740 for(ii=0; ii<16; ii++) a[k+ii] = x[ii]&0xff;
drh33746482018-12-13 15:06:26 +00004741 }
drh33746482018-12-13 15:06:26 +00004742 }
4743 }
4744 *pnData = n;
drh2c8ee022018-12-13 18:59:30 +00004745 if( in!=p->in ){
4746 fclose(in);
4747 }else{
4748 p->lineno = nLine;
4749 }
drh33746482018-12-13 15:06:26 +00004750 return a;
4751
4752readHexDb_error:
drh68feae52019-05-09 11:18:41 +00004753 if( in!=p->in ){
drh33746482018-12-13 15:06:26 +00004754 fclose(in);
4755 }else{
drh60379d42018-12-13 18:30:01 +00004756 while( fgets(zLine, sizeof(zLine), p->in)!=0 ){
drh2c8ee022018-12-13 18:59:30 +00004757 nLine++;
drh33746482018-12-13 15:06:26 +00004758 if(strncmp(zLine, "| end ", 6)==0 ) break;
4759 }
drh2c8ee022018-12-13 18:59:30 +00004760 p->lineno = nLine;
drh33746482018-12-13 15:06:26 +00004761 }
4762 sqlite3_free(a);
4763 utf8_printf(stderr,"Error on line %d of --hexdb input\n", nLine);
4764 return 0;
4765}
drh8d889af2021-05-08 17:18:23 +00004766#endif /* SQLITE_OMIT_DESERIALIZE */
drh33746482018-12-13 15:06:26 +00004767
danb1825882019-04-23 20:48:32 +00004768/*
dan9c014f82019-04-25 19:23:15 +00004769** Scalar function "shell_int32". The first argument to this function
4770** must be a blob. The second a non-negative integer. This function
4771** reads and returns a 32-bit big-endian integer from byte
4772** offset (4*<arg2>) of the blob.
4773*/
4774static void shellInt32(
4775 sqlite3_context *context,
4776 int argc,
4777 sqlite3_value **argv
4778){
4779 const unsigned char *pBlob;
4780 int nBlob;
4781 int iInt;
drh9546c762019-05-10 17:50:33 +00004782
4783 UNUSED_PARAMETER(argc);
dan9c014f82019-04-25 19:23:15 +00004784 nBlob = sqlite3_value_bytes(argv[0]);
4785 pBlob = (const unsigned char*)sqlite3_value_blob(argv[0]);
4786 iInt = sqlite3_value_int(argv[1]);
4787
4788 if( iInt>=0 && (iInt+1)*4<=nBlob ){
4789 const unsigned char *a = &pBlob[iInt*4];
4790 sqlite3_int64 iVal = ((sqlite3_int64)a[0]<<24)
4791 + ((sqlite3_int64)a[1]<<16)
4792 + ((sqlite3_int64)a[2]<< 8)
4793 + ((sqlite3_int64)a[3]<< 0);
4794 sqlite3_result_int64(context, iVal);
4795 }
4796}
4797
4798/*
drha2de66c2019-08-06 20:26:17 +00004799** Scalar function "shell_idquote(X)" returns string X quoted as an identifier,
4800** using "..." with internal double-quote characters doubled.
4801*/
4802static void shellIdQuote(
4803 sqlite3_context *context,
4804 int argc,
4805 sqlite3_value **argv
4806){
4807 const char *zName = (const char*)sqlite3_value_text(argv[0]);
drh51755a72019-08-08 19:40:29 +00004808 UNUSED_PARAMETER(argc);
drha2de66c2019-08-06 20:26:17 +00004809 if( zName ){
4810 char *z = sqlite3_mprintf("\"%w\"", zName);
4811 sqlite3_result_text(context, z, -1, sqlite3_free);
4812 }
4813}
4814
4815/*
drhddcfe922020-09-15 12:29:35 +00004816** Scalar function "usleep(X)" invokes sqlite3_sleep(X) and returns X.
4817*/
4818static void shellUSleepFunc(
4819 sqlite3_context *context,
drhd36f5882020-11-25 16:28:04 +00004820 int argcUnused,
drhddcfe922020-09-15 12:29:35 +00004821 sqlite3_value **argv
4822){
4823 int sleep = sqlite3_value_int(argv[0]);
drhd36f5882020-11-25 16:28:04 +00004824 (void)argcUnused;
drhddcfe922020-09-15 12:29:35 +00004825 sqlite3_sleep(sleep/1000);
4826 sqlite3_result_int(context, sleep);
4827}
4828
4829/*
danb1825882019-04-23 20:48:32 +00004830** Scalar function "shell_escape_crnl" used by the .recover command.
4831** The argument passed to this function is the output of built-in
4832** function quote(). If the first character of the input is "'",
4833** indicating that the value passed to quote() was a text value,
4834** then this function searches the input for "\n" and "\r" characters
4835** and adds a wrapper similar to the following:
4836**
4837** replace(replace(<input>, '\n', char(10), '\r', char(13));
4838**
4839** Or, if the first character of the input is not "'", then a copy
4840** of the input is returned.
4841*/
4842static void shellEscapeCrnl(
4843 sqlite3_context *context,
4844 int argc,
4845 sqlite3_value **argv
4846){
4847 const char *zText = (const char*)sqlite3_value_text(argv[0]);
drh9546c762019-05-10 17:50:33 +00004848 UNUSED_PARAMETER(argc);
drh621a5e02021-12-16 17:35:27 +00004849 if( zText && zText[0]=='\'' ){
danb1825882019-04-23 20:48:32 +00004850 int nText = sqlite3_value_bytes(argv[0]);
4851 int i;
4852 char zBuf1[20];
4853 char zBuf2[20];
4854 const char *zNL = 0;
4855 const char *zCR = 0;
4856 int nCR = 0;
4857 int nNL = 0;
4858
4859 for(i=0; zText[i]; i++){
4860 if( zNL==0 && zText[i]=='\n' ){
4861 zNL = unused_string(zText, "\\n", "\\012", zBuf1);
4862 nNL = (int)strlen(zNL);
4863 }
4864 if( zCR==0 && zText[i]=='\r' ){
4865 zCR = unused_string(zText, "\\r", "\\015", zBuf2);
4866 nCR = (int)strlen(zCR);
4867 }
4868 }
4869
4870 if( zNL || zCR ){
4871 int iOut = 0;
4872 i64 nMax = (nNL > nCR) ? nNL : nCR;
dan51f5ffa2019-04-29 11:41:46 +00004873 i64 nAlloc = nMax * nText + (nMax+64)*2;
danb1825882019-04-23 20:48:32 +00004874 char *zOut = (char*)sqlite3_malloc64(nAlloc);
4875 if( zOut==0 ){
4876 sqlite3_result_error_nomem(context);
4877 return;
4878 }
4879
4880 if( zNL && zCR ){
4881 memcpy(&zOut[iOut], "replace(replace(", 16);
4882 iOut += 16;
4883 }else{
4884 memcpy(&zOut[iOut], "replace(", 8);
4885 iOut += 8;
4886 }
4887 for(i=0; zText[i]; i++){
4888 if( zText[i]=='\n' ){
4889 memcpy(&zOut[iOut], zNL, nNL);
4890 iOut += nNL;
4891 }else if( zText[i]=='\r' ){
4892 memcpy(&zOut[iOut], zCR, nCR);
4893 iOut += nCR;
4894 }else{
4895 zOut[iOut] = zText[i];
4896 iOut++;
4897 }
4898 }
4899
4900 if( zNL ){
4901 memcpy(&zOut[iOut], ",'", 2); iOut += 2;
4902 memcpy(&zOut[iOut], zNL, nNL); iOut += nNL;
4903 memcpy(&zOut[iOut], "', char(10))", 12); iOut += 12;
4904 }
4905 if( zCR ){
4906 memcpy(&zOut[iOut], ",'", 2); iOut += 2;
4907 memcpy(&zOut[iOut], zCR, nCR); iOut += nCR;
4908 memcpy(&zOut[iOut], "', char(13))", 12); iOut += 12;
4909 }
4910
4911 sqlite3_result_text(context, zOut, iOut, SQLITE_TRANSIENT);
4912 sqlite3_free(zOut);
4913 return;
4914 }
4915 }
4916
4917 sqlite3_result_value(context, argv[0]);
4918}
4919
drhbe4ccb22018-05-17 20:04:24 +00004920/* Flags for open_db().
4921**
4922** The default behavior of open_db() is to exit(1) if the database fails to
4923** open. The OPEN_DB_KEEPALIVE flag changes that so that it prints an error
4924** but still returns without calling exit.
4925**
4926** The OPEN_DB_ZIPFILE flag causes open_db() to prefer to open files as a
4927** ZIP archive if the file does not exist or is empty and its name matches
4928** the *.zip pattern.
4929*/
4930#define OPEN_DB_KEEPALIVE 0x001 /* Return after error if true */
4931#define OPEN_DB_ZIPFILE 0x002 /* Open as ZIP if name matches *.zip */
4932
drh1fa6d9f2018-01-06 21:46:01 +00004933/*
drh2ce15c32017-07-11 13:34:40 +00004934** Make sure the database is open. If it is not, then open it. If
4935** the database fails to open, print an error message and exit.
4936*/
drhbe4ccb22018-05-17 20:04:24 +00004937static void open_db(ShellState *p, int openFlags){
drh2ce15c32017-07-11 13:34:40 +00004938 if( p->db==0 ){
drh37407122021-07-23 18:43:58 +00004939 const char *zDbFilename = p->pAuxDb->zDbFilename;
drhf2072d12018-05-11 15:10:11 +00004940 if( p->openMode==SHELL_OPEN_UNSPEC ){
drh37407122021-07-23 18:43:58 +00004941 if( zDbFilename==0 || zDbFilename[0]==0 ){
drhf2072d12018-05-11 15:10:11 +00004942 p->openMode = SHELL_OPEN_NORMAL;
drhbe4ccb22018-05-17 20:04:24 +00004943 }else{
drh37407122021-07-23 18:43:58 +00004944 p->openMode = (u8)deduceDatabaseType(zDbFilename,
drhbe4ccb22018-05-17 20:04:24 +00004945 (openFlags & OPEN_DB_ZIPFILE)!=0);
drhf2072d12018-05-11 15:10:11 +00004946 }
drh1fa6d9f2018-01-06 21:46:01 +00004947 }
4948 switch( p->openMode ){
4949 case SHELL_OPEN_APPENDVFS: {
drh37407122021-07-23 18:43:58 +00004950 sqlite3_open_v2(zDbFilename, &p->db,
drh0933aad2019-11-18 17:46:38 +00004951 SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|p->openFlags, "apndvfs");
drh1fa6d9f2018-01-06 21:46:01 +00004952 break;
4953 }
drh33746482018-12-13 15:06:26 +00004954 case SHELL_OPEN_HEXDB:
drh60f34ae2018-10-30 13:19:49 +00004955 case SHELL_OPEN_DESERIALIZE: {
4956 sqlite3_open(0, &p->db);
4957 break;
4958 }
drh1fa6d9f2018-01-06 21:46:01 +00004959 case SHELL_OPEN_ZIPFILE: {
4960 sqlite3_open(":memory:", &p->db);
4961 break;
4962 }
drhee269a62018-02-14 23:27:43 +00004963 case SHELL_OPEN_READONLY: {
drh37407122021-07-23 18:43:58 +00004964 sqlite3_open_v2(zDbFilename, &p->db,
drh0933aad2019-11-18 17:46:38 +00004965 SQLITE_OPEN_READONLY|p->openFlags, 0);
drhee269a62018-02-14 23:27:43 +00004966 break;
4967 }
drh1fa6d9f2018-01-06 21:46:01 +00004968 case SHELL_OPEN_UNSPEC:
4969 case SHELL_OPEN_NORMAL: {
drh37407122021-07-23 18:43:58 +00004970 sqlite3_open_v2(zDbFilename, &p->db,
drh0933aad2019-11-18 17:46:38 +00004971 SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|p->openFlags, 0);
drh1fa6d9f2018-01-06 21:46:01 +00004972 break;
4973 }
4974 }
drh2ce15c32017-07-11 13:34:40 +00004975 globalDb = p->db;
4976 if( p->db==0 || SQLITE_OK!=sqlite3_errcode(p->db) ){
4977 utf8_printf(stderr,"Error: unable to open database \"%s\": %s\n",
drh37407122021-07-23 18:43:58 +00004978 zDbFilename, sqlite3_errmsg(p->db));
drhf25cc4f2019-01-04 14:29:21 +00004979 if( openFlags & OPEN_DB_KEEPALIVE ){
4980 sqlite3_open(":memory:", &p->db);
4981 return;
4982 }
drh2ce15c32017-07-11 13:34:40 +00004983 exit(1);
4984 }
4985#ifndef SQLITE_OMIT_LOAD_EXTENSION
4986 sqlite3_enable_load_extension(p->db, 1);
4987#endif
4988 sqlite3_fileio_init(p->db, 0, 0);
4989 sqlite3_shathree_init(p->db, 0, 0);
drh56eb09b2017-07-11 13:59:07 +00004990 sqlite3_completion_init(p->db, 0, 0);
drhf05dd032020-04-14 15:53:58 +00004991 sqlite3_uint_init(p->db, 0, 0);
drhbeb9def2020-06-22 19:12:23 +00004992 sqlite3_decimal_init(p->db, 0, 0);
drh64689902021-06-03 13:51:31 +00004993 sqlite3_regexp_init(p->db, 0, 0);
drh8cda77d2020-06-24 15:06:29 +00004994 sqlite3_ieee_init(p->db, 0, 0);
mistachkin72c38d82020-08-28 18:47:39 +00004995 sqlite3_series_init(p->db, 0, 0);
dan1b162162019-04-27 20:15:15 +00004996#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
dan68cb86e2019-04-20 20:57:28 +00004997 sqlite3_dbdata_init(p->db, 0, 0);
dan1b162162019-04-27 20:15:15 +00004998#endif
dan72afc3c2017-12-05 18:32:40 +00004999#ifdef SQLITE_HAVE_ZLIB
drh9198f5a2022-03-19 15:19:35 +00005000 if( !p->bSafeModePersist ){
5001 sqlite3_zipfile_init(p->db, 0, 0);
5002 sqlite3_sqlar_init(p->db, 0, 0);
5003 }
dan72afc3c2017-12-05 18:32:40 +00005004#endif
drhceba7922018-01-01 21:28:25 +00005005 sqlite3_create_function(p->db, "shell_add_schema", 3, SQLITE_UTF8, 0,
drh2ce15c32017-07-11 13:34:40 +00005006 shellAddSchemaName, 0, 0);
drh667a2a22018-01-02 00:04:37 +00005007 sqlite3_create_function(p->db, "shell_module_schema", 1, SQLITE_UTF8, 0,
5008 shellModuleSchema, 0, 0);
drh634c70f2018-01-10 16:50:18 +00005009 sqlite3_create_function(p->db, "shell_putsnl", 1, SQLITE_UTF8, p,
5010 shellPutsFunc, 0, 0);
danb1825882019-04-23 20:48:32 +00005011 sqlite3_create_function(p->db, "shell_escape_crnl", 1, SQLITE_UTF8, 0,
5012 shellEscapeCrnl, 0, 0);
dan9c014f82019-04-25 19:23:15 +00005013 sqlite3_create_function(p->db, "shell_int32", 2, SQLITE_UTF8, 0,
5014 shellInt32, 0, 0);
drha2de66c2019-08-06 20:26:17 +00005015 sqlite3_create_function(p->db, "shell_idquote", 1, SQLITE_UTF8, 0,
5016 shellIdQuote, 0, 0);
drhddcfe922020-09-15 12:29:35 +00005017 sqlite3_create_function(p->db, "usleep",1,SQLITE_UTF8,0,
5018 shellUSleepFunc, 0, 0);
drh04a28c32018-01-31 01:38:44 +00005019#ifndef SQLITE_NOHAVE_SYSTEM
drh97913132018-01-11 00:04:00 +00005020 sqlite3_create_function(p->db, "edit", 1, SQLITE_UTF8, 0,
5021 editFunc, 0, 0);
5022 sqlite3_create_function(p->db, "edit", 2, SQLITE_UTF8, 0,
5023 editFunc, 0, 0);
drh04a28c32018-01-31 01:38:44 +00005024#endif
drh1fa6d9f2018-01-06 21:46:01 +00005025 if( p->openMode==SHELL_OPEN_ZIPFILE ){
5026 char *zSql = sqlite3_mprintf(
drh37407122021-07-23 18:43:58 +00005027 "CREATE VIRTUAL TABLE zip USING zipfile(%Q);", zDbFilename);
drhe3e25652021-12-16 13:29:28 +00005028 shell_check_oom(zSql);
drh1fa6d9f2018-01-06 21:46:01 +00005029 sqlite3_exec(p->db, zSql, 0, 0, 0);
5030 sqlite3_free(zSql);
drha751f392018-10-30 15:31:22 +00005031 }
drh8d889af2021-05-08 17:18:23 +00005032#ifndef SQLITE_OMIT_DESERIALIZE
drh33746482018-12-13 15:06:26 +00005033 else
5034 if( p->openMode==SHELL_OPEN_DESERIALIZE || p->openMode==SHELL_OPEN_HEXDB ){
mistachkin99490932018-12-17 22:19:57 +00005035 int rc;
drh60f34ae2018-10-30 13:19:49 +00005036 int nData = 0;
drh33746482018-12-13 15:06:26 +00005037 unsigned char *aData;
5038 if( p->openMode==SHELL_OPEN_DESERIALIZE ){
drh37407122021-07-23 18:43:58 +00005039 aData = (unsigned char*)readFile(zDbFilename, &nData);
drh33746482018-12-13 15:06:26 +00005040 }else{
5041 aData = readHexDb(p, &nData);
5042 if( aData==0 ){
drh33746482018-12-13 15:06:26 +00005043 return;
5044 }
5045 }
mistachkin99490932018-12-17 22:19:57 +00005046 rc = sqlite3_deserialize(p->db, "main", aData, nData, nData,
drh60f34ae2018-10-30 13:19:49 +00005047 SQLITE_DESERIALIZE_RESIZEABLE |
5048 SQLITE_DESERIALIZE_FREEONCLOSE);
5049 if( rc ){
5050 utf8_printf(stderr, "Error: sqlite3_deserialize() returns %d\n", rc);
5051 }
drh6ca64482019-01-22 16:06:20 +00005052 if( p->szMax>0 ){
5053 sqlite3_file_control(p->db, "main", SQLITE_FCNTL_SIZE_LIMIT, &p->szMax);
5054 }
drh1fa6d9f2018-01-06 21:46:01 +00005055 }
drha751f392018-10-30 15:31:22 +00005056#endif
drh2ce15c32017-07-11 13:34:40 +00005057 }
drhb97e2ad2021-08-26 18:31:39 +00005058 if( p->bSafeModePersist && p->db!=0 ){
5059 sqlite3_set_authorizer(p->db, safeModeAuth, p);
5060 }
drh2ce15c32017-07-11 13:34:40 +00005061}
5062
drh9e804032018-05-18 17:11:50 +00005063/*
5064** Attempt to close the databaes connection. Report errors.
5065*/
5066void close_db(sqlite3 *db){
5067 int rc = sqlite3_close(db);
5068 if( rc ){
5069 utf8_printf(stderr, "Error: sqlite3_close() returns %d: %s\n",
5070 rc, sqlite3_errmsg(db));
5071 }
5072}
5073
drh56eb09b2017-07-11 13:59:07 +00005074#if HAVE_READLINE || HAVE_EDITLINE
5075/*
5076** Readline completion callbacks
5077*/
5078static char *readline_completion_generator(const char *text, int state){
5079 static sqlite3_stmt *pStmt = 0;
5080 char *zRet;
5081 if( state==0 ){
5082 char *zSql;
drh56eb09b2017-07-11 13:59:07 +00005083 sqlite3_finalize(pStmt);
5084 zSql = sqlite3_mprintf("SELECT DISTINCT candidate COLLATE nocase"
5085 " FROM completion(%Q) ORDER BY 1", text);
drhe3e25652021-12-16 13:29:28 +00005086 shell_check_oom(zSql);
drh56eb09b2017-07-11 13:59:07 +00005087 sqlite3_prepare_v2(globalDb, zSql, -1, &pStmt, 0);
5088 sqlite3_free(zSql);
5089 }
5090 if( sqlite3_step(pStmt)==SQLITE_ROW ){
drh621a5e02021-12-16 17:35:27 +00005091 const char *z = (const char*)sqlite3_column_text(pStmt,0);
5092 zRet = z ? strdup(z) : 0;
drh56eb09b2017-07-11 13:59:07 +00005093 }else{
5094 sqlite3_finalize(pStmt);
5095 pStmt = 0;
5096 zRet = 0;
5097 }
5098 return zRet;
5099}
5100static char **readline_completion(const char *zText, int iStart, int iEnd){
5101 rl_attempted_completion_over = 1;
5102 return rl_completion_matches(zText, readline_completion_generator);
5103}
5104
5105#elif HAVE_LINENOISE
5106/*
5107** Linenoise completion callback
5108*/
5109static void linenoise_completion(const char *zLine, linenoiseCompletions *lc){
drhaf2770f2018-01-05 14:55:43 +00005110 int nLine = strlen30(zLine);
drh56eb09b2017-07-11 13:59:07 +00005111 int i, iStart;
5112 sqlite3_stmt *pStmt = 0;
5113 char *zSql;
5114 char zBuf[1000];
5115
5116 if( nLine>sizeof(zBuf)-30 ) return;
drh1615c372018-05-12 23:56:22 +00005117 if( zLine[0]=='.' || zLine[0]=='#') return;
drh56eb09b2017-07-11 13:59:07 +00005118 for(i=nLine-1; i>=0 && (isalnum(zLine[i]) || zLine[i]=='_'); i--){}
5119 if( i==nLine-1 ) return;
5120 iStart = i+1;
5121 memcpy(zBuf, zLine, iStart);
5122 zSql = sqlite3_mprintf("SELECT DISTINCT candidate COLLATE nocase"
5123 " FROM completion(%Q,%Q) ORDER BY 1",
5124 &zLine[iStart], zLine);
drhe3e25652021-12-16 13:29:28 +00005125 shell_check_oom(zSql);
drh56eb09b2017-07-11 13:59:07 +00005126 sqlite3_prepare_v2(globalDb, zSql, -1, &pStmt, 0);
5127 sqlite3_free(zSql);
5128 sqlite3_exec(globalDb, "PRAGMA page_count", 0, 0, 0); /* Load the schema */
5129 while( sqlite3_step(pStmt)==SQLITE_ROW ){
5130 const char *zCompletion = (const char*)sqlite3_column_text(pStmt, 0);
5131 int nCompletion = sqlite3_column_bytes(pStmt, 0);
drh621a5e02021-12-16 17:35:27 +00005132 if( iStart+nCompletion < sizeof(zBuf)-1 && zCompletion ){
drh56eb09b2017-07-11 13:59:07 +00005133 memcpy(zBuf+iStart, zCompletion, nCompletion+1);
5134 linenoiseAddCompletion(lc, zBuf);
5135 }
5136 }
5137 sqlite3_finalize(pStmt);
5138}
5139#endif
5140
drh2ce15c32017-07-11 13:34:40 +00005141/*
5142** Do C-language style dequoting.
5143**
5144** \a -> alarm
5145** \b -> backspace
5146** \t -> tab
5147** \n -> newline
5148** \v -> vertical tab
5149** \f -> form feed
5150** \r -> carriage return
5151** \s -> space
5152** \" -> "
5153** \' -> '
5154** \\ -> backslash
5155** \NNN -> ascii character NNN in octal
5156*/
5157static void resolve_backslashes(char *z){
5158 int i, j;
5159 char c;
5160 while( *z && *z!='\\' ) z++;
5161 for(i=j=0; (c = z[i])!=0; i++, j++){
5162 if( c=='\\' && z[i+1]!=0 ){
5163 c = z[++i];
5164 if( c=='a' ){
5165 c = '\a';
5166 }else if( c=='b' ){
5167 c = '\b';
5168 }else if( c=='t' ){
5169 c = '\t';
5170 }else if( c=='n' ){
5171 c = '\n';
5172 }else if( c=='v' ){
5173 c = '\v';
5174 }else if( c=='f' ){
5175 c = '\f';
5176 }else if( c=='r' ){
5177 c = '\r';
5178 }else if( c=='"' ){
5179 c = '"';
5180 }else if( c=='\'' ){
5181 c = '\'';
5182 }else if( c=='\\' ){
5183 c = '\\';
5184 }else if( c>='0' && c<='7' ){
5185 c -= '0';
5186 if( z[i+1]>='0' && z[i+1]<='7' ){
5187 i++;
5188 c = (c<<3) + z[i] - '0';
5189 if( z[i+1]>='0' && z[i+1]<='7' ){
5190 i++;
5191 c = (c<<3) + z[i] - '0';
5192 }
5193 }
5194 }
5195 }
5196 z[j] = c;
5197 }
5198 if( j<i ) z[j] = 0;
5199}
5200
5201/*
drh2ce15c32017-07-11 13:34:40 +00005202** Interpret zArg as either an integer or a boolean value. Return 1 or 0
5203** for TRUE and FALSE. Return the integer value if appropriate.
5204*/
5205static int booleanValue(const char *zArg){
5206 int i;
5207 if( zArg[0]=='0' && zArg[1]=='x' ){
5208 for(i=2; hexDigitValue(zArg[i])>=0; i++){}
5209 }else{
5210 for(i=0; zArg[i]>='0' && zArg[i]<='9'; i++){}
5211 }
5212 if( i>0 && zArg[i]==0 ) return (int)(integerValue(zArg) & 0xffffffff);
5213 if( sqlite3_stricmp(zArg, "on")==0 || sqlite3_stricmp(zArg,"yes")==0 ){
5214 return 1;
5215 }
5216 if( sqlite3_stricmp(zArg, "off")==0 || sqlite3_stricmp(zArg,"no")==0 ){
5217 return 0;
5218 }
5219 utf8_printf(stderr, "ERROR: Not a boolean value: \"%s\". Assuming \"no\".\n",
5220 zArg);
5221 return 0;
5222}
5223
5224/*
5225** Set or clear a shell flag according to a boolean value.
5226*/
5227static void setOrClearFlag(ShellState *p, unsigned mFlag, const char *zArg){
5228 if( booleanValue(zArg) ){
5229 ShellSetFlag(p, mFlag);
5230 }else{
5231 ShellClearFlag(p, mFlag);
5232 }
5233}
5234
5235/*
5236** Close an output file, assuming it is not stderr or stdout
5237*/
5238static void output_file_close(FILE *f){
5239 if( f && f!=stdout && f!=stderr ) fclose(f);
5240}
5241
5242/*
5243** Try to open an output file. The names "stdout" and "stderr" are
5244** recognized and do the right thing. NULL is returned if the output
5245** filename is "off".
5246*/
drha92a01a2018-01-10 22:15:37 +00005247static FILE *output_file_open(const char *zFile, int bTextMode){
drh2ce15c32017-07-11 13:34:40 +00005248 FILE *f;
5249 if( strcmp(zFile,"stdout")==0 ){
5250 f = stdout;
5251 }else if( strcmp(zFile, "stderr")==0 ){
5252 f = stderr;
5253 }else if( strcmp(zFile, "off")==0 ){
5254 f = 0;
5255 }else{
drha92a01a2018-01-10 22:15:37 +00005256 f = fopen(zFile, bTextMode ? "w" : "wb");
drh2ce15c32017-07-11 13:34:40 +00005257 if( f==0 ){
5258 utf8_printf(stderr, "Error: cannot open \"%s\"\n", zFile);
5259 }
5260 }
5261 return f;
5262}
5263
drh707821f2018-12-05 13:39:06 +00005264#ifndef SQLITE_OMIT_TRACE
drh2ce15c32017-07-11 13:34:40 +00005265/*
5266** A routine for handling output from sqlite3_trace().
5267*/
5268static int sql_trace_callback(
drh707821f2018-12-05 13:39:06 +00005269 unsigned mType, /* The trace type */
5270 void *pArg, /* The ShellState pointer */
5271 void *pP, /* Usually a pointer to sqlite_stmt */
5272 void *pX /* Auxiliary output */
drh2ce15c32017-07-11 13:34:40 +00005273){
drh707821f2018-12-05 13:39:06 +00005274 ShellState *p = (ShellState*)pArg;
5275 sqlite3_stmt *pStmt;
5276 const char *zSql;
5277 int nSql;
5278 if( p->traceOut==0 ) return 0;
5279 if( mType==SQLITE_TRACE_CLOSE ){
5280 utf8_printf(p->traceOut, "-- closing database connection\n");
5281 return 0;
5282 }
5283 if( mType!=SQLITE_TRACE_ROW && ((const char*)pX)[0]=='-' ){
5284 zSql = (const char*)pX;
5285 }else{
5286 pStmt = (sqlite3_stmt*)pP;
5287 switch( p->eTraceType ){
5288 case SHELL_TRACE_EXPANDED: {
5289 zSql = sqlite3_expanded_sql(pStmt);
5290 break;
5291 }
5292#ifdef SQLITE_ENABLE_NORMALIZE
5293 case SHELL_TRACE_NORMALIZED: {
5294 zSql = sqlite3_normalized_sql(pStmt);
5295 break;
5296 }
5297#endif
5298 default: {
5299 zSql = sqlite3_sql(pStmt);
5300 break;
5301 }
5302 }
5303 }
5304 if( zSql==0 ) return 0;
5305 nSql = strlen30(zSql);
5306 while( nSql>0 && zSql[nSql-1]==';' ){ nSql--; }
5307 switch( mType ){
5308 case SQLITE_TRACE_ROW:
5309 case SQLITE_TRACE_STMT: {
5310 utf8_printf(p->traceOut, "%.*s;\n", nSql, zSql);
5311 break;
5312 }
5313 case SQLITE_TRACE_PROFILE: {
5314 sqlite3_int64 nNanosec = *(sqlite3_int64*)pX;
5315 utf8_printf(p->traceOut, "%.*s; -- %lld ns\n", nSql, zSql, nNanosec);
5316 break;
5317 }
drh2ce15c32017-07-11 13:34:40 +00005318 }
5319 return 0;
5320}
5321#endif
drh2ce15c32017-07-11 13:34:40 +00005322
5323/*
5324** A no-op routine that runs with the ".breakpoint" doc-command. This is
5325** a useful spot to set a debugger breakpoint.
5326*/
5327static void test_breakpoint(void){
5328 static int nCall = 0;
5329 nCall++;
5330}
5331
5332/*
5333** An object used to read a CSV and other files for import.
5334*/
5335typedef struct ImportCtx ImportCtx;
5336struct ImportCtx {
5337 const char *zFile; /* Name of the input file */
5338 FILE *in; /* Read the CSV text from this input stream */
drh97767842020-05-29 19:39:35 +00005339 int (SQLITE_CDECL *xCloser)(FILE*); /* Func to close in */
drh2ce15c32017-07-11 13:34:40 +00005340 char *z; /* Accumulated text for a field */
5341 int n; /* Number of bytes in z */
5342 int nAlloc; /* Space allocated for z[] */
5343 int nLine; /* Current line number */
drhccb37812020-03-09 15:39:39 +00005344 int nRow; /* Number of rows imported */
5345 int nErr; /* Number of errors encountered */
drh2ce15c32017-07-11 13:34:40 +00005346 int bNotFirst; /* True if one or more bytes already read */
5347 int cTerm; /* Character that terminated the most recent field */
5348 int cColSep; /* The column separator character. (Usually ",") */
5349 int cRowSep; /* The row separator character. (Usually "\n") */
5350};
5351
drh97767842020-05-29 19:39:35 +00005352/* Clean up resourced used by an ImportCtx */
5353static void import_cleanup(ImportCtx *p){
drh42c2a042020-05-29 20:16:19 +00005354 if( p->in!=0 && p->xCloser!=0 ){
drh97767842020-05-29 19:39:35 +00005355 p->xCloser(p->in);
5356 p->in = 0;
5357 }
5358 sqlite3_free(p->z);
5359 p->z = 0;
5360}
5361
drh2ce15c32017-07-11 13:34:40 +00005362/* Append a single byte to z[] */
5363static void import_append_char(ImportCtx *p, int c){
5364 if( p->n+1>=p->nAlloc ){
5365 p->nAlloc += p->nAlloc + 100;
5366 p->z = sqlite3_realloc64(p->z, p->nAlloc);
drhe3e25652021-12-16 13:29:28 +00005367 shell_check_oom(p->z);
drh2ce15c32017-07-11 13:34:40 +00005368 }
5369 p->z[p->n++] = (char)c;
5370}
5371
5372/* Read a single field of CSV text. Compatible with rfc4180 and extended
5373** with the option of having a separator other than ",".
5374**
5375** + Input comes from p->in.
5376** + Store results in p->z of length p->n. Space to hold p->z comes
5377** from sqlite3_malloc64().
5378** + Use p->cSep as the column separator. The default is ",".
5379** + Use p->rSep as the row separator. The default is "\n".
5380** + Keep track of the line number in p->nLine.
5381** + Store the character that terminates the field in p->cTerm. Store
5382** EOF on end-of-file.
5383** + Report syntax errors on stderr
5384*/
5385static char *SQLITE_CDECL csv_read_one_field(ImportCtx *p){
5386 int c;
5387 int cSep = p->cColSep;
5388 int rSep = p->cRowSep;
5389 p->n = 0;
5390 c = fgetc(p->in);
5391 if( c==EOF || seenInterrupt ){
5392 p->cTerm = EOF;
5393 return 0;
5394 }
5395 if( c=='"' ){
5396 int pc, ppc;
5397 int startLine = p->nLine;
5398 int cQuote = c;
5399 pc = ppc = 0;
5400 while( 1 ){
5401 c = fgetc(p->in);
5402 if( c==rSep ) p->nLine++;
5403 if( c==cQuote ){
5404 if( pc==cQuote ){
5405 pc = 0;
5406 continue;
5407 }
5408 }
5409 if( (c==cSep && pc==cQuote)
5410 || (c==rSep && pc==cQuote)
5411 || (c==rSep && pc=='\r' && ppc==cQuote)
5412 || (c==EOF && pc==cQuote)
5413 ){
5414 do{ p->n--; }while( p->z[p->n]!=cQuote );
5415 p->cTerm = c;
5416 break;
5417 }
5418 if( pc==cQuote && c!='\r' ){
5419 utf8_printf(stderr, "%s:%d: unescaped %c character\n",
5420 p->zFile, p->nLine, cQuote);
5421 }
5422 if( c==EOF ){
5423 utf8_printf(stderr, "%s:%d: unterminated %c-quoted field\n",
5424 p->zFile, startLine, cQuote);
5425 p->cTerm = c;
5426 break;
5427 }
5428 import_append_char(p, c);
5429 ppc = pc;
5430 pc = c;
5431 }
5432 }else{
5433 /* If this is the first field being parsed and it begins with the
5434 ** UTF-8 BOM (0xEF BB BF) then skip the BOM */
5435 if( (c&0xff)==0xef && p->bNotFirst==0 ){
5436 import_append_char(p, c);
5437 c = fgetc(p->in);
5438 if( (c&0xff)==0xbb ){
5439 import_append_char(p, c);
5440 c = fgetc(p->in);
5441 if( (c&0xff)==0xbf ){
5442 p->bNotFirst = 1;
5443 p->n = 0;
5444 return csv_read_one_field(p);
5445 }
5446 }
5447 }
5448 while( c!=EOF && c!=cSep && c!=rSep ){
5449 import_append_char(p, c);
5450 c = fgetc(p->in);
5451 }
5452 if( c==rSep ){
5453 p->nLine++;
5454 if( p->n>0 && p->z[p->n-1]=='\r' ) p->n--;
5455 }
5456 p->cTerm = c;
5457 }
5458 if( p->z ) p->z[p->n] = 0;
5459 p->bNotFirst = 1;
5460 return p->z;
5461}
5462
5463/* Read a single field of ASCII delimited text.
5464**
5465** + Input comes from p->in.
5466** + Store results in p->z of length p->n. Space to hold p->z comes
5467** from sqlite3_malloc64().
5468** + Use p->cSep as the column separator. The default is "\x1F".
5469** + Use p->rSep as the row separator. The default is "\x1E".
5470** + Keep track of the row number in p->nLine.
5471** + Store the character that terminates the field in p->cTerm. Store
5472** EOF on end-of-file.
5473** + Report syntax errors on stderr
5474*/
5475static char *SQLITE_CDECL ascii_read_one_field(ImportCtx *p){
5476 int c;
5477 int cSep = p->cColSep;
5478 int rSep = p->cRowSep;
5479 p->n = 0;
5480 c = fgetc(p->in);
5481 if( c==EOF || seenInterrupt ){
5482 p->cTerm = EOF;
5483 return 0;
5484 }
5485 while( c!=EOF && c!=cSep && c!=rSep ){
5486 import_append_char(p, c);
5487 c = fgetc(p->in);
5488 }
5489 if( c==rSep ){
5490 p->nLine++;
5491 }
5492 p->cTerm = c;
5493 if( p->z ) p->z[p->n] = 0;
5494 return p->z;
5495}
5496
5497/*
5498** Try to transfer data for table zTable. If an error is seen while
5499** moving forward, try to go backwards. The backwards movement won't
5500** work for WITHOUT ROWID tables.
5501*/
5502static void tryToCloneData(
5503 ShellState *p,
5504 sqlite3 *newDb,
5505 const char *zTable
5506){
5507 sqlite3_stmt *pQuery = 0;
5508 sqlite3_stmt *pInsert = 0;
5509 char *zQuery = 0;
5510 char *zInsert = 0;
5511 int rc;
5512 int i, j, n;
drhaf2770f2018-01-05 14:55:43 +00005513 int nTable = strlen30(zTable);
drh2ce15c32017-07-11 13:34:40 +00005514 int k = 0;
5515 int cnt = 0;
5516 const int spinRate = 10000;
5517
5518 zQuery = sqlite3_mprintf("SELECT * FROM \"%w\"", zTable);
drhe3e25652021-12-16 13:29:28 +00005519 shell_check_oom(zQuery);
drh2ce15c32017-07-11 13:34:40 +00005520 rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
5521 if( rc ){
5522 utf8_printf(stderr, "Error %d: %s on [%s]\n",
5523 sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db),
5524 zQuery);
5525 goto end_data_xfer;
5526 }
5527 n = sqlite3_column_count(pQuery);
5528 zInsert = sqlite3_malloc64(200 + nTable + n*3);
drhe3e25652021-12-16 13:29:28 +00005529 shell_check_oom(zInsert);
drh2ce15c32017-07-11 13:34:40 +00005530 sqlite3_snprintf(200+nTable,zInsert,
5531 "INSERT OR IGNORE INTO \"%s\" VALUES(?", zTable);
drhaf2770f2018-01-05 14:55:43 +00005532 i = strlen30(zInsert);
drh2ce15c32017-07-11 13:34:40 +00005533 for(j=1; j<n; j++){
5534 memcpy(zInsert+i, ",?", 2);
5535 i += 2;
5536 }
5537 memcpy(zInsert+i, ");", 3);
5538 rc = sqlite3_prepare_v2(newDb, zInsert, -1, &pInsert, 0);
5539 if( rc ){
5540 utf8_printf(stderr, "Error %d: %s on [%s]\n",
5541 sqlite3_extended_errcode(newDb), sqlite3_errmsg(newDb),
5542 zQuery);
5543 goto end_data_xfer;
5544 }
5545 for(k=0; k<2; k++){
5546 while( (rc = sqlite3_step(pQuery))==SQLITE_ROW ){
5547 for(i=0; i<n; i++){
5548 switch( sqlite3_column_type(pQuery, i) ){
5549 case SQLITE_NULL: {
5550 sqlite3_bind_null(pInsert, i+1);
5551 break;
5552 }
5553 case SQLITE_INTEGER: {
5554 sqlite3_bind_int64(pInsert, i+1, sqlite3_column_int64(pQuery,i));
5555 break;
5556 }
5557 case SQLITE_FLOAT: {
5558 sqlite3_bind_double(pInsert, i+1, sqlite3_column_double(pQuery,i));
5559 break;
5560 }
5561 case SQLITE_TEXT: {
5562 sqlite3_bind_text(pInsert, i+1,
5563 (const char*)sqlite3_column_text(pQuery,i),
5564 -1, SQLITE_STATIC);
5565 break;
5566 }
5567 case SQLITE_BLOB: {
5568 sqlite3_bind_blob(pInsert, i+1, sqlite3_column_blob(pQuery,i),
5569 sqlite3_column_bytes(pQuery,i),
5570 SQLITE_STATIC);
5571 break;
5572 }
5573 }
5574 } /* End for */
5575 rc = sqlite3_step(pInsert);
5576 if( rc!=SQLITE_OK && rc!=SQLITE_ROW && rc!=SQLITE_DONE ){
5577 utf8_printf(stderr, "Error %d: %s\n", sqlite3_extended_errcode(newDb),
5578 sqlite3_errmsg(newDb));
5579 }
5580 sqlite3_reset(pInsert);
5581 cnt++;
5582 if( (cnt%spinRate)==0 ){
5583 printf("%c\b", "|/-\\"[(cnt/spinRate)%4]);
5584 fflush(stdout);
5585 }
5586 } /* End while */
5587 if( rc==SQLITE_DONE ) break;
5588 sqlite3_finalize(pQuery);
5589 sqlite3_free(zQuery);
5590 zQuery = sqlite3_mprintf("SELECT * FROM \"%w\" ORDER BY rowid DESC;",
5591 zTable);
drhe3e25652021-12-16 13:29:28 +00005592 shell_check_oom(zQuery);
drh2ce15c32017-07-11 13:34:40 +00005593 rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
5594 if( rc ){
5595 utf8_printf(stderr, "Warning: cannot step \"%s\" backwards", zTable);
5596 break;
5597 }
5598 } /* End for(k=0...) */
5599
5600end_data_xfer:
5601 sqlite3_finalize(pQuery);
5602 sqlite3_finalize(pInsert);
5603 sqlite3_free(zQuery);
5604 sqlite3_free(zInsert);
5605}
5606
5607
5608/*
5609** Try to transfer all rows of the schema that match zWhere. For
5610** each row, invoke xForEach() on the object defined by that row.
5611** If an error is encountered while moving forward through the
drh067b92b2020-06-19 15:24:12 +00005612** sqlite_schema table, try again moving backwards.
drh2ce15c32017-07-11 13:34:40 +00005613*/
5614static void tryToCloneSchema(
5615 ShellState *p,
5616 sqlite3 *newDb,
5617 const char *zWhere,
5618 void (*xForEach)(ShellState*,sqlite3*,const char*)
5619){
5620 sqlite3_stmt *pQuery = 0;
5621 char *zQuery = 0;
5622 int rc;
5623 const unsigned char *zName;
5624 const unsigned char *zSql;
5625 char *zErrMsg = 0;
5626
drh067b92b2020-06-19 15:24:12 +00005627 zQuery = sqlite3_mprintf("SELECT name, sql FROM sqlite_schema"
drh2ce15c32017-07-11 13:34:40 +00005628 " WHERE %s", zWhere);
drhe3e25652021-12-16 13:29:28 +00005629 shell_check_oom(zQuery);
drh2ce15c32017-07-11 13:34:40 +00005630 rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
5631 if( rc ){
5632 utf8_printf(stderr, "Error: (%d) %s on [%s]\n",
5633 sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db),
5634 zQuery);
5635 goto end_schema_xfer;
5636 }
5637 while( (rc = sqlite3_step(pQuery))==SQLITE_ROW ){
5638 zName = sqlite3_column_text(pQuery, 0);
5639 zSql = sqlite3_column_text(pQuery, 1);
drh621a5e02021-12-16 17:35:27 +00005640 if( zName==0 || zSql==0 ) continue;
drh2ce15c32017-07-11 13:34:40 +00005641 printf("%s... ", zName); fflush(stdout);
5642 sqlite3_exec(newDb, (const char*)zSql, 0, 0, &zErrMsg);
5643 if( zErrMsg ){
5644 utf8_printf(stderr, "Error: %s\nSQL: [%s]\n", zErrMsg, zSql);
5645 sqlite3_free(zErrMsg);
5646 zErrMsg = 0;
5647 }
5648 if( xForEach ){
5649 xForEach(p, newDb, (const char*)zName);
5650 }
5651 printf("done\n");
5652 }
5653 if( rc!=SQLITE_DONE ){
5654 sqlite3_finalize(pQuery);
5655 sqlite3_free(zQuery);
drh067b92b2020-06-19 15:24:12 +00005656 zQuery = sqlite3_mprintf("SELECT name, sql FROM sqlite_schema"
drh2ce15c32017-07-11 13:34:40 +00005657 " WHERE %s ORDER BY rowid DESC", zWhere);
drhe3e25652021-12-16 13:29:28 +00005658 shell_check_oom(zQuery);
drh2ce15c32017-07-11 13:34:40 +00005659 rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
5660 if( rc ){
5661 utf8_printf(stderr, "Error: (%d) %s on [%s]\n",
5662 sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db),
5663 zQuery);
5664 goto end_schema_xfer;
5665 }
drh76fc88f2021-10-02 16:39:16 +00005666 while( sqlite3_step(pQuery)==SQLITE_ROW ){
drh2ce15c32017-07-11 13:34:40 +00005667 zName = sqlite3_column_text(pQuery, 0);
5668 zSql = sqlite3_column_text(pQuery, 1);
drh621a5e02021-12-16 17:35:27 +00005669 if( zName==0 || zSql==0 ) continue;
drh2ce15c32017-07-11 13:34:40 +00005670 printf("%s... ", zName); fflush(stdout);
5671 sqlite3_exec(newDb, (const char*)zSql, 0, 0, &zErrMsg);
5672 if( zErrMsg ){
5673 utf8_printf(stderr, "Error: %s\nSQL: [%s]\n", zErrMsg, zSql);
5674 sqlite3_free(zErrMsg);
5675 zErrMsg = 0;
5676 }
5677 if( xForEach ){
5678 xForEach(p, newDb, (const char*)zName);
5679 }
5680 printf("done\n");
5681 }
5682 }
5683end_schema_xfer:
5684 sqlite3_finalize(pQuery);
5685 sqlite3_free(zQuery);
5686}
5687
5688/*
5689** Open a new database file named "zNewDb". Try to recover as much information
5690** as possible out of the main database (which might be corrupt) and write it
5691** into zNewDb.
5692*/
5693static void tryToClone(ShellState *p, const char *zNewDb){
5694 int rc;
5695 sqlite3 *newDb = 0;
5696 if( access(zNewDb,0)==0 ){
5697 utf8_printf(stderr, "File \"%s\" already exists.\n", zNewDb);
5698 return;
5699 }
5700 rc = sqlite3_open(zNewDb, &newDb);
5701 if( rc ){
5702 utf8_printf(stderr, "Cannot create output database: %s\n",
5703 sqlite3_errmsg(newDb));
5704 }else{
5705 sqlite3_exec(p->db, "PRAGMA writable_schema=ON;", 0, 0, 0);
5706 sqlite3_exec(newDb, "BEGIN EXCLUSIVE;", 0, 0, 0);
5707 tryToCloneSchema(p, newDb, "type='table'", tryToCloneData);
5708 tryToCloneSchema(p, newDb, "type!='table'", 0);
5709 sqlite3_exec(newDb, "COMMIT;", 0, 0, 0);
5710 sqlite3_exec(p->db, "PRAGMA writable_schema=OFF;", 0, 0, 0);
5711 }
drh9e804032018-05-18 17:11:50 +00005712 close_db(newDb);
drh2ce15c32017-07-11 13:34:40 +00005713}
5714
5715/*
drh13c20932018-01-10 21:41:55 +00005716** Change the output file back to stdout.
5717**
5718** If the p->doXdgOpen flag is set, that means the output was being
5719** redirected to a temporary file named by p->zTempFile. In that case,
5720** launch start/open/xdg-open on that temporary file.
drh2ce15c32017-07-11 13:34:40 +00005721*/
5722static void output_reset(ShellState *p){
5723 if( p->outfile[0]=='|' ){
5724#ifndef SQLITE_OMIT_POPEN
5725 pclose(p->out);
5726#endif
5727 }else{
5728 output_file_close(p->out);
drh04a28c32018-01-31 01:38:44 +00005729#ifndef SQLITE_NOHAVE_SYSTEM
drh13c20932018-01-10 21:41:55 +00005730 if( p->doXdgOpen ){
5731 const char *zXdgOpenCmd =
5732#if defined(_WIN32)
5733 "start";
5734#elif defined(__APPLE__)
5735 "open";
5736#else
5737 "xdg-open";
5738#endif
5739 char *zCmd;
5740 zCmd = sqlite3_mprintf("%s %s", zXdgOpenCmd, p->zTempFile);
drha92a01a2018-01-10 22:15:37 +00005741 if( system(zCmd) ){
5742 utf8_printf(stderr, "Failed: [%s]\n", zCmd);
drh1d9ea272020-04-17 23:46:54 +00005743 }else{
5744 /* Give the start/open/xdg-open command some time to get
5745 ** going before we continue, and potential delete the
5746 ** p->zTempFile data file out from under it */
5747 sqlite3_sleep(2000);
drha92a01a2018-01-10 22:15:37 +00005748 }
drh13c20932018-01-10 21:41:55 +00005749 sqlite3_free(zCmd);
drh3c484e82018-01-10 22:27:21 +00005750 outputModePop(p);
drh13c20932018-01-10 21:41:55 +00005751 p->doXdgOpen = 0;
5752 }
drh04a28c32018-01-31 01:38:44 +00005753#endif /* !defined(SQLITE_NOHAVE_SYSTEM) */
drh2ce15c32017-07-11 13:34:40 +00005754 }
5755 p->outfile[0] = 0;
5756 p->out = stdout;
5757}
5758
5759/*
5760** Run an SQL command and return the single integer result.
5761*/
larrybr58a53d62022-02-10 03:21:48 +00005762static int db_int(sqlite3 *db, const char *zSql){
drh2ce15c32017-07-11 13:34:40 +00005763 sqlite3_stmt *pStmt;
5764 int res = 0;
larrybr58a53d62022-02-10 03:21:48 +00005765 sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
drh2ce15c32017-07-11 13:34:40 +00005766 if( pStmt && sqlite3_step(pStmt)==SQLITE_ROW ){
5767 res = sqlite3_column_int(pStmt,0);
5768 }
5769 sqlite3_finalize(pStmt);
5770 return res;
5771}
5772
5773/*
5774** Convert a 2-byte or 4-byte big-endian integer into a native integer
5775*/
5776static unsigned int get2byteInt(unsigned char *a){
5777 return (a[0]<<8) + a[1];
5778}
5779static unsigned int get4byteInt(unsigned char *a){
5780 return (a[0]<<24) + (a[1]<<16) + (a[2]<<8) + a[3];
5781}
5782
5783/*
drh76c12062020-01-14 13:13:19 +00005784** Implementation of the ".dbinfo" command.
drh2ce15c32017-07-11 13:34:40 +00005785**
5786** Return 1 on error, 2 to exit, and 0 otherwise.
5787*/
5788static int shell_dbinfo_command(ShellState *p, int nArg, char **azArg){
5789 static const struct { const char *zName; int ofst; } aField[] = {
5790 { "file change counter:", 24 },
5791 { "database page count:", 28 },
5792 { "freelist page count:", 36 },
5793 { "schema cookie:", 40 },
5794 { "schema format:", 44 },
5795 { "default cache size:", 48 },
5796 { "autovacuum top root:", 52 },
5797 { "incremental vacuum:", 64 },
5798 { "text encoding:", 56 },
5799 { "user version:", 60 },
5800 { "application id:", 68 },
5801 { "software version:", 96 },
5802 };
5803 static const struct { const char *zName; const char *zSql; } aQuery[] = {
5804 { "number of tables:",
5805 "SELECT count(*) FROM %s WHERE type='table'" },
5806 { "number of indexes:",
5807 "SELECT count(*) FROM %s WHERE type='index'" },
5808 { "number of triggers:",
5809 "SELECT count(*) FROM %s WHERE type='trigger'" },
5810 { "number of views:",
5811 "SELECT count(*) FROM %s WHERE type='view'" },
5812 { "schema size:",
5813 "SELECT total(length(sql)) FROM %s" },
5814 };
drh87c889c2019-03-20 18:22:51 +00005815 int i, rc;
drhea99a312018-07-18 19:09:07 +00005816 unsigned iDataVersion;
drh2ce15c32017-07-11 13:34:40 +00005817 char *zSchemaTab;
5818 char *zDb = nArg>=2 ? azArg[1] : "main";
drh512e6c32017-10-11 17:51:08 +00005819 sqlite3_stmt *pStmt = 0;
drh2ce15c32017-07-11 13:34:40 +00005820 unsigned char aHdr[100];
5821 open_db(p, 0);
5822 if( p->db==0 ) return 1;
drh87c889c2019-03-20 18:22:51 +00005823 rc = sqlite3_prepare_v2(p->db,
5824 "SELECT data FROM sqlite_dbpage(?1) WHERE pgno=1",
5825 -1, &pStmt, 0);
5826 if( rc ){
drh451f89a2020-04-28 23:09:56 +00005827 utf8_printf(stderr, "error: %s\n", sqlite3_errmsg(p->db));
drh87c889c2019-03-20 18:22:51 +00005828 sqlite3_finalize(pStmt);
5829 return 1;
5830 }
drh512e6c32017-10-11 17:51:08 +00005831 sqlite3_bind_text(pStmt, 1, zDb, -1, SQLITE_STATIC);
5832 if( sqlite3_step(pStmt)==SQLITE_ROW
5833 && sqlite3_column_bytes(pStmt,0)>100
5834 ){
5835 memcpy(aHdr, sqlite3_column_blob(pStmt,0), 100);
5836 sqlite3_finalize(pStmt);
5837 }else{
drh2ce15c32017-07-11 13:34:40 +00005838 raw_printf(stderr, "unable to read database header\n");
drh512e6c32017-10-11 17:51:08 +00005839 sqlite3_finalize(pStmt);
drh2ce15c32017-07-11 13:34:40 +00005840 return 1;
5841 }
5842 i = get2byteInt(aHdr+16);
5843 if( i==1 ) i = 65536;
5844 utf8_printf(p->out, "%-20s %d\n", "database page size:", i);
5845 utf8_printf(p->out, "%-20s %d\n", "write format:", aHdr[18]);
5846 utf8_printf(p->out, "%-20s %d\n", "read format:", aHdr[19]);
5847 utf8_printf(p->out, "%-20s %d\n", "reserved bytes:", aHdr[20]);
5848 for(i=0; i<ArraySize(aField); i++){
5849 int ofst = aField[i].ofst;
5850 unsigned int val = get4byteInt(aHdr + ofst);
5851 utf8_printf(p->out, "%-20s %u", aField[i].zName, val);
5852 switch( ofst ){
5853 case 56: {
5854 if( val==1 ) raw_printf(p->out, " (utf8)");
5855 if( val==2 ) raw_printf(p->out, " (utf16le)");
5856 if( val==3 ) raw_printf(p->out, " (utf16be)");
5857 }
5858 }
5859 raw_printf(p->out, "\n");
5860 }
5861 if( zDb==0 ){
drh067b92b2020-06-19 15:24:12 +00005862 zSchemaTab = sqlite3_mprintf("main.sqlite_schema");
drh2ce15c32017-07-11 13:34:40 +00005863 }else if( strcmp(zDb,"temp")==0 ){
drh067b92b2020-06-19 15:24:12 +00005864 zSchemaTab = sqlite3_mprintf("%s", "sqlite_temp_schema");
drh2ce15c32017-07-11 13:34:40 +00005865 }else{
drh067b92b2020-06-19 15:24:12 +00005866 zSchemaTab = sqlite3_mprintf("\"%w\".sqlite_schema", zDb);
drh2ce15c32017-07-11 13:34:40 +00005867 }
5868 for(i=0; i<ArraySize(aQuery); i++){
5869 char *zSql = sqlite3_mprintf(aQuery[i].zSql, zSchemaTab);
larrybr58a53d62022-02-10 03:21:48 +00005870 int val = db_int(p->db, zSql);
drh2ce15c32017-07-11 13:34:40 +00005871 sqlite3_free(zSql);
5872 utf8_printf(p->out, "%-20s %d\n", aQuery[i].zName, val);
5873 }
5874 sqlite3_free(zSchemaTab);
drhea99a312018-07-18 19:09:07 +00005875 sqlite3_file_control(p->db, zDb, SQLITE_FCNTL_DATA_VERSION, &iDataVersion);
5876 utf8_printf(p->out, "%-20s %u\n", "data version", iDataVersion);
drh2ce15c32017-07-11 13:34:40 +00005877 return 0;
5878}
5879
5880/*
5881** Print the current sqlite3_errmsg() value to stderr and return 1.
5882*/
5883static int shellDatabaseError(sqlite3 *db){
5884 const char *zErr = sqlite3_errmsg(db);
5885 utf8_printf(stderr, "Error: %s\n", zErr);
5886 return 1;
5887}
5888
5889/*
drh2ce15c32017-07-11 13:34:40 +00005890** Compare the pattern in zGlob[] against the text in z[]. Return TRUE
5891** if they match and FALSE (0) if they do not match.
5892**
5893** Globbing rules:
5894**
5895** '*' Matches any sequence of zero or more characters.
5896**
5897** '?' Matches exactly one character.
5898**
5899** [...] Matches one character from the enclosed list of
5900** characters.
5901**
5902** [^...] Matches one character not in the enclosed list.
5903**
5904** '#' Matches any sequence of one or more digits with an
5905** optional + or - sign in front
5906**
5907** ' ' Any span of whitespace matches any other span of
5908** whitespace.
5909**
5910** Extra whitespace at the end of z[] is ignored.
5911*/
5912static int testcase_glob(const char *zGlob, const char *z){
5913 int c, c2;
5914 int invert;
5915 int seen;
5916
5917 while( (c = (*(zGlob++)))!=0 ){
5918 if( IsSpace(c) ){
5919 if( !IsSpace(*z) ) return 0;
5920 while( IsSpace(*zGlob) ) zGlob++;
5921 while( IsSpace(*z) ) z++;
5922 }else if( c=='*' ){
5923 while( (c=(*(zGlob++))) == '*' || c=='?' ){
5924 if( c=='?' && (*(z++))==0 ) return 0;
5925 }
5926 if( c==0 ){
5927 return 1;
5928 }else if( c=='[' ){
5929 while( *z && testcase_glob(zGlob-1,z)==0 ){
5930 z++;
5931 }
5932 return (*z)!=0;
5933 }
5934 while( (c2 = (*(z++)))!=0 ){
5935 while( c2!=c ){
5936 c2 = *(z++);
5937 if( c2==0 ) return 0;
5938 }
5939 if( testcase_glob(zGlob,z) ) return 1;
5940 }
5941 return 0;
5942 }else if( c=='?' ){
5943 if( (*(z++))==0 ) return 0;
5944 }else if( c=='[' ){
5945 int prior_c = 0;
5946 seen = 0;
5947 invert = 0;
5948 c = *(z++);
5949 if( c==0 ) return 0;
5950 c2 = *(zGlob++);
5951 if( c2=='^' ){
5952 invert = 1;
5953 c2 = *(zGlob++);
5954 }
5955 if( c2==']' ){
5956 if( c==']' ) seen = 1;
5957 c2 = *(zGlob++);
5958 }
5959 while( c2 && c2!=']' ){
5960 if( c2=='-' && zGlob[0]!=']' && zGlob[0]!=0 && prior_c>0 ){
5961 c2 = *(zGlob++);
5962 if( c>=prior_c && c<=c2 ) seen = 1;
5963 prior_c = 0;
5964 }else{
5965 if( c==c2 ){
5966 seen = 1;
5967 }
5968 prior_c = c2;
5969 }
5970 c2 = *(zGlob++);
5971 }
5972 if( c2==0 || (seen ^ invert)==0 ) return 0;
5973 }else if( c=='#' ){
5974 if( (z[0]=='-' || z[0]=='+') && IsDigit(z[1]) ) z++;
5975 if( !IsDigit(z[0]) ) return 0;
5976 z++;
5977 while( IsDigit(z[0]) ){ z++; }
5978 }else{
5979 if( c!=(*(z++)) ) return 0;
5980 }
5981 }
5982 while( IsSpace(*z) ){ z++; }
5983 return *z==0;
5984}
5985
5986
5987/*
5988** Compare the string as a command-line option with either one or two
5989** initial "-" characters.
5990*/
5991static int optionMatch(const char *zStr, const char *zOpt){
5992 if( zStr[0]!='-' ) return 0;
5993 zStr++;
5994 if( zStr[0]=='-' ) zStr++;
5995 return strcmp(zStr, zOpt)==0;
5996}
5997
5998/*
5999** Delete a file.
6000*/
6001int shellDeleteFile(const char *zFilename){
6002 int rc;
6003#ifdef _WIN32
6004 wchar_t *z = sqlite3_win32_utf8_to_unicode(zFilename);
6005 rc = _wunlink(z);
6006 sqlite3_free(z);
6007#else
6008 rc = unlink(zFilename);
6009#endif
6010 return rc;
6011}
6012
drh13c20932018-01-10 21:41:55 +00006013/*
6014** Try to delete the temporary file (if there is one) and free the
6015** memory used to hold the name of the temp file.
6016*/
6017static void clearTempFile(ShellState *p){
6018 if( p->zTempFile==0 ) return;
drh536c3452018-01-11 00:38:39 +00006019 if( p->doXdgOpen ) return;
drh13c20932018-01-10 21:41:55 +00006020 if( shellDeleteFile(p->zTempFile) ) return;
6021 sqlite3_free(p->zTempFile);
6022 p->zTempFile = 0;
6023}
6024
6025/*
6026** Create a new temp file name with the given suffix.
6027*/
6028static void newTempFile(ShellState *p, const char *zSuffix){
6029 clearTempFile(p);
6030 sqlite3_free(p->zTempFile);
6031 p->zTempFile = 0;
drh7f3bf8a2018-01-10 21:50:08 +00006032 if( p->db ){
6033 sqlite3_file_control(p->db, 0, SQLITE_FCNTL_TEMPFILENAME, &p->zTempFile);
6034 }
drh13c20932018-01-10 21:41:55 +00006035 if( p->zTempFile==0 ){
drh1d9ea272020-04-17 23:46:54 +00006036 /* If p->db is an in-memory database then the TEMPFILENAME file-control
6037 ** will not work and we will need to fallback to guessing */
6038 char *zTemp;
drh13c20932018-01-10 21:41:55 +00006039 sqlite3_uint64 r;
6040 sqlite3_randomness(sizeof(r), &r);
drh1d9ea272020-04-17 23:46:54 +00006041 zTemp = getenv("TEMP");
6042 if( zTemp==0 ) zTemp = getenv("TMP");
6043 if( zTemp==0 ){
6044#ifdef _WIN32
6045 zTemp = "\\tmp";
6046#else
6047 zTemp = "/tmp";
6048#endif
6049 }
6050 p->zTempFile = sqlite3_mprintf("%s/temp%llx.%s", zTemp, r, zSuffix);
drh13c20932018-01-10 21:41:55 +00006051 }else{
6052 p->zTempFile = sqlite3_mprintf("%z.%s", p->zTempFile, zSuffix);
6053 }
drhe3e25652021-12-16 13:29:28 +00006054 shell_check_oom(p->zTempFile);
drh13c20932018-01-10 21:41:55 +00006055}
6056
drh2ce15c32017-07-11 13:34:40 +00006057
6058/*
6059** The implementation of SQL scalar function fkey_collate_clause(), used
6060** by the ".lint fkey-indexes" command. This scalar function is always
6061** called with four arguments - the parent table name, the parent column name,
6062** the child table name and the child column name.
6063**
6064** fkey_collate_clause('parent-tab', 'parent-col', 'child-tab', 'child-col')
6065**
6066** If either of the named tables or columns do not exist, this function
6067** returns an empty string. An empty string is also returned if both tables
6068** and columns exist but have the same default collation sequence. Or,
6069** if both exist but the default collation sequences are different, this
6070** function returns the string " COLLATE <parent-collation>", where
6071** <parent-collation> is the default collation sequence of the parent column.
6072*/
6073static void shellFkeyCollateClause(
6074 sqlite3_context *pCtx,
6075 int nVal,
6076 sqlite3_value **apVal
6077){
6078 sqlite3 *db = sqlite3_context_db_handle(pCtx);
6079 const char *zParent;
6080 const char *zParentCol;
6081 const char *zParentSeq;
6082 const char *zChild;
6083 const char *zChildCol;
6084 const char *zChildSeq = 0; /* Initialize to avoid false-positive warning */
6085 int rc;
6086
6087 assert( nVal==4 );
6088 zParent = (const char*)sqlite3_value_text(apVal[0]);
6089 zParentCol = (const char*)sqlite3_value_text(apVal[1]);
6090 zChild = (const char*)sqlite3_value_text(apVal[2]);
6091 zChildCol = (const char*)sqlite3_value_text(apVal[3]);
6092
6093 sqlite3_result_text(pCtx, "", -1, SQLITE_STATIC);
6094 rc = sqlite3_table_column_metadata(
6095 db, "main", zParent, zParentCol, 0, &zParentSeq, 0, 0, 0
6096 );
6097 if( rc==SQLITE_OK ){
6098 rc = sqlite3_table_column_metadata(
6099 db, "main", zChild, zChildCol, 0, &zChildSeq, 0, 0, 0
6100 );
6101 }
6102
6103 if( rc==SQLITE_OK && sqlite3_stricmp(zParentSeq, zChildSeq) ){
6104 char *z = sqlite3_mprintf(" COLLATE %s", zParentSeq);
6105 sqlite3_result_text(pCtx, z, -1, SQLITE_TRANSIENT);
6106 sqlite3_free(z);
6107 }
6108}
6109
6110
6111/*
6112** The implementation of dot-command ".lint fkey-indexes".
6113*/
6114static int lintFkeyIndexes(
6115 ShellState *pState, /* Current shell tool state */
6116 char **azArg, /* Array of arguments passed to dot command */
6117 int nArg /* Number of entries in azArg[] */
6118){
6119 sqlite3 *db = pState->db; /* Database handle to query "main" db of */
6120 FILE *out = pState->out; /* Stream to write non-error output to */
6121 int bVerbose = 0; /* If -verbose is present */
6122 int bGroupByParent = 0; /* If -groupbyparent is present */
6123 int i; /* To iterate through azArg[] */
6124 const char *zIndent = ""; /* How much to indent CREATE INDEX by */
6125 int rc; /* Return code */
6126 sqlite3_stmt *pSql = 0; /* Compiled version of SQL statement below */
6127
6128 /*
6129 ** This SELECT statement returns one row for each foreign key constraint
6130 ** in the schema of the main database. The column values are:
6131 **
6132 ** 0. The text of an SQL statement similar to:
6133 **
danf9679312017-12-01 18:40:18 +00006134 ** "EXPLAIN QUERY PLAN SELECT 1 FROM child_table WHERE child_key=?"
drh2ce15c32017-07-11 13:34:40 +00006135 **
danf9679312017-12-01 18:40:18 +00006136 ** This SELECT is similar to the one that the foreign keys implementation
6137 ** needs to run internally on child tables. If there is an index that can
drh2ce15c32017-07-11 13:34:40 +00006138 ** be used to optimize this query, then it can also be used by the FK
6139 ** implementation to optimize DELETE or UPDATE statements on the parent
6140 ** table.
6141 **
6142 ** 1. A GLOB pattern suitable for sqlite3_strglob(). If the plan output by
6143 ** the EXPLAIN QUERY PLAN command matches this pattern, then the schema
6144 ** contains an index that can be used to optimize the query.
6145 **
6146 ** 2. Human readable text that describes the child table and columns. e.g.
6147 **
6148 ** "child_table(child_key1, child_key2)"
6149 **
6150 ** 3. Human readable text that describes the parent table and columns. e.g.
6151 **
6152 ** "parent_table(parent_key1, parent_key2)"
6153 **
6154 ** 4. A full CREATE INDEX statement for an index that could be used to
6155 ** optimize DELETE or UPDATE statements on the parent table. e.g.
6156 **
6157 ** "CREATE INDEX child_table_child_key ON child_table(child_key)"
6158 **
6159 ** 5. The name of the parent table.
6160 **
6161 ** These six values are used by the C logic below to generate the report.
6162 */
6163 const char *zSql =
6164 "SELECT "
danf9679312017-12-01 18:40:18 +00006165 " 'EXPLAIN QUERY PLAN SELECT 1 FROM ' || quote(s.name) || ' WHERE '"
drh2ce15c32017-07-11 13:34:40 +00006166 " || group_concat(quote(s.name) || '.' || quote(f.[from]) || '=?' "
6167 " || fkey_collate_clause("
6168 " f.[table], COALESCE(f.[to], p.[name]), s.name, f.[from]),' AND ')"
6169 ", "
drh82102332021-03-20 15:11:29 +00006170 " 'SEARCH ' || s.name || ' USING COVERING INDEX*('"
drh2ce15c32017-07-11 13:34:40 +00006171 " || group_concat('*=?', ' AND ') || ')'"
6172 ", "
6173 " s.name || '(' || group_concat(f.[from], ', ') || ')'"
6174 ", "
6175 " f.[table] || '(' || group_concat(COALESCE(f.[to], p.[name])) || ')'"
6176 ", "
6177 " 'CREATE INDEX ' || quote(s.name ||'_'|| group_concat(f.[from], '_'))"
6178 " || ' ON ' || quote(s.name) || '('"
6179 " || group_concat(quote(f.[from]) ||"
6180 " fkey_collate_clause("
6181 " f.[table], COALESCE(f.[to], p.[name]), s.name, f.[from]), ', ')"
6182 " || ');'"
6183 ", "
6184 " f.[table] "
drh067b92b2020-06-19 15:24:12 +00006185 "FROM sqlite_schema AS s, pragma_foreign_key_list(s.name) AS f "
drh2ce15c32017-07-11 13:34:40 +00006186 "LEFT JOIN pragma_table_info AS p ON (pk-1=seq AND p.arg=f.[table]) "
6187 "GROUP BY s.name, f.id "
6188 "ORDER BY (CASE WHEN ? THEN f.[table] ELSE s.name END)"
6189 ;
drh82102332021-03-20 15:11:29 +00006190 const char *zGlobIPK = "SEARCH * USING INTEGER PRIMARY KEY (rowid=?)";
drh2ce15c32017-07-11 13:34:40 +00006191
6192 for(i=2; i<nArg; i++){
drhaf2770f2018-01-05 14:55:43 +00006193 int n = strlen30(azArg[i]);
drh2ce15c32017-07-11 13:34:40 +00006194 if( n>1 && sqlite3_strnicmp("-verbose", azArg[i], n)==0 ){
6195 bVerbose = 1;
6196 }
6197 else if( n>1 && sqlite3_strnicmp("-groupbyparent", azArg[i], n)==0 ){
6198 bGroupByParent = 1;
6199 zIndent = " ";
6200 }
6201 else{
6202 raw_printf(stderr, "Usage: %s %s ?-verbose? ?-groupbyparent?\n",
6203 azArg[0], azArg[1]
6204 );
6205 return SQLITE_ERROR;
6206 }
6207 }
6208
6209 /* Register the fkey_collate_clause() SQL function */
6210 rc = sqlite3_create_function(db, "fkey_collate_clause", 4, SQLITE_UTF8,
6211 0, shellFkeyCollateClause, 0, 0
6212 );
6213
6214
6215 if( rc==SQLITE_OK ){
6216 rc = sqlite3_prepare_v2(db, zSql, -1, &pSql, 0);
6217 }
6218 if( rc==SQLITE_OK ){
6219 sqlite3_bind_int(pSql, 1, bGroupByParent);
6220 }
6221
6222 if( rc==SQLITE_OK ){
6223 int rc2;
6224 char *zPrev = 0;
6225 while( SQLITE_ROW==sqlite3_step(pSql) ){
6226 int res = -1;
6227 sqlite3_stmt *pExplain = 0;
6228 const char *zEQP = (const char*)sqlite3_column_text(pSql, 0);
6229 const char *zGlob = (const char*)sqlite3_column_text(pSql, 1);
6230 const char *zFrom = (const char*)sqlite3_column_text(pSql, 2);
6231 const char *zTarget = (const char*)sqlite3_column_text(pSql, 3);
6232 const char *zCI = (const char*)sqlite3_column_text(pSql, 4);
6233 const char *zParent = (const char*)sqlite3_column_text(pSql, 5);
6234
drh621a5e02021-12-16 17:35:27 +00006235 if( zEQP==0 ) continue;
6236 if( zGlob==0 ) continue;
drh2ce15c32017-07-11 13:34:40 +00006237 rc = sqlite3_prepare_v2(db, zEQP, -1, &pExplain, 0);
6238 if( rc!=SQLITE_OK ) break;
6239 if( SQLITE_ROW==sqlite3_step(pExplain) ){
6240 const char *zPlan = (const char*)sqlite3_column_text(pExplain, 3);
drh621a5e02021-12-16 17:35:27 +00006241 res = zPlan!=0 && ( 0==sqlite3_strglob(zGlob, zPlan)
6242 || 0==sqlite3_strglob(zGlobIPK, zPlan));
drh2ce15c32017-07-11 13:34:40 +00006243 }
6244 rc = sqlite3_finalize(pExplain);
6245 if( rc!=SQLITE_OK ) break;
6246
6247 if( res<0 ){
6248 raw_printf(stderr, "Error: internal error");
6249 break;
6250 }else{
6251 if( bGroupByParent
6252 && (bVerbose || res==0)
6253 && (zPrev==0 || sqlite3_stricmp(zParent, zPrev))
6254 ){
6255 raw_printf(out, "-- Parent table %s\n", zParent);
6256 sqlite3_free(zPrev);
6257 zPrev = sqlite3_mprintf("%s", zParent);
6258 }
6259
6260 if( res==0 ){
6261 raw_printf(out, "%s%s --> %s\n", zIndent, zCI, zTarget);
6262 }else if( bVerbose ){
6263 raw_printf(out, "%s/* no extra indexes required for %s -> %s */\n",
6264 zIndent, zFrom, zTarget
6265 );
6266 }
6267 }
6268 }
6269 sqlite3_free(zPrev);
6270
6271 if( rc!=SQLITE_OK ){
6272 raw_printf(stderr, "%s\n", sqlite3_errmsg(db));
6273 }
6274
6275 rc2 = sqlite3_finalize(pSql);
6276 if( rc==SQLITE_OK && rc2!=SQLITE_OK ){
6277 rc = rc2;
6278 raw_printf(stderr, "%s\n", sqlite3_errmsg(db));
6279 }
6280 }else{
6281 raw_printf(stderr, "%s\n", sqlite3_errmsg(db));
6282 }
6283
6284 return rc;
6285}
6286
6287/*
6288** Implementation of ".lint" dot command.
6289*/
6290static int lintDotCommand(
6291 ShellState *pState, /* Current shell tool state */
6292 char **azArg, /* Array of arguments passed to dot command */
6293 int nArg /* Number of entries in azArg[] */
6294){
6295 int n;
drhaf2770f2018-01-05 14:55:43 +00006296 n = (nArg>=2 ? strlen30(azArg[1]) : 0);
drh2ce15c32017-07-11 13:34:40 +00006297 if( n<1 || sqlite3_strnicmp(azArg[1], "fkey-indexes", n) ) goto usage;
6298 return lintFkeyIndexes(pState, azArg, nArg);
6299
6300 usage:
6301 raw_printf(stderr, "Usage %s sub-command ?switches...?\n", azArg[0]);
6302 raw_printf(stderr, "Where sub-commands are:\n");
6303 raw_printf(stderr, " fkey-indexes\n");
6304 return SQLITE_ERROR;
6305}
6306
dan1b162162019-04-27 20:15:15 +00006307#if !defined SQLITE_OMIT_VIRTUALTABLE
danfd0245d2017-12-07 15:44:29 +00006308static void shellPrepare(
dand4b56e52017-12-12 20:04:59 +00006309 sqlite3 *db,
danfd0245d2017-12-07 15:44:29 +00006310 int *pRc,
6311 const char *zSql,
6312 sqlite3_stmt **ppStmt
6313){
6314 *ppStmt = 0;
6315 if( *pRc==SQLITE_OK ){
dand4b56e52017-12-12 20:04:59 +00006316 int rc = sqlite3_prepare_v2(db, zSql, -1, ppStmt, 0);
danfd0245d2017-12-07 15:44:29 +00006317 if( rc!=SQLITE_OK ){
6318 raw_printf(stderr, "sql error: %s (%d)\n",
dand4b56e52017-12-12 20:04:59 +00006319 sqlite3_errmsg(db), sqlite3_errcode(db)
danfd0245d2017-12-07 15:44:29 +00006320 );
6321 *pRc = rc;
6322 }
6323 }
6324}
6325
drh9546c762019-05-10 17:50:33 +00006326/*
6327** Create a prepared statement using printf-style arguments for the SQL.
6328**
6329** This routine is could be marked "static". But it is not always used,
6330** depending on compile-time options. By omitting the "static", we avoid
6331** nuisance compiler warnings about "defined but not used".
6332*/
6333void shellPreparePrintf(
dan3f67ddf2017-12-13 20:04:53 +00006334 sqlite3 *db,
6335 int *pRc,
danac15e2d2017-12-14 19:15:07 +00006336 sqlite3_stmt **ppStmt,
6337 const char *zFmt,
6338 ...
dan3f67ddf2017-12-13 20:04:53 +00006339){
danac15e2d2017-12-14 19:15:07 +00006340 *ppStmt = 0;
6341 if( *pRc==SQLITE_OK ){
6342 va_list ap;
6343 char *z;
6344 va_start(ap, zFmt);
6345 z = sqlite3_vmprintf(zFmt, ap);
drh1dbb1472018-10-11 10:37:24 +00006346 va_end(ap);
dan3f67ddf2017-12-13 20:04:53 +00006347 if( z==0 ){
6348 *pRc = SQLITE_NOMEM;
6349 }else{
6350 shellPrepare(db, pRc, z, ppStmt);
6351 sqlite3_free(z);
6352 }
dan3f67ddf2017-12-13 20:04:53 +00006353 }
6354}
6355
drh9546c762019-05-10 17:50:33 +00006356/* Finalize the prepared statement created using shellPreparePrintf().
6357**
6358** This routine is could be marked "static". But it is not always used,
6359** depending on compile-time options. By omitting the "static", we avoid
6360** nuisance compiler warnings about "defined but not used".
6361*/
6362void shellFinalize(
danfd0245d2017-12-07 15:44:29 +00006363 int *pRc,
6364 sqlite3_stmt *pStmt
6365){
dan25c12182017-12-07 21:03:33 +00006366 if( pStmt ){
6367 sqlite3 *db = sqlite3_db_handle(pStmt);
6368 int rc = sqlite3_finalize(pStmt);
6369 if( *pRc==SQLITE_OK ){
6370 if( rc!=SQLITE_OK ){
6371 raw_printf(stderr, "SQL error: %s\n", sqlite3_errmsg(db));
6372 }
6373 *pRc = rc;
6374 }
6375 }
danfd0245d2017-12-07 15:44:29 +00006376}
6377
drh9546c762019-05-10 17:50:33 +00006378/* Reset the prepared statement created using shellPreparePrintf().
6379**
6380** This routine is could be marked "static". But it is not always used,
6381** depending on compile-time options. By omitting the "static", we avoid
6382** nuisance compiler warnings about "defined but not used".
6383*/
6384void shellReset(
danfd0245d2017-12-07 15:44:29 +00006385 int *pRc,
6386 sqlite3_stmt *pStmt
6387){
6388 int rc = sqlite3_reset(pStmt);
dan5a78b812017-12-27 18:54:11 +00006389 if( *pRc==SQLITE_OK ){
6390 if( rc!=SQLITE_OK ){
6391 sqlite3 *db = sqlite3_db_handle(pStmt);
6392 raw_printf(stderr, "SQL error: %s\n", sqlite3_errmsg(db));
6393 }
6394 *pRc = rc;
6395 }
danfd0245d2017-12-07 15:44:29 +00006396}
dan1b162162019-04-27 20:15:15 +00006397#endif /* !defined SQLITE_OMIT_VIRTUALTABLE */
6398
6399#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
drhe2754c12019-08-26 12:50:01 +00006400/******************************************************************************
dan1b162162019-04-27 20:15:15 +00006401** The ".archive" or ".ar" command.
6402*/
drhe37c0e12018-01-06 19:19:50 +00006403/*
dan88be0202017-12-09 17:58:02 +00006404** Structure representing a single ".ar" command.
6405*/
6406typedef struct ArCommand ArCommand;
6407struct ArCommand {
drhb376b3d2018-01-10 13:11:51 +00006408 u8 eCmd; /* An AR_CMD_* value */
6409 u8 bVerbose; /* True if --verbose */
drha5676c42018-01-10 15:17:34 +00006410 u8 bZip; /* True if the archive is a ZIP */
drhb376b3d2018-01-10 13:11:51 +00006411 u8 bDryRun; /* True if --dry-run */
drha5676c42018-01-10 15:17:34 +00006412 u8 bAppend; /* True if --append */
larrybr8f09f4b2021-11-02 00:18:11 +00006413 u8 bGlob; /* True if --glob */
drhd0f9cdc2018-05-17 14:09:06 +00006414 u8 fromCmdLine; /* Run from -A instead of .archive */
drhb376b3d2018-01-10 13:11:51 +00006415 int nArg; /* Number of command arguments */
drha5676c42018-01-10 15:17:34 +00006416 char *zSrcTable; /* "sqlar", "zipfile($file)" or "zip" */
dan88be0202017-12-09 17:58:02 +00006417 const char *zFile; /* --file argument, or NULL */
6418 const char *zDir; /* --directory argument, or NULL */
dan88be0202017-12-09 17:58:02 +00006419 char **azArg; /* Array of command arguments */
drhb376b3d2018-01-10 13:11:51 +00006420 ShellState *p; /* Shell state */
6421 sqlite3 *db; /* Database containing the archive */
dan88be0202017-12-09 17:58:02 +00006422};
6423
6424/*
6425** Print a usage message for the .ar command to stderr and return SQLITE_ERROR.
6426*/
dan0d0547f2017-12-14 15:40:42 +00006427static int arUsage(FILE *f){
drh98aa2ab2018-09-26 16:53:51 +00006428 showHelp(f,"archive");
dan0d0547f2017-12-14 15:40:42 +00006429 return SQLITE_ERROR;
6430}
6431
6432/*
6433** Print an error message for the .ar command to stderr and return
6434** SQLITE_ERROR.
6435*/
drhd0f9cdc2018-05-17 14:09:06 +00006436static int arErrorMsg(ArCommand *pAr, const char *zFmt, ...){
dan0d0547f2017-12-14 15:40:42 +00006437 va_list ap;
6438 char *z;
6439 va_start(ap, zFmt);
6440 z = sqlite3_vmprintf(zFmt, ap);
6441 va_end(ap);
drhd0f9cdc2018-05-17 14:09:06 +00006442 utf8_printf(stderr, "Error: %s\n", z);
6443 if( pAr->fromCmdLine ){
6444 utf8_printf(stderr, "Use \"-A\" for more help\n");
6445 }else{
6446 utf8_printf(stderr, "Use \".archive --help\" for more help\n");
6447 }
dan0d0547f2017-12-14 15:40:42 +00006448 sqlite3_free(z);
dan88be0202017-12-09 17:58:02 +00006449 return SQLITE_ERROR;
6450}
6451
6452/*
6453** Values for ArCommand.eCmd.
6454*/
dand4b56e52017-12-12 20:04:59 +00006455#define AR_CMD_CREATE 1
drhb17ea912019-03-25 14:24:19 +00006456#define AR_CMD_UPDATE 2
6457#define AR_CMD_INSERT 3
6458#define AR_CMD_EXTRACT 4
6459#define AR_CMD_LIST 5
6460#define AR_CMD_HELP 6
larrybr47061b92021-11-01 17:22:52 +00006461#define AR_CMD_REMOVE 7
dand4b56e52017-12-12 20:04:59 +00006462
6463/*
6464** Other (non-command) switches.
6465*/
larrybr47061b92021-11-01 17:22:52 +00006466#define AR_SWITCH_VERBOSE 8
6467#define AR_SWITCH_FILE 9
6468#define AR_SWITCH_DIRECTORY 10
6469#define AR_SWITCH_APPEND 11
larrybr719506f2021-11-01 22:33:20 +00006470#define AR_SWITCH_DRYRUN 12
larrybr8f09f4b2021-11-02 00:18:11 +00006471#define AR_SWITCH_GLOB 13
dand4b56e52017-12-12 20:04:59 +00006472
6473static int arProcessSwitch(ArCommand *pAr, int eSwitch, const char *zArg){
6474 switch( eSwitch ){
6475 case AR_CMD_CREATE:
6476 case AR_CMD_EXTRACT:
6477 case AR_CMD_LIST:
larrybr47061b92021-11-01 17:22:52 +00006478 case AR_CMD_REMOVE:
dand4b56e52017-12-12 20:04:59 +00006479 case AR_CMD_UPDATE:
drhb17ea912019-03-25 14:24:19 +00006480 case AR_CMD_INSERT:
dan0d0547f2017-12-14 15:40:42 +00006481 case AR_CMD_HELP:
6482 if( pAr->eCmd ){
drhd0f9cdc2018-05-17 14:09:06 +00006483 return arErrorMsg(pAr, "multiple command options");
dan0d0547f2017-12-14 15:40:42 +00006484 }
dand4b56e52017-12-12 20:04:59 +00006485 pAr->eCmd = eSwitch;
6486 break;
6487
drhb376b3d2018-01-10 13:11:51 +00006488 case AR_SWITCH_DRYRUN:
6489 pAr->bDryRun = 1;
6490 break;
larrybr8f09f4b2021-11-02 00:18:11 +00006491 case AR_SWITCH_GLOB:
6492 pAr->bGlob = 1;
6493 break;
dand4b56e52017-12-12 20:04:59 +00006494 case AR_SWITCH_VERBOSE:
6495 pAr->bVerbose = 1;
6496 break;
drha5676c42018-01-10 15:17:34 +00006497 case AR_SWITCH_APPEND:
6498 pAr->bAppend = 1;
drhca7733b2018-01-10 18:09:20 +00006499 /* Fall thru into --file */
dand4b56e52017-12-12 20:04:59 +00006500 case AR_SWITCH_FILE:
6501 pAr->zFile = zArg;
6502 break;
6503 case AR_SWITCH_DIRECTORY:
6504 pAr->zDir = zArg;
6505 break;
6506 }
6507
6508 return SQLITE_OK;
6509}
dan88be0202017-12-09 17:58:02 +00006510
6511/*
6512** Parse the command line for an ".ar" command. The results are written into
6513** structure (*pAr). SQLITE_OK is returned if the command line is parsed
6514** successfully, otherwise an error message is written to stderr and
6515** SQLITE_ERROR returned.
6516*/
6517static int arParseCommand(
6518 char **azArg, /* Array of arguments passed to dot command */
6519 int nArg, /* Number of entries in azArg[] */
6520 ArCommand *pAr /* Populate this object */
6521){
dand4b56e52017-12-12 20:04:59 +00006522 struct ArSwitch {
dand4b56e52017-12-12 20:04:59 +00006523 const char *zLong;
drhb376b3d2018-01-10 13:11:51 +00006524 char cShort;
6525 u8 eSwitch;
6526 u8 bArg;
dand4b56e52017-12-12 20:04:59 +00006527 } aSwitch[] = {
drhb376b3d2018-01-10 13:11:51 +00006528 { "create", 'c', AR_CMD_CREATE, 0 },
6529 { "extract", 'x', AR_CMD_EXTRACT, 0 },
drhb17ea912019-03-25 14:24:19 +00006530 { "insert", 'i', AR_CMD_INSERT, 0 },
drhb376b3d2018-01-10 13:11:51 +00006531 { "list", 't', AR_CMD_LIST, 0 },
larrybr47061b92021-11-01 17:22:52 +00006532 { "remove", 'r', AR_CMD_REMOVE, 0 },
drhb376b3d2018-01-10 13:11:51 +00006533 { "update", 'u', AR_CMD_UPDATE, 0 },
6534 { "help", 'h', AR_CMD_HELP, 0 },
6535 { "verbose", 'v', AR_SWITCH_VERBOSE, 0 },
6536 { "file", 'f', AR_SWITCH_FILE, 1 },
drhca7733b2018-01-10 18:09:20 +00006537 { "append", 'a', AR_SWITCH_APPEND, 1 },
drhb376b3d2018-01-10 13:11:51 +00006538 { "directory", 'C', AR_SWITCH_DIRECTORY, 1 },
drhb376b3d2018-01-10 13:11:51 +00006539 { "dryrun", 'n', AR_SWITCH_DRYRUN, 0 },
larrybr8f09f4b2021-11-02 00:18:11 +00006540 { "glob", 'g', AR_SWITCH_GLOB, 0 },
dand4b56e52017-12-12 20:04:59 +00006541 };
6542 int nSwitch = sizeof(aSwitch) / sizeof(struct ArSwitch);
6543 struct ArSwitch *pEnd = &aSwitch[nSwitch];
6544
dan88be0202017-12-09 17:58:02 +00006545 if( nArg<=1 ){
drh98aa2ab2018-09-26 16:53:51 +00006546 utf8_printf(stderr, "Wrong number of arguments. Usage:\n");
dan0d0547f2017-12-14 15:40:42 +00006547 return arUsage(stderr);
dan88be0202017-12-09 17:58:02 +00006548 }else{
6549 char *z = azArg[1];
dan88be0202017-12-09 17:58:02 +00006550 if( z[0]!='-' ){
6551 /* Traditional style [tar] invocation */
6552 int i;
6553 int iArg = 2;
6554 for(i=0; z[i]; i++){
dand4b56e52017-12-12 20:04:59 +00006555 const char *zArg = 0;
6556 struct ArSwitch *pOpt;
6557 for(pOpt=&aSwitch[0]; pOpt<pEnd; pOpt++){
6558 if( z[i]==pOpt->cShort ) break;
dan88be0202017-12-09 17:58:02 +00006559 }
dan0d0547f2017-12-14 15:40:42 +00006560 if( pOpt==pEnd ){
drhd0f9cdc2018-05-17 14:09:06 +00006561 return arErrorMsg(pAr, "unrecognized option: %c", z[i]);
dan0d0547f2017-12-14 15:40:42 +00006562 }
dand4b56e52017-12-12 20:04:59 +00006563 if( pOpt->bArg ){
dan0d0547f2017-12-14 15:40:42 +00006564 if( iArg>=nArg ){
drhd0f9cdc2018-05-17 14:09:06 +00006565 return arErrorMsg(pAr, "option requires an argument: %c",z[i]);
dan0d0547f2017-12-14 15:40:42 +00006566 }
dand4b56e52017-12-12 20:04:59 +00006567 zArg = azArg[iArg++];
6568 }
6569 if( arProcessSwitch(pAr, pOpt->eSwitch, zArg) ) return SQLITE_ERROR;
dan88be0202017-12-09 17:58:02 +00006570 }
dan88be0202017-12-09 17:58:02 +00006571 pAr->nArg = nArg-iArg;
6572 if( pAr->nArg>0 ){
6573 pAr->azArg = &azArg[iArg];
6574 }
dand4b56e52017-12-12 20:04:59 +00006575 }else{
6576 /* Non-traditional invocation */
6577 int iArg;
6578 for(iArg=1; iArg<nArg; iArg++){
6579 int n;
6580 z = azArg[iArg];
6581 if( z[0]!='-' ){
6582 /* All remaining command line words are command arguments. */
6583 pAr->azArg = &azArg[iArg];
6584 pAr->nArg = nArg-iArg;
6585 break;
6586 }
drhaf2770f2018-01-05 14:55:43 +00006587 n = strlen30(z);
dand4b56e52017-12-12 20:04:59 +00006588
6589 if( z[1]!='-' ){
6590 int i;
6591 /* One or more short options */
6592 for(i=1; i<n; i++){
6593 const char *zArg = 0;
6594 struct ArSwitch *pOpt;
6595 for(pOpt=&aSwitch[0]; pOpt<pEnd; pOpt++){
6596 if( z[i]==pOpt->cShort ) break;
6597 }
dan0d0547f2017-12-14 15:40:42 +00006598 if( pOpt==pEnd ){
drhd0f9cdc2018-05-17 14:09:06 +00006599 return arErrorMsg(pAr, "unrecognized option: %c", z[i]);
dan0d0547f2017-12-14 15:40:42 +00006600 }
dand4b56e52017-12-12 20:04:59 +00006601 if( pOpt->bArg ){
6602 if( i<(n-1) ){
6603 zArg = &z[i+1];
6604 i = n;
6605 }else{
dan0d0547f2017-12-14 15:40:42 +00006606 if( iArg>=(nArg-1) ){
drhe2754c12019-08-26 12:50:01 +00006607 return arErrorMsg(pAr, "option requires an argument: %c",
6608 z[i]);
dan0d0547f2017-12-14 15:40:42 +00006609 }
dand4b56e52017-12-12 20:04:59 +00006610 zArg = azArg[++iArg];
6611 }
6612 }
6613 if( arProcessSwitch(pAr, pOpt->eSwitch, zArg) ) return SQLITE_ERROR;
6614 }
6615 }else if( z[2]=='\0' ){
6616 /* A -- option, indicating that all remaining command line words
6617 ** are command arguments. */
6618 pAr->azArg = &azArg[iArg+1];
6619 pAr->nArg = nArg-iArg-1;
6620 break;
6621 }else{
6622 /* A long option */
6623 const char *zArg = 0; /* Argument for option, if any */
6624 struct ArSwitch *pMatch = 0; /* Matching option */
6625 struct ArSwitch *pOpt; /* Iterator */
6626 for(pOpt=&aSwitch[0]; pOpt<pEnd; pOpt++){
6627 const char *zLong = pOpt->zLong;
drhaf2770f2018-01-05 14:55:43 +00006628 if( (n-2)<=strlen30(zLong) && 0==memcmp(&z[2], zLong, n-2) ){
dand4b56e52017-12-12 20:04:59 +00006629 if( pMatch ){
drhd0f9cdc2018-05-17 14:09:06 +00006630 return arErrorMsg(pAr, "ambiguous option: %s",z);
dand4b56e52017-12-12 20:04:59 +00006631 }else{
6632 pMatch = pOpt;
6633 }
6634 }
6635 }
6636
6637 if( pMatch==0 ){
drhd0f9cdc2018-05-17 14:09:06 +00006638 return arErrorMsg(pAr, "unrecognized option: %s", z);
dand4b56e52017-12-12 20:04:59 +00006639 }
6640 if( pMatch->bArg ){
dan0d0547f2017-12-14 15:40:42 +00006641 if( iArg>=(nArg-1) ){
drhd0f9cdc2018-05-17 14:09:06 +00006642 return arErrorMsg(pAr, "option requires an argument: %s", z);
dan0d0547f2017-12-14 15:40:42 +00006643 }
dand4b56e52017-12-12 20:04:59 +00006644 zArg = azArg[++iArg];
6645 }
6646 if( arProcessSwitch(pAr, pMatch->eSwitch, zArg) ) return SQLITE_ERROR;
6647 }
6648 }
dan88be0202017-12-09 17:58:02 +00006649 }
6650 }
6651
6652 return SQLITE_OK;
6653}
6654
6655/*
dan3f67ddf2017-12-13 20:04:53 +00006656** This function assumes that all arguments within the ArCommand.azArg[]
larrybr47061b92021-11-01 17:22:52 +00006657** array refer to archive members, as for the --extract, --list or --remove
larrybr8f09f4b2021-11-02 00:18:11 +00006658** commands. It checks that each of them are "present". If any specified
6659** file is not present in the archive, an error is printed to stderr and an
larrybr47061b92021-11-01 17:22:52 +00006660** error code returned. Otherwise, if all specified arguments are present
larrybr8f09f4b2021-11-02 00:18:11 +00006661** in the archive, SQLITE_OK is returned. Here, "present" means either an
6662** exact equality when pAr->bGlob is false or a "name GLOB pattern" match
drh0c0fb9c2021-11-02 10:54:39 +00006663** when pAr->bGlob is true.
dan3f67ddf2017-12-13 20:04:53 +00006664**
6665** This function strips any trailing '/' characters from each argument.
6666** This is consistent with the way the [tar] command seems to work on
6667** Linux.
6668*/
drhb376b3d2018-01-10 13:11:51 +00006669static int arCheckEntries(ArCommand *pAr){
dan3f67ddf2017-12-13 20:04:53 +00006670 int rc = SQLITE_OK;
6671 if( pAr->nArg ){
drhb376b3d2018-01-10 13:11:51 +00006672 int i, j;
dan3f67ddf2017-12-13 20:04:53 +00006673 sqlite3_stmt *pTest = 0;
larrybr8f09f4b2021-11-02 00:18:11 +00006674 const char *zSel = (pAr->bGlob)
6675 ? "SELECT name FROM %s WHERE glob($name,name)"
6676 : "SELECT name FROM %s WHERE name=$name";
dan3f67ddf2017-12-13 20:04:53 +00006677
larrybr8f09f4b2021-11-02 00:18:11 +00006678 shellPreparePrintf(pAr->db, &rc, &pTest, zSel, pAr->zSrcTable);
drhb376b3d2018-01-10 13:11:51 +00006679 j = sqlite3_bind_parameter_index(pTest, "$name");
dan3f67ddf2017-12-13 20:04:53 +00006680 for(i=0; i<pAr->nArg && rc==SQLITE_OK; i++){
6681 char *z = pAr->azArg[i];
drhaf2770f2018-01-05 14:55:43 +00006682 int n = strlen30(z);
dan3f67ddf2017-12-13 20:04:53 +00006683 int bOk = 0;
6684 while( n>0 && z[n-1]=='/' ) n--;
6685 z[n] = '\0';
drhb376b3d2018-01-10 13:11:51 +00006686 sqlite3_bind_text(pTest, j, z, -1, SQLITE_STATIC);
dan3f67ddf2017-12-13 20:04:53 +00006687 if( SQLITE_ROW==sqlite3_step(pTest) ){
6688 bOk = 1;
6689 }
6690 shellReset(&rc, pTest);
6691 if( rc==SQLITE_OK && bOk==0 ){
drhb376b3d2018-01-10 13:11:51 +00006692 utf8_printf(stderr, "not found in archive: %s\n", z);
dan3f67ddf2017-12-13 20:04:53 +00006693 rc = SQLITE_ERROR;
6694 }
6695 }
6696 shellFinalize(&rc, pTest);
6697 }
dan3f67ddf2017-12-13 20:04:53 +00006698 return rc;
6699}
6700
6701/*
6702** Format a WHERE clause that can be used against the "sqlar" table to
6703** identify all archive members that match the command arguments held
6704** in (*pAr). Leave this WHERE clause in (*pzWhere) before returning.
6705** The caller is responsible for eventually calling sqlite3_free() on
larrybr8f09f4b2021-11-02 00:18:11 +00006706** any non-NULL (*pzWhere) value. Here, "match" means strict equality
6707** when pAr->bGlob is false and GLOB match when pAr->bGlob is true.
dan3f67ddf2017-12-13 20:04:53 +00006708*/
6709static void arWhereClause(
6710 int *pRc,
larrybr8f09f4b2021-11-02 00:18:11 +00006711 ArCommand *pAr,
danac15e2d2017-12-14 19:15:07 +00006712 char **pzWhere /* OUT: New WHERE clause */
dan3f67ddf2017-12-13 20:04:53 +00006713){
6714 char *zWhere = 0;
larrybr8f09f4b2021-11-02 00:18:11 +00006715 const char *zSameOp = (pAr->bGlob)? "GLOB" : "=";
dan3f67ddf2017-12-13 20:04:53 +00006716 if( *pRc==SQLITE_OK ){
danac15e2d2017-12-14 19:15:07 +00006717 if( pAr->nArg==0 ){
6718 zWhere = sqlite3_mprintf("1");
6719 }else{
6720 int i;
6721 const char *zSep = "";
6722 for(i=0; i<pAr->nArg; i++){
6723 const char *z = pAr->azArg[i];
6724 zWhere = sqlite3_mprintf(
larrybr8f09f4b2021-11-02 00:18:11 +00006725 "%z%s name %s '%q' OR substr(name,1,%d) %s '%q/'",
6726 zWhere, zSep, zSameOp, z, strlen30(z)+1, zSameOp, z
drhb376b3d2018-01-10 13:11:51 +00006727 );
danac15e2d2017-12-14 19:15:07 +00006728 if( zWhere==0 ){
6729 *pRc = SQLITE_NOMEM;
6730 break;
6731 }
6732 zSep = " OR ";
dan3f67ddf2017-12-13 20:04:53 +00006733 }
dan3f67ddf2017-12-13 20:04:53 +00006734 }
6735 }
6736 *pzWhere = zWhere;
6737}
6738
6739/*
dan88be0202017-12-09 17:58:02 +00006740** Implementation of .ar "lisT" command.
6741*/
drhb376b3d2018-01-10 13:11:51 +00006742static int arListCommand(ArCommand *pAr){
danb5090e42017-12-27 21:13:21 +00006743 const char *zSql = "SELECT %s FROM %s WHERE %s";
danb5090e42017-12-27 21:13:21 +00006744 const char *azCols[] = {
6745 "name",
drh410cad92018-01-10 17:19:16 +00006746 "lsmode(mode), sz, datetime(mtime, 'unixepoch'), name"
danb5090e42017-12-27 21:13:21 +00006747 };
dan5a78b812017-12-27 18:54:11 +00006748
dan3f67ddf2017-12-13 20:04:53 +00006749 char *zWhere = 0;
6750 sqlite3_stmt *pSql = 0;
6751 int rc;
6752
drhb376b3d2018-01-10 13:11:51 +00006753 rc = arCheckEntries(pAr);
dan3f67ddf2017-12-13 20:04:53 +00006754 arWhereClause(&rc, pAr, &zWhere);
6755
drhb376b3d2018-01-10 13:11:51 +00006756 shellPreparePrintf(pAr->db, &rc, &pSql, zSql, azCols[pAr->bVerbose],
6757 pAr->zSrcTable, zWhere);
drhb376b3d2018-01-10 13:11:51 +00006758 if( pAr->bDryRun ){
6759 utf8_printf(pAr->p->out, "%s\n", sqlite3_sql(pSql));
6760 }else{
6761 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){
6762 if( pAr->bVerbose ){
drh410cad92018-01-10 17:19:16 +00006763 utf8_printf(pAr->p->out, "%s % 10d %s %s\n",
6764 sqlite3_column_text(pSql, 0),
drhb376b3d2018-01-10 13:11:51 +00006765 sqlite3_column_int(pSql, 1),
6766 sqlite3_column_text(pSql, 2),
6767 sqlite3_column_text(pSql, 3)
6768 );
6769 }else{
6770 utf8_printf(pAr->p->out, "%s\n", sqlite3_column_text(pSql, 0));
6771 }
danb5090e42017-12-27 21:13:21 +00006772 }
dan3f67ddf2017-12-13 20:04:53 +00006773 }
dan5a78b812017-12-27 18:54:11 +00006774 shellFinalize(&rc, pSql);
drhd0f9cdc2018-05-17 14:09:06 +00006775 sqlite3_free(zWhere);
dan3f67ddf2017-12-13 20:04:53 +00006776 return rc;
dan88be0202017-12-09 17:58:02 +00006777}
6778
6779
danfd0245d2017-12-07 15:44:29 +00006780/*
larrybr47061b92021-11-01 17:22:52 +00006781** Implementation of .ar "Remove" command.
6782*/
6783static int arRemoveCommand(ArCommand *pAr){
larrybr7774fc02021-11-01 22:30:24 +00006784 int rc = 0;
larrybr47061b92021-11-01 17:22:52 +00006785 char *zSql = 0;
6786 char *zWhere = 0;
6787
6788 if( pAr->nArg ){
6789 /* Verify that args actually exist within the archive before proceeding.
6790 ** And formulate a WHERE clause to match them. */
6791 rc = arCheckEntries(pAr);
6792 arWhereClause(&rc, pAr, &zWhere);
6793 }
6794 if( rc==SQLITE_OK ){
6795 zSql = sqlite3_mprintf("DELETE FROM %s WHERE %s;",
6796 pAr->zSrcTable, zWhere);
6797 if( pAr->bDryRun ){
6798 utf8_printf(pAr->p->out, "%s\n", zSql);
6799 }else{
6800 char *zErr = 0;
6801 rc = sqlite3_exec(pAr->db, "SAVEPOINT ar;", 0, 0, 0);
6802 if( rc==SQLITE_OK ){
6803 rc = sqlite3_exec(pAr->db, zSql, 0, 0, &zErr);
6804 if( rc!=SQLITE_OK ){
6805 sqlite3_exec(pAr->db, "ROLLBACK TO ar; RELEASE ar;", 0, 0, 0);
6806 }else{
6807 rc = sqlite3_exec(pAr->db, "RELEASE ar;", 0, 0, 0);
6808 }
6809 }
6810 if( zErr ){
6811 utf8_printf(stdout, "ERROR: %s\n", zErr);
6812 sqlite3_free(zErr);
6813 }
6814 }
6815 }
6816 sqlite3_free(zWhere);
6817 sqlite3_free(zSql);
6818 return rc;
6819}
6820
6821/*
danfd0245d2017-12-07 15:44:29 +00006822** Implementation of .ar "eXtract" command.
6823*/
drhb376b3d2018-01-10 13:11:51 +00006824static int arExtractCommand(ArCommand *pAr){
dan25c12182017-12-07 21:03:33 +00006825 const char *zSql1 =
dand1b51d42017-12-16 19:11:26 +00006826 "SELECT "
drhb376b3d2018-01-10 13:11:51 +00006827 " ($dir || name),"
6828 " writefile(($dir || name), %s, mode, mtime) "
drh0cfd46a2018-06-06 01:18:01 +00006829 "FROM %s WHERE (%s) AND (data IS NULL OR $dirOnly = 0)"
6830 " AND name NOT GLOB '*..[/\\]*'";
dan5a78b812017-12-27 18:54:11 +00006831
6832 const char *azExtraArg[] = {
6833 "sqlar_uncompress(data, sz)",
dan7c15ac12018-01-08 19:59:59 +00006834 "data"
dan5a78b812017-12-27 18:54:11 +00006835 };
dan5a78b812017-12-27 18:54:11 +00006836
danfd0245d2017-12-07 15:44:29 +00006837 sqlite3_stmt *pSql = 0;
6838 int rc = SQLITE_OK;
dan2ad09492017-12-09 18:28:22 +00006839 char *zDir = 0;
dan3f67ddf2017-12-13 20:04:53 +00006840 char *zWhere = 0;
drhb376b3d2018-01-10 13:11:51 +00006841 int i, j;
dan2ad09492017-12-09 18:28:22 +00006842
dan3f67ddf2017-12-13 20:04:53 +00006843 /* If arguments are specified, check that they actually exist within
6844 ** the archive before proceeding. And formulate a WHERE clause to
6845 ** match them. */
drhb376b3d2018-01-10 13:11:51 +00006846 rc = arCheckEntries(pAr);
dan3f67ddf2017-12-13 20:04:53 +00006847 arWhereClause(&rc, pAr, &zWhere);
6848
6849 if( rc==SQLITE_OK ){
6850 if( pAr->zDir ){
6851 zDir = sqlite3_mprintf("%s/", pAr->zDir);
6852 }else{
6853 zDir = sqlite3_mprintf("");
6854 }
6855 if( zDir==0 ) rc = SQLITE_NOMEM;
dan2ad09492017-12-09 18:28:22 +00006856 }
danfd0245d2017-12-07 15:44:29 +00006857
drhb376b3d2018-01-10 13:11:51 +00006858 shellPreparePrintf(pAr->db, &rc, &pSql, zSql1,
6859 azExtraArg[pAr->bZip], pAr->zSrcTable, zWhere
dan5a78b812017-12-27 18:54:11 +00006860 );
6861
dan2ad09492017-12-09 18:28:22 +00006862 if( rc==SQLITE_OK ){
drhb376b3d2018-01-10 13:11:51 +00006863 j = sqlite3_bind_parameter_index(pSql, "$dir");
6864 sqlite3_bind_text(pSql, j, zDir, -1, SQLITE_STATIC);
dan25c12182017-12-07 21:03:33 +00006865
danac15e2d2017-12-14 19:15:07 +00006866 /* Run the SELECT statement twice. The first time, writefile() is called
6867 ** for all archive members that should be extracted. The second time,
6868 ** only for the directories. This is because the timestamps for
6869 ** extracted directories must be reset after they are populated (as
6870 ** populating them changes the timestamp). */
6871 for(i=0; i<2; i++){
drhb376b3d2018-01-10 13:11:51 +00006872 j = sqlite3_bind_parameter_index(pSql, "$dirOnly");
6873 sqlite3_bind_int(pSql, j, i);
6874 if( pAr->bDryRun ){
6875 utf8_printf(pAr->p->out, "%s\n", sqlite3_sql(pSql));
6876 }else{
6877 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){
6878 if( i==0 && pAr->bVerbose ){
6879 utf8_printf(pAr->p->out, "%s\n", sqlite3_column_text(pSql, 0));
6880 }
danac15e2d2017-12-14 19:15:07 +00006881 }
6882 }
6883 shellReset(&rc, pSql);
dan25c12182017-12-07 21:03:33 +00006884 }
danac15e2d2017-12-14 19:15:07 +00006885 shellFinalize(&rc, pSql);
dan25c12182017-12-07 21:03:33 +00006886 }
dan25c12182017-12-07 21:03:33 +00006887
dan2ad09492017-12-09 18:28:22 +00006888 sqlite3_free(zDir);
dan3f67ddf2017-12-13 20:04:53 +00006889 sqlite3_free(zWhere);
danfd0245d2017-12-07 15:44:29 +00006890 return rc;
6891}
6892
drhb376b3d2018-01-10 13:11:51 +00006893/*
6894** Run the SQL statement in zSql. Or if doing a --dryrun, merely print it out.
6895*/
6896static int arExecSql(ArCommand *pAr, const char *zSql){
6897 int rc;
6898 if( pAr->bDryRun ){
6899 utf8_printf(pAr->p->out, "%s\n", zSql);
6900 rc = SQLITE_OK;
6901 }else{
drh410cad92018-01-10 17:19:16 +00006902 char *zErr = 0;
6903 rc = sqlite3_exec(pAr->db, zSql, 0, 0, &zErr);
6904 if( zErr ){
6905 utf8_printf(stdout, "ERROR: %s\n", zErr);
6906 sqlite3_free(zErr);
6907 }
drhb376b3d2018-01-10 13:11:51 +00006908 }
6909 return rc;
6910}
6911
dan1ad3f612017-12-11 20:22:02 +00006912
danfd0245d2017-12-07 15:44:29 +00006913/*
drhb17ea912019-03-25 14:24:19 +00006914** Implementation of .ar "create", "insert", and "update" commands.
6915**
6916** create -> Create a new SQL archive
6917** insert -> Insert or reinsert all files listed
6918** update -> Insert files that have changed or that were not
6919** previously in the archive
danfd0245d2017-12-07 15:44:29 +00006920**
6921** Create the "sqlar" table in the database if it does not already exist.
6922** Then add each file in the azFile[] array to the archive. Directories
6923** are added recursively. If argument bVerbose is non-zero, a message is
6924** printed on stdout for each file archived.
dan06741a32017-12-13 20:17:18 +00006925**
6926** The create command is the same as update, except that it drops
drhb17ea912019-03-25 14:24:19 +00006927** any existing "sqlar" table before beginning. The "insert" command
6928** always overwrites every file named on the command-line, where as
6929** "update" only overwrites if the size or mtime or mode has changed.
danfd0245d2017-12-07 15:44:29 +00006930*/
drhb376b3d2018-01-10 13:11:51 +00006931static int arCreateOrUpdateCommand(
dan06741a32017-12-13 20:17:18 +00006932 ArCommand *pAr, /* Command arguments and options */
drhb17ea912019-03-25 14:24:19 +00006933 int bUpdate, /* true for a --create. */
6934 int bOnlyIfChanged /* Only update if file has changed */
danfd0245d2017-12-07 15:44:29 +00006935){
dand4b56e52017-12-12 20:04:59 +00006936 const char *zCreate =
drhafba1802018-01-06 15:49:57 +00006937 "CREATE TABLE IF NOT EXISTS sqlar(\n"
6938 " name TEXT PRIMARY KEY, -- name of the file\n"
6939 " mode INT, -- access permissions\n"
6940 " mtime INT, -- last modification time\n"
6941 " sz INT, -- original file size\n"
6942 " data BLOB -- compressed content\n"
6943 ")";
dand4b56e52017-12-12 20:04:59 +00006944 const char *zDrop = "DROP TABLE IF EXISTS sqlar";
drh1bf208c2018-03-09 21:54:01 +00006945 const char *zInsertFmt[2] = {
6946 "REPLACE INTO %s(name,mode,mtime,sz,data)\n"
drh634c70f2018-01-10 16:50:18 +00006947 " SELECT\n"
6948 " %s,\n"
6949 " mode,\n"
6950 " mtime,\n"
drh410cad92018-01-10 17:19:16 +00006951 " CASE substr(lsmode(mode),1,1)\n"
6952 " WHEN '-' THEN length(data)\n"
6953 " WHEN 'd' THEN 0\n"
drh634c70f2018-01-10 16:50:18 +00006954 " ELSE -1 END,\n"
drh69d2d352018-03-09 22:18:53 +00006955 " sqlar_compress(data)\n"
drhb17ea912019-03-25 14:24:19 +00006956 " FROM fsdir(%Q,%Q) AS disk\n"
6957 " WHERE lsmode(mode) NOT LIKE '?%%'%s;"
6958 ,
drh1bf208c2018-03-09 21:54:01 +00006959 "REPLACE INTO %s(name,mode,mtime,data)\n"
6960 " SELECT\n"
6961 " %s,\n"
6962 " mode,\n"
6963 " mtime,\n"
6964 " data\n"
drhb17ea912019-03-25 14:24:19 +00006965 " FROM fsdir(%Q,%Q) AS disk\n"
6966 " WHERE lsmode(mode) NOT LIKE '?%%'%s;"
drh1bf208c2018-03-09 21:54:01 +00006967 };
danfd0245d2017-12-07 15:44:29 +00006968 int i; /* For iterating through azFile[] */
6969 int rc; /* Return code */
drh1bf208c2018-03-09 21:54:01 +00006970 const char *zTab = 0; /* SQL table into which to insert */
6971 char *zSql;
6972 char zTemp[50];
drhb17ea912019-03-25 14:24:19 +00006973 char *zExists = 0;
danfd0245d2017-12-07 15:44:29 +00006974
drh1bf208c2018-03-09 21:54:01 +00006975 arExecSql(pAr, "PRAGMA page_size=512");
drhb376b3d2018-01-10 13:11:51 +00006976 rc = arExecSql(pAr, "SAVEPOINT ar;");
danfd0245d2017-12-07 15:44:29 +00006977 if( rc!=SQLITE_OK ) return rc;
drh1bf208c2018-03-09 21:54:01 +00006978 zTemp[0] = 0;
6979 if( pAr->bZip ){
6980 /* Initialize the zipfile virtual table, if necessary */
6981 if( pAr->zFile ){
6982 sqlite3_uint64 r;
6983 sqlite3_randomness(sizeof(r),&r);
6984 sqlite3_snprintf(sizeof(zTemp),zTemp,"zip%016llx",r);
6985 zTab = zTemp;
6986 zSql = sqlite3_mprintf(
6987 "CREATE VIRTUAL TABLE temp.%s USING zipfile(%Q)",
6988 zTab, pAr->zFile
6989 );
6990 rc = arExecSql(pAr, zSql);
6991 sqlite3_free(zSql);
6992 }else{
6993 zTab = "zip";
6994 }
6995 }else{
6996 /* Initialize the table for an SQLAR */
6997 zTab = "sqlar";
6998 if( bUpdate==0 ){
6999 rc = arExecSql(pAr, zDrop);
7000 if( rc!=SQLITE_OK ) goto end_ar_transaction;
7001 }
7002 rc = arExecSql(pAr, zCreate);
dan06741a32017-12-13 20:17:18 +00007003 }
drhb17ea912019-03-25 14:24:19 +00007004 if( bOnlyIfChanged ){
7005 zExists = sqlite3_mprintf(
7006 " AND NOT EXISTS("
7007 "SELECT 1 FROM %s AS mem"
7008 " WHERE mem.name=disk.name"
7009 " AND mem.mtime=disk.mtime"
7010 " AND mem.mode=disk.mode)", zTab);
7011 }else{
7012 zExists = sqlite3_mprintf("");
7013 }
7014 if( zExists==0 ) rc = SQLITE_NOMEM;
dan88be0202017-12-09 17:58:02 +00007015 for(i=0; i<pAr->nArg && rc==SQLITE_OK; i++){
mistachkince2052b2018-03-23 00:31:53 +00007016 char *zSql2 = sqlite3_mprintf(zInsertFmt[pAr->bZip], zTab,
drh634c70f2018-01-10 16:50:18 +00007017 pAr->bVerbose ? "shell_putsnl(name)" : "name",
drhb17ea912019-03-25 14:24:19 +00007018 pAr->azArg[i], pAr->zDir, zExists);
mistachkince2052b2018-03-23 00:31:53 +00007019 rc = arExecSql(pAr, zSql2);
7020 sqlite3_free(zSql2);
danfd0245d2017-12-07 15:44:29 +00007021 }
drh1bf208c2018-03-09 21:54:01 +00007022end_ar_transaction:
danfd0245d2017-12-07 15:44:29 +00007023 if( rc!=SQLITE_OK ){
drh2bd207f2019-01-11 17:19:59 +00007024 sqlite3_exec(pAr->db, "ROLLBACK TO ar; RELEASE ar;", 0, 0, 0);
danfd0245d2017-12-07 15:44:29 +00007025 }else{
drhb376b3d2018-01-10 13:11:51 +00007026 rc = arExecSql(pAr, "RELEASE ar;");
drh1bf208c2018-03-09 21:54:01 +00007027 if( pAr->bZip && pAr->zFile ){
7028 zSql = sqlite3_mprintf("DROP TABLE %s", zTemp);
7029 arExecSql(pAr, zSql);
7030 sqlite3_free(zSql);
7031 }
danfd0245d2017-12-07 15:44:29 +00007032 }
drhb17ea912019-03-25 14:24:19 +00007033 sqlite3_free(zExists);
danfd0245d2017-12-07 15:44:29 +00007034 return rc;
7035}
7036
7037/*
7038** Implementation of ".ar" dot command.
7039*/
7040static int arDotCommand(
drhe2754c12019-08-26 12:50:01 +00007041 ShellState *pState, /* Current shell tool state */
7042 int fromCmdLine, /* True if -A command-line option, not .ar cmd */
7043 char **azArg, /* Array of arguments passed to dot command */
7044 int nArg /* Number of entries in azArg[] */
danfd0245d2017-12-07 15:44:29 +00007045){
dan88be0202017-12-09 17:58:02 +00007046 ArCommand cmd;
7047 int rc;
drh34660642018-01-10 17:39:54 +00007048 memset(&cmd, 0, sizeof(cmd));
drhd0f9cdc2018-05-17 14:09:06 +00007049 cmd.fromCmdLine = fromCmdLine;
dan88be0202017-12-09 17:58:02 +00007050 rc = arParseCommand(azArg, nArg, &cmd);
7051 if( rc==SQLITE_OK ){
drha5676c42018-01-10 15:17:34 +00007052 int eDbType = SHELL_OPEN_UNSPEC;
drhb376b3d2018-01-10 13:11:51 +00007053 cmd.p = pState;
7054 cmd.db = pState->db;
drha5676c42018-01-10 15:17:34 +00007055 if( cmd.zFile ){
drh1bf208c2018-03-09 21:54:01 +00007056 eDbType = deduceDatabaseType(cmd.zFile, 1);
drha5676c42018-01-10 15:17:34 +00007057 }else{
7058 eDbType = pState->openMode;
7059 }
7060 if( eDbType==SHELL_OPEN_ZIPFILE ){
drh1bf208c2018-03-09 21:54:01 +00007061 if( cmd.eCmd==AR_CMD_EXTRACT || cmd.eCmd==AR_CMD_LIST ){
7062 if( cmd.zFile==0 ){
7063 cmd.zSrcTable = sqlite3_mprintf("zip");
7064 }else{
7065 cmd.zSrcTable = sqlite3_mprintf("zipfile(%Q)", cmd.zFile);
7066 }
dan5a78b812017-12-27 18:54:11 +00007067 }
drha5676c42018-01-10 15:17:34 +00007068 cmd.bZip = 1;
dan5a78b812017-12-27 18:54:11 +00007069 }else if( cmd.zFile ){
dand4b56e52017-12-12 20:04:59 +00007070 int flags;
drha5676c42018-01-10 15:17:34 +00007071 if( cmd.bAppend ) eDbType = SHELL_OPEN_APPENDVFS;
drhb17ea912019-03-25 14:24:19 +00007072 if( cmd.eCmd==AR_CMD_CREATE || cmd.eCmd==AR_CMD_INSERT
larrybr47061b92021-11-01 17:22:52 +00007073 || cmd.eCmd==AR_CMD_REMOVE || cmd.eCmd==AR_CMD_UPDATE ){
dand4b56e52017-12-12 20:04:59 +00007074 flags = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE;
7075 }else{
7076 flags = SQLITE_OPEN_READONLY;
7077 }
drha82c95b2018-01-10 14:00:00 +00007078 cmd.db = 0;
drha5676c42018-01-10 15:17:34 +00007079 if( cmd.bDryRun ){
7080 utf8_printf(pState->out, "-- open database '%s'%s\n", cmd.zFile,
7081 eDbType==SHELL_OPEN_APPENDVFS ? " using 'apndvfs'" : "");
7082 }
7083 rc = sqlite3_open_v2(cmd.zFile, &cmd.db, flags,
7084 eDbType==SHELL_OPEN_APPENDVFS ? "apndvfs" : 0);
dand4b56e52017-12-12 20:04:59 +00007085 if( rc!=SQLITE_OK ){
drhb376b3d2018-01-10 13:11:51 +00007086 utf8_printf(stderr, "cannot open file: %s (%s)\n",
7087 cmd.zFile, sqlite3_errmsg(cmd.db)
dand4b56e52017-12-12 20:04:59 +00007088 );
drha5676c42018-01-10 15:17:34 +00007089 goto end_ar_command;
dand4b56e52017-12-12 20:04:59 +00007090 }
drhb376b3d2018-01-10 13:11:51 +00007091 sqlite3_fileio_init(cmd.db, 0, 0);
drhb376b3d2018-01-10 13:11:51 +00007092 sqlite3_sqlar_init(cmd.db, 0, 0);
drh34660642018-01-10 17:39:54 +00007093 sqlite3_create_function(cmd.db, "shell_putsnl", 1, SQLITE_UTF8, cmd.p,
7094 shellPutsFunc, 0, 0);
7095
dand4b56e52017-12-12 20:04:59 +00007096 }
drhd0f9cdc2018-05-17 14:09:06 +00007097 if( cmd.zSrcTable==0 && cmd.bZip==0 && cmd.eCmd!=AR_CMD_HELP ){
drh634c70f2018-01-10 16:50:18 +00007098 if( cmd.eCmd!=AR_CMD_CREATE
7099 && sqlite3_table_column_metadata(cmd.db,0,"sqlar","name",0,0,0,0,0)
7100 ){
drha5676c42018-01-10 15:17:34 +00007101 utf8_printf(stderr, "database does not contain an 'sqlar' table\n");
7102 rc = SQLITE_ERROR;
7103 goto end_ar_command;
7104 }
7105 cmd.zSrcTable = sqlite3_mprintf("sqlar");
7106 }
dand4b56e52017-12-12 20:04:59 +00007107
dan88be0202017-12-09 17:58:02 +00007108 switch( cmd.eCmd ){
7109 case AR_CMD_CREATE:
drhb17ea912019-03-25 14:24:19 +00007110 rc = arCreateOrUpdateCommand(&cmd, 0, 0);
dan88be0202017-12-09 17:58:02 +00007111 break;
danfd0245d2017-12-07 15:44:29 +00007112
dan88be0202017-12-09 17:58:02 +00007113 case AR_CMD_EXTRACT:
drhb376b3d2018-01-10 13:11:51 +00007114 rc = arExtractCommand(&cmd);
dan88be0202017-12-09 17:58:02 +00007115 break;
7116
7117 case AR_CMD_LIST:
drhb376b3d2018-01-10 13:11:51 +00007118 rc = arListCommand(&cmd);
dan88be0202017-12-09 17:58:02 +00007119 break;
7120
dan0d0547f2017-12-14 15:40:42 +00007121 case AR_CMD_HELP:
7122 arUsage(pState->out);
7123 break;
7124
drhb17ea912019-03-25 14:24:19 +00007125 case AR_CMD_INSERT:
7126 rc = arCreateOrUpdateCommand(&cmd, 1, 0);
7127 break;
7128
larrybr47061b92021-11-01 17:22:52 +00007129 case AR_CMD_REMOVE:
7130 rc = arRemoveCommand(&cmd);
7131 break;
7132
dan88be0202017-12-09 17:58:02 +00007133 default:
7134 assert( cmd.eCmd==AR_CMD_UPDATE );
drhb17ea912019-03-25 14:24:19 +00007135 rc = arCreateOrUpdateCommand(&cmd, 1, 1);
dan88be0202017-12-09 17:58:02 +00007136 break;
danfd0245d2017-12-07 15:44:29 +00007137 }
7138 }
drha5676c42018-01-10 15:17:34 +00007139end_ar_command:
7140 if( cmd.db!=pState->db ){
drh9e804032018-05-18 17:11:50 +00007141 close_db(cmd.db);
drha5676c42018-01-10 15:17:34 +00007142 }
7143 sqlite3_free(cmd.zSrcTable);
danfd0245d2017-12-07 15:44:29 +00007144
dan88be0202017-12-09 17:58:02 +00007145 return rc;
danfd0245d2017-12-07 15:44:29 +00007146}
drhe37c0e12018-01-06 19:19:50 +00007147/* End of the ".archive" or ".ar" command logic
drhe2754c12019-08-26 12:50:01 +00007148*******************************************************************************/
drhe37c0e12018-01-06 19:19:50 +00007149#endif /* !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB) */
danfd0245d2017-12-07 15:44:29 +00007150
dan1b162162019-04-27 20:15:15 +00007151#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
dan42ebb012019-04-27 18:47:03 +00007152/*
7153** If (*pRc) is not SQLITE_OK when this function is called, it is a no-op.
7154** Otherwise, the SQL statement or statements in zSql are executed using
7155** database connection db and the error code written to *pRc before
7156** this function returns.
7157*/
dan68cb86e2019-04-20 20:57:28 +00007158static void shellExec(sqlite3 *db, int *pRc, const char *zSql){
7159 int rc = *pRc;
7160 if( rc==SQLITE_OK ){
7161 char *zErr = 0;
7162 rc = sqlite3_exec(db, zSql, 0, 0, &zErr);
7163 if( rc!=SQLITE_OK ){
7164 raw_printf(stderr, "SQL error: %s\n", zErr);
7165 }
drhf83d5012021-05-03 13:35:00 +00007166 sqlite3_free(zErr);
dan68cb86e2019-04-20 20:57:28 +00007167 *pRc = rc;
7168 }
7169}
7170
dan42ebb012019-04-27 18:47:03 +00007171/*
7172** Like shellExec(), except that zFmt is a printf() style format string.
7173*/
danc0b42432019-04-26 15:14:53 +00007174static void shellExecPrintf(sqlite3 *db, int *pRc, const char *zFmt, ...){
7175 char *z = 0;
7176 if( *pRc==SQLITE_OK ){
7177 va_list ap;
7178 va_start(ap, zFmt);
7179 z = sqlite3_vmprintf(zFmt, ap);
7180 va_end(ap);
7181 if( z==0 ){
7182 *pRc = SQLITE_NOMEM;
7183 }else{
7184 shellExec(db, pRc, z);
7185 }
7186 sqlite3_free(z);
7187 }
7188}
7189
dan42ebb012019-04-27 18:47:03 +00007190/*
7191** If *pRc is not SQLITE_OK when this function is called, it is a no-op.
7192** Otherwise, an attempt is made to allocate, zero and return a pointer
7193** to a buffer nByte bytes in size. If an OOM error occurs, *pRc is set
7194** to SQLITE_NOMEM and NULL returned.
7195*/
dan68cb86e2019-04-20 20:57:28 +00007196static void *shellMalloc(int *pRc, sqlite3_int64 nByte){
7197 void *pRet = 0;
7198 if( *pRc==SQLITE_OK ){
7199 pRet = sqlite3_malloc64(nByte);
7200 if( pRet==0 ){
7201 *pRc = SQLITE_NOMEM;
7202 }else{
7203 memset(pRet, 0, nByte);
7204 }
7205 }
7206 return pRet;
7207}
7208
dan42ebb012019-04-27 18:47:03 +00007209/*
7210** If *pRc is not SQLITE_OK when this function is called, it is a no-op.
7211** Otherwise, zFmt is treated as a printf() style string. The result of
7212** formatting it along with any trailing arguments is written into a
7213** buffer obtained from sqlite3_malloc(), and pointer to which is returned.
7214** It is the responsibility of the caller to eventually free this buffer
7215** using a call to sqlite3_free().
7216**
7217** If an OOM error occurs, (*pRc) is set to SQLITE_NOMEM and a NULL
7218** pointer returned.
7219*/
dan68cb86e2019-04-20 20:57:28 +00007220static char *shellMPrintf(int *pRc, const char *zFmt, ...){
7221 char *z = 0;
7222 if( *pRc==SQLITE_OK ){
7223 va_list ap;
7224 va_start(ap, zFmt);
7225 z = sqlite3_vmprintf(zFmt, ap);
7226 va_end(ap);
7227 if( z==0 ){
7228 *pRc = SQLITE_NOMEM;
7229 }
7230 }
7231 return z;
7232}
7233
larrybr58a53d62022-02-10 03:21:48 +00007234
dan42ebb012019-04-27 18:47:03 +00007235/*
7236** When running the ".recover" command, each output table, and the special
7237** orphaned row table if it is required, is represented by an instance
7238** of the following struct.
7239*/
dan68cb86e2019-04-20 20:57:28 +00007240typedef struct RecoverTable RecoverTable;
7241struct RecoverTable {
dan42ebb012019-04-27 18:47:03 +00007242 char *zQuoted; /* Quoted version of table name */
dan68cb86e2019-04-20 20:57:28 +00007243 int nCol; /* Number of columns in table */
7244 char **azlCol; /* Array of column lists */
dan42ebb012019-04-27 18:47:03 +00007245 int iPk; /* Index of IPK column */
dan68cb86e2019-04-20 20:57:28 +00007246};
7247
7248/*
dan42ebb012019-04-27 18:47:03 +00007249** Free a RecoverTable object allocated by recoverFindTable() or
7250** recoverOrphanTable().
dan68cb86e2019-04-20 20:57:28 +00007251*/
7252static void recoverFreeTable(RecoverTable *pTab){
7253 if( pTab ){
dan68cb86e2019-04-20 20:57:28 +00007254 sqlite3_free(pTab->zQuoted);
dan68cb86e2019-04-20 20:57:28 +00007255 if( pTab->azlCol ){
7256 int i;
dan98c5ad32019-04-26 21:11:37 +00007257 for(i=0; i<=pTab->nCol; i++){
dan68cb86e2019-04-20 20:57:28 +00007258 sqlite3_free(pTab->azlCol[i]);
7259 }
7260 sqlite3_free(pTab->azlCol);
7261 }
7262 sqlite3_free(pTab);
7263 }
7264}
7265
dan42ebb012019-04-27 18:47:03 +00007266/*
7267** This function is a no-op if (*pRc) is not SQLITE_OK when it is called.
7268** Otherwise, it allocates and returns a RecoverTable object based on the
7269** final four arguments passed to this function. It is the responsibility
7270** of the caller to eventually free the returned object using
7271** recoverFreeTable().
7272*/
7273static RecoverTable *recoverNewTable(
danb40af492019-04-22 20:52:12 +00007274 int *pRc, /* IN/OUT: Error code */
danb40af492019-04-22 20:52:12 +00007275 const char *zName, /* Name of table */
7276 const char *zSql, /* CREATE TABLE statement */
7277 int bIntkey,
7278 int nCol
7279){
7280 sqlite3 *dbtmp = 0; /* sqlite3 handle for testing CREATE TABLE */
7281 int rc = *pRc;
dan98c5ad32019-04-26 21:11:37 +00007282 RecoverTable *pTab = 0;
danb40af492019-04-22 20:52:12 +00007283
dan98c5ad32019-04-26 21:11:37 +00007284 pTab = (RecoverTable*)shellMalloc(&rc, sizeof(RecoverTable));
danb40af492019-04-22 20:52:12 +00007285 if( rc==SQLITE_OK ){
7286 int nSqlCol = 0;
7287 int bSqlIntkey = 0;
7288 sqlite3_stmt *pStmt = 0;
dan98c5ad32019-04-26 21:11:37 +00007289
danb40af492019-04-22 20:52:12 +00007290 rc = sqlite3_open("", &dbtmp);
7291 if( rc==SQLITE_OK ){
drha2de66c2019-08-06 20:26:17 +00007292 sqlite3_create_function(dbtmp, "shell_idquote", 1, SQLITE_UTF8, 0,
7293 shellIdQuote, 0, 0);
7294 }
7295 if( rc==SQLITE_OK ){
dan38f9c712019-04-23 18:03:02 +00007296 rc = sqlite3_exec(dbtmp, "PRAGMA writable_schema = on", 0, 0, 0);
7297 }
7298 if( rc==SQLITE_OK ){
danb40af492019-04-22 20:52:12 +00007299 rc = sqlite3_exec(dbtmp, zSql, 0, 0, 0);
7300 if( rc==SQLITE_ERROR ){
7301 rc = SQLITE_OK;
7302 goto finished;
7303 }
7304 }
7305 shellPreparePrintf(dbtmp, &rc, &pStmt,
7306 "SELECT count(*) FROM pragma_table_info(%Q)", zName
7307 );
7308 if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
7309 nSqlCol = sqlite3_column_int(pStmt, 0);
7310 }
7311 shellFinalize(&rc, pStmt);
7312
7313 if( rc!=SQLITE_OK || nSqlCol<nCol ){
7314 goto finished;
7315 }
7316
7317 shellPreparePrintf(dbtmp, &rc, &pStmt,
7318 "SELECT ("
7319 " SELECT substr(data,1,1)==X'0D' FROM sqlite_dbpage WHERE pgno=rootpage"
drh067b92b2020-06-19 15:24:12 +00007320 ") FROM sqlite_schema WHERE name = %Q", zName
danb40af492019-04-22 20:52:12 +00007321 );
7322 if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
7323 bSqlIntkey = sqlite3_column_int(pStmt, 0);
7324 }
7325 shellFinalize(&rc, pStmt);
7326
7327 if( bIntkey==bSqlIntkey ){
dan98c5ad32019-04-26 21:11:37 +00007328 int i;
danb40af492019-04-22 20:52:12 +00007329 const char *zPk = "_rowid_";
7330 sqlite3_stmt *pPkFinder = 0;
7331
danf57bea32019-04-27 15:35:45 +00007332 /* If this is an intkey table and there is an INTEGER PRIMARY KEY,
7333 ** set zPk to the name of the PK column, and pTab->iPk to the index
7334 ** of the column, where columns are 0-numbered from left to right.
7335 ** Or, if this is a WITHOUT ROWID table or if there is no IPK column,
7336 ** leave zPk as "_rowid_" and pTab->iPk at -2. */
dan98c5ad32019-04-26 21:11:37 +00007337 pTab->iPk = -2;
7338 if( bIntkey ){
7339 shellPreparePrintf(dbtmp, &rc, &pPkFinder,
danb40af492019-04-22 20:52:12 +00007340 "SELECT cid, name FROM pragma_table_info(%Q) "
7341 " WHERE pk=1 AND type='integer' COLLATE nocase"
dan98c5ad32019-04-26 21:11:37 +00007342 " AND NOT EXISTS (SELECT cid FROM pragma_table_info(%Q) WHERE pk=2)"
7343 , zName, zName
7344 );
7345 if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pPkFinder) ){
7346 pTab->iPk = sqlite3_column_int(pPkFinder, 0);
7347 zPk = (const char*)sqlite3_column_text(pPkFinder, 1);
drh621a5e02021-12-16 17:35:27 +00007348 if( zPk==0 ){ zPk = "_"; /* Defensive. Should never happen */ }
dan98c5ad32019-04-26 21:11:37 +00007349 }
danb40af492019-04-22 20:52:12 +00007350 }
7351
drha2de66c2019-08-06 20:26:17 +00007352 pTab->zQuoted = shellMPrintf(&rc, "\"%w\"", zName);
dan98c5ad32019-04-26 21:11:37 +00007353 pTab->azlCol = (char**)shellMalloc(&rc, sizeof(char*) * (nSqlCol+1));
danb40af492019-04-22 20:52:12 +00007354 pTab->nCol = nSqlCol;
7355
dan98c5ad32019-04-26 21:11:37 +00007356 if( bIntkey ){
drha2de66c2019-08-06 20:26:17 +00007357 pTab->azlCol[0] = shellMPrintf(&rc, "\"%w\"", zPk);
danb40af492019-04-22 20:52:12 +00007358 }else{
dan98c5ad32019-04-26 21:11:37 +00007359 pTab->azlCol[0] = shellMPrintf(&rc, "");
danb40af492019-04-22 20:52:12 +00007360 }
dan98c5ad32019-04-26 21:11:37 +00007361 i = 1;
7362 shellPreparePrintf(dbtmp, &rc, &pStmt,
drha2de66c2019-08-06 20:26:17 +00007363 "SELECT %Q || group_concat(shell_idquote(name), ', ') "
danf57bea32019-04-27 15:35:45 +00007364 " FILTER (WHERE cid!=%d) OVER (ORDER BY %s cid) "
dan98c5ad32019-04-26 21:11:37 +00007365 "FROM pragma_table_info(%Q)",
danf57bea32019-04-27 15:35:45 +00007366 bIntkey ? ", " : "", pTab->iPk,
7367 bIntkey ? "" : "(CASE WHEN pk=0 THEN 1000000 ELSE pk END), ",
7368 zName
dan98c5ad32019-04-26 21:11:37 +00007369 );
7370 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
7371 const char *zText = (const char*)sqlite3_column_text(pStmt, 0);
7372 pTab->azlCol[i] = shellMPrintf(&rc, "%s%s", pTab->azlCol[0], zText);
7373 i++;
7374 }
7375 shellFinalize(&rc, pStmt);
7376
danb40af492019-04-22 20:52:12 +00007377 shellFinalize(&rc, pPkFinder);
7378 }
7379 }
7380
7381 finished:
7382 sqlite3_close(dbtmp);
7383 *pRc = rc;
dan98779652019-05-09 14:15:19 +00007384 if( rc!=SQLITE_OK || (pTab && pTab->zQuoted==0) ){
dan98c5ad32019-04-26 21:11:37 +00007385 recoverFreeTable(pTab);
7386 pTab = 0;
7387 }
7388 return pTab;
danb40af492019-04-22 20:52:12 +00007389}
7390
dan0aa01ee2019-04-27 19:36:49 +00007391/*
7392** This function is called to search the schema recovered from the
drh067b92b2020-06-19 15:24:12 +00007393** sqlite_schema table of the (possibly) corrupt database as part
dan0aa01ee2019-04-27 19:36:49 +00007394** of a ".recover" command. Specifically, for a table with root page
7395** iRoot and at least nCol columns. Additionally, if bIntkey is 0, the
7396** table must be a WITHOUT ROWID table, or if non-zero, not one of
7397** those.
7398**
7399** If a table is found, a (RecoverTable*) object is returned. Or, if
7400** no such table is found, but bIntkey is false and iRoot is the
7401** root page of an index in the recovered schema, then (*pbNoop) is
7402** set to true and NULL returned. Or, if there is no such table or
7403** index, NULL is returned and (*pbNoop) set to 0, indicating that
7404** the caller should write data to the orphans table.
7405*/
dan42ebb012019-04-27 18:47:03 +00007406static RecoverTable *recoverFindTable(
dan0aa01ee2019-04-27 19:36:49 +00007407 ShellState *pState, /* Shell state object */
7408 int *pRc, /* IN/OUT: Error code */
7409 int iRoot, /* Root page of table */
7410 int bIntkey, /* True for an intkey table */
7411 int nCol, /* Number of columns in table */
7412 int *pbNoop /* OUT: True if iRoot is root of index */
dan68cb86e2019-04-20 20:57:28 +00007413){
danb40af492019-04-22 20:52:12 +00007414 sqlite3_stmt *pStmt = 0;
dan68cb86e2019-04-20 20:57:28 +00007415 RecoverTable *pRet = 0;
danb40af492019-04-22 20:52:12 +00007416 int bNoop = 0;
7417 const char *zSql = 0;
7418 const char *zName = 0;
dan68cb86e2019-04-20 20:57:28 +00007419
danb40af492019-04-22 20:52:12 +00007420 /* Search the recovered schema for an object with root page iRoot. */
7421 shellPreparePrintf(pState->db, pRc, &pStmt,
7422 "SELECT type, name, sql FROM recovery.schema WHERE rootpage=%d", iRoot
7423 );
7424 while( *pRc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
7425 const char *zType = (const char*)sqlite3_column_text(pStmt, 0);
7426 if( bIntkey==0 && sqlite3_stricmp(zType, "index")==0 ){
7427 bNoop = 1;
7428 break;
7429 }
7430 if( sqlite3_stricmp(zType, "table")==0 ){
7431 zName = (const char*)sqlite3_column_text(pStmt, 1);
7432 zSql = (const char*)sqlite3_column_text(pStmt, 2);
drh621a5e02021-12-16 17:35:27 +00007433 if( zName!=0 && zSql!=0 ){
7434 pRet = recoverNewTable(pRc, zName, zSql, bIntkey, nCol);
7435 break;
7436 }
danb40af492019-04-22 20:52:12 +00007437 }
7438 }
dan98c5ad32019-04-26 21:11:37 +00007439
danb40af492019-04-22 20:52:12 +00007440 shellFinalize(pRc, pStmt);
dan98c5ad32019-04-26 21:11:37 +00007441 *pbNoop = bNoop;
7442 return pRet;
7443}
danb40af492019-04-22 20:52:12 +00007444
dan0aa01ee2019-04-27 19:36:49 +00007445/*
7446** Return a RecoverTable object representing the orphans table.
7447*/
dan98c5ad32019-04-26 21:11:37 +00007448static RecoverTable *recoverOrphanTable(
dan0aa01ee2019-04-27 19:36:49 +00007449 ShellState *pState, /* Shell state object */
7450 int *pRc, /* IN/OUT: Error code */
7451 const char *zLostAndFound, /* Base name for orphans table */
7452 int nCol /* Number of user data columns */
dan98c5ad32019-04-26 21:11:37 +00007453){
7454 RecoverTable *pTab = 0;
7455 if( nCol>=0 && *pRc==SQLITE_OK ){
7456 int i;
dan42ebb012019-04-27 18:47:03 +00007457
7458 /* This block determines the name of the orphan table. The prefered
7459 ** name is zLostAndFound. But if that clashes with another name
7460 ** in the recovered schema, try zLostAndFound_0, zLostAndFound_1
7461 ** and so on until a non-clashing name is found. */
7462 int iTab = 0;
7463 char *zTab = shellMPrintf(pRc, "%s", zLostAndFound);
7464 sqlite3_stmt *pTest = 0;
7465 shellPrepare(pState->db, pRc,
7466 "SELECT 1 FROM recovery.schema WHERE name=?", &pTest
dan68cb86e2019-04-20 20:57:28 +00007467 );
dan42ebb012019-04-27 18:47:03 +00007468 if( pTest ) sqlite3_bind_text(pTest, 1, zTab, -1, SQLITE_TRANSIENT);
7469 while( *pRc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pTest) ){
7470 shellReset(pRc, pTest);
7471 sqlite3_free(zTab);
7472 zTab = shellMPrintf(pRc, "%s_%d", zLostAndFound, iTab++);
7473 sqlite3_bind_text(pTest, 1, zTab, -1, SQLITE_TRANSIENT);
dan68cb86e2019-04-20 20:57:28 +00007474 }
dan42ebb012019-04-27 18:47:03 +00007475 shellFinalize(pRc, pTest);
dan68cb86e2019-04-20 20:57:28 +00007476
dan98c5ad32019-04-26 21:11:37 +00007477 pTab = (RecoverTable*)shellMalloc(pRc, sizeof(RecoverTable));
7478 if( pTab ){
drha2de66c2019-08-06 20:26:17 +00007479 pTab->zQuoted = shellMPrintf(pRc, "\"%w\"", zTab);
dan98c5ad32019-04-26 21:11:37 +00007480 pTab->nCol = nCol;
7481 pTab->iPk = -2;
7482 if( nCol>0 ){
7483 pTab->azlCol = (char**)shellMalloc(pRc, sizeof(char*) * (nCol+1));
7484 if( pTab->azlCol ){
7485 pTab->azlCol[nCol] = shellMPrintf(pRc, "");
7486 for(i=nCol-1; i>=0; i--){
7487 pTab->azlCol[i] = shellMPrintf(pRc, "%s, NULL", pTab->azlCol[i+1]);
7488 }
7489 }
danb40af492019-04-22 20:52:12 +00007490 }
dan68cb86e2019-04-20 20:57:28 +00007491
dan42ebb012019-04-27 18:47:03 +00007492 if( *pRc!=SQLITE_OK ){
7493 recoverFreeTable(pTab);
7494 pTab = 0;
7495 }else{
7496 raw_printf(pState->out,
7497 "CREATE TABLE %s(rootpgno INTEGER, "
7498 "pgno INTEGER, nfield INTEGER, id INTEGER", pTab->zQuoted
7499 );
7500 for(i=0; i<nCol; i++){
7501 raw_printf(pState->out, ", c%d", i);
7502 }
7503 raw_printf(pState->out, ");\n");
7504 }
dan98c5ad32019-04-26 21:11:37 +00007505 }
dan42ebb012019-04-27 18:47:03 +00007506 sqlite3_free(zTab);
dan68cb86e2019-04-20 20:57:28 +00007507 }
dan98c5ad32019-04-26 21:11:37 +00007508 return pTab;
dan68cb86e2019-04-20 20:57:28 +00007509}
7510
7511/*
7512** This function is called to recover data from the database. A script
7513** to construct a new database containing all recovered data is output
7514** on stream pState->out.
7515*/
danb9b71db2019-04-25 16:20:40 +00007516static int recoverDatabaseCmd(ShellState *pState, int nArg, char **azArg){
dan68cb86e2019-04-20 20:57:28 +00007517 int rc = SQLITE_OK;
7518 sqlite3_stmt *pLoop = 0; /* Loop through all root pages */
danefa363b2019-04-24 20:48:55 +00007519 sqlite3_stmt *pPages = 0; /* Loop through all pages in a group */
7520 sqlite3_stmt *pCells = 0; /* Loop through all cells in a page */
danc0b42432019-04-26 15:14:53 +00007521 const char *zRecoveryDb = ""; /* Name of "recovery" database */
dan42ebb012019-04-27 18:47:03 +00007522 const char *zLostAndFound = "lost_and_found";
dan9c014f82019-04-25 19:23:15 +00007523 int i;
dan98c5ad32019-04-26 21:11:37 +00007524 int nOrphan = -1;
7525 RecoverTable *pOrphan = 0;
dan9c014f82019-04-25 19:23:15 +00007526
7527 int bFreelist = 1; /* 0 if --freelist-corrupt is specified */
dan8cce6b82019-09-14 16:44:51 +00007528 int bRowids = 1; /* 0 if --no-rowids */
dan9c014f82019-04-25 19:23:15 +00007529 for(i=1; i<nArg; i++){
7530 char *z = azArg[i];
7531 int n;
7532 if( z[0]=='-' && z[1]=='-' ) z++;
drh4245e042019-06-13 13:52:46 +00007533 n = strlen30(z);
dan9c014f82019-04-25 19:23:15 +00007534 if( n<=17 && memcmp("-freelist-corrupt", z, n)==0 ){
7535 bFreelist = 0;
dan42ebb012019-04-27 18:47:03 +00007536 }else
danc0b42432019-04-26 15:14:53 +00007537 if( n<=12 && memcmp("-recovery-db", z, n)==0 && i<(nArg-1) ){
7538 i++;
7539 zRecoveryDb = azArg[i];
dan42ebb012019-04-27 18:47:03 +00007540 }else
7541 if( n<=15 && memcmp("-lost-and-found", z, n)==0 && i<(nArg-1) ){
7542 i++;
7543 zLostAndFound = azArg[i];
dan8cce6b82019-09-14 16:44:51 +00007544 }else
7545 if( n<=10 && memcmp("-no-rowids", z, n)==0 ){
7546 bRowids = 0;
danc0b42432019-04-26 15:14:53 +00007547 }
dan9c014f82019-04-25 19:23:15 +00007548 else{
drhe2754c12019-08-26 12:50:01 +00007549 utf8_printf(stderr, "unexpected option: %s\n", azArg[i]);
7550 showHelp(pState->out, azArg[0]);
dan9c014f82019-04-25 19:23:15 +00007551 return 1;
7552 }
7553 }
dan68cb86e2019-04-20 20:57:28 +00007554
danc0b42432019-04-26 15:14:53 +00007555 shellExecPrintf(pState->db, &rc,
dan68cb86e2019-04-20 20:57:28 +00007556 /* Attach an in-memory database named 'recovery'. Create an indexed
7557 ** cache of the sqlite_dbptr virtual table. */
dan01c08bc2019-07-24 19:20:30 +00007558 "PRAGMA writable_schema = on;"
danc0b42432019-04-26 15:14:53 +00007559 "ATTACH %Q AS recovery;"
7560 "DROP TABLE IF EXISTS recovery.dbptr;"
7561 "DROP TABLE IF EXISTS recovery.freelist;"
7562 "DROP TABLE IF EXISTS recovery.map;"
7563 "DROP TABLE IF EXISTS recovery.schema;"
danc0b42432019-04-26 15:14:53 +00007564 "CREATE TABLE recovery.freelist(pgno INTEGER PRIMARY KEY);", zRecoveryDb
dan9c014f82019-04-25 19:23:15 +00007565 );
7566
7567 if( bFreelist ){
7568 shellExec(pState->db, &rc,
7569 "WITH trunk(pgno) AS ("
7570 " SELECT shell_int32("
7571 " (SELECT data FROM sqlite_dbpage WHERE pgno=1), 8) AS x "
7572 " WHERE x>0"
7573 " UNION"
7574 " SELECT shell_int32("
7575 " (SELECT data FROM sqlite_dbpage WHERE pgno=trunk.pgno), 0) AS x "
7576 " FROM trunk WHERE x>0"
7577 "),"
7578 "freelist(data, n, freepgno) AS ("
danf6099e92019-05-09 16:57:39 +00007579 " SELECT data, min(16384, shell_int32(data, 1)-1), t.pgno "
dan9c014f82019-04-25 19:23:15 +00007580 " FROM trunk t, sqlite_dbpage s WHERE s.pgno=t.pgno"
7581 " UNION ALL"
7582 " SELECT data, n-1, shell_int32(data, 2+n) "
7583 " FROM freelist WHERE n>=0"
7584 ")"
7585 "REPLACE INTO recovery.freelist SELECT freepgno FROM freelist;"
7586 );
7587 }
7588
dan95063c22019-07-24 08:15:09 +00007589 /* If this is an auto-vacuum database, add all pointer-map pages to
7590 ** the freelist table. Do this regardless of whether or not
7591 ** --freelist-corrupt was specified. */
7592 shellExec(pState->db, &rc,
7593 "WITH ptrmap(pgno) AS ("
7594 " SELECT 2 WHERE shell_int32("
7595 " (SELECT data FROM sqlite_dbpage WHERE pgno=1), 13"
7596 " )"
7597 " UNION ALL "
7598 " SELECT pgno+1+(SELECT page_size FROM pragma_page_size)/5 AS pp "
7599 " FROM ptrmap WHERE pp<=(SELECT page_count FROM pragma_page_count)"
7600 ")"
7601 "REPLACE INTO recovery.freelist SELECT pgno FROM ptrmap"
7602 );
7603
dan9c014f82019-04-25 19:23:15 +00007604 shellExec(pState->db, &rc,
danca424382019-04-26 15:40:27 +00007605 "CREATE TABLE recovery.dbptr("
7606 " pgno, child, PRIMARY KEY(child, pgno)"
7607 ") WITHOUT ROWID;"
7608 "INSERT OR IGNORE INTO recovery.dbptr(pgno, child) "
7609 " SELECT * FROM sqlite_dbptr"
7610 " WHERE pgno NOT IN freelist AND child NOT IN freelist;"
7611
7612 /* Delete any pointer to page 1. This ensures that page 1 is considered
7613 ** a root page, regardless of how corrupt the db is. */
7614 "DELETE FROM recovery.dbptr WHERE child = 1;"
7615
7616 /* Delete all pointers to any pages that have more than one pointer
7617 ** to them. Such pages will be treated as root pages when recovering
7618 ** data. */
7619 "DELETE FROM recovery.dbptr WHERE child IN ("
7620 " SELECT child FROM recovery.dbptr GROUP BY child HAVING count(*)>1"
7621 ");"
7622
dan68cb86e2019-04-20 20:57:28 +00007623 /* Create the "map" table that will (eventually) contain instructions
7624 ** for dealing with each page in the db that contains one or more
7625 ** records. */
danb40af492019-04-22 20:52:12 +00007626 "CREATE TABLE recovery.map("
7627 "pgno INTEGER PRIMARY KEY, maxlen INT, intkey, root INT"
7628 ");"
dan68cb86e2019-04-20 20:57:28 +00007629
7630 /* Populate table [map]. If there are circular loops of pages in the
7631 ** database, the following adds all pages in such a loop to the map
7632 ** as individual root pages. This could be handled better. */
7633 "WITH pages(i, maxlen) AS ("
danb9b71db2019-04-25 16:20:40 +00007634 " SELECT page_count, ("
7635 " SELECT max(field+1) FROM sqlite_dbdata WHERE pgno=page_count"
dan13b87672019-05-09 11:45:21 +00007636 " ) FROM pragma_page_count WHERE page_count>0"
dan68cb86e2019-04-20 20:57:28 +00007637 " UNION ALL"
danb40af492019-04-22 20:52:12 +00007638 " SELECT i-1, ("
7639 " SELECT max(field+1) FROM sqlite_dbdata WHERE pgno=i-1"
7640 " ) FROM pages WHERE i>=2"
dan68cb86e2019-04-20 20:57:28 +00007641 ")"
danb40af492019-04-22 20:52:12 +00007642 "INSERT INTO recovery.map(pgno, maxlen, intkey, root) "
7643 " SELECT i, maxlen, NULL, ("
dan68cb86e2019-04-20 20:57:28 +00007644 " WITH p(orig, pgno, parent) AS ("
7645 " SELECT 0, i, (SELECT pgno FROM recovery.dbptr WHERE child=i)"
dan39e04f82019-05-09 18:33:32 +00007646 " UNION "
dan68cb86e2019-04-20 20:57:28 +00007647 " SELECT i, p.parent, "
7648 " (SELECT pgno FROM recovery.dbptr WHERE child=p.parent) FROM p"
7649 " )"
7650 " SELECT pgno FROM p WHERE (parent IS NULL OR pgno = orig)"
7651 ") "
dand790c9a2019-08-26 14:57:58 +00007652 "FROM pages WHERE maxlen IS NOT NULL AND i NOT IN freelist;"
danb40af492019-04-22 20:52:12 +00007653 "UPDATE recovery.map AS o SET intkey = ("
7654 " SELECT substr(data, 1, 1)==X'0D' FROM sqlite_dbpage WHERE pgno=o.pgno"
7655 ");"
dan68cb86e2019-04-20 20:57:28 +00007656
7657 /* Extract data from page 1 and any linked pages into table
drh067b92b2020-06-19 15:24:12 +00007658 ** recovery.schema. With the same schema as an sqlite_schema table. */
dan68cb86e2019-04-20 20:57:28 +00007659 "CREATE TABLE recovery.schema(type, name, tbl_name, rootpage, sql);"
7660 "INSERT INTO recovery.schema SELECT "
7661 " max(CASE WHEN field=0 THEN value ELSE NULL END),"
7662 " max(CASE WHEN field=1 THEN value ELSE NULL END),"
7663 " max(CASE WHEN field=2 THEN value ELSE NULL END),"
7664 " max(CASE WHEN field=3 THEN value ELSE NULL END),"
7665 " max(CASE WHEN field=4 THEN value ELSE NULL END)"
7666 "FROM sqlite_dbdata WHERE pgno IN ("
7667 " SELECT pgno FROM recovery.map WHERE root=1"
7668 ")"
7669 "GROUP BY pgno, cell;"
dan98c5ad32019-04-26 21:11:37 +00007670 "CREATE INDEX recovery.schema_rootpage ON schema(rootpage);"
dan68cb86e2019-04-20 20:57:28 +00007671 );
7672
danb40af492019-04-22 20:52:12 +00007673 /* Open a transaction, then print out all non-virtual, non-"sqlite_%"
7674 ** CREATE TABLE statements that extracted from the existing schema. */
7675 if( rc==SQLITE_OK ){
7676 sqlite3_stmt *pStmt = 0;
danf3210572019-08-06 18:40:36 +00007677 /* ".recover" might output content in an order which causes immediate
7678 ** foreign key constraints to be violated. So disable foreign-key
7679 ** constraint enforcement to prevent problems when running the output
7680 ** script. */
7681 raw_printf(pState->out, "PRAGMA foreign_keys=OFF;\n");
danb40af492019-04-22 20:52:12 +00007682 raw_printf(pState->out, "BEGIN;\n");
dan38f9c712019-04-23 18:03:02 +00007683 raw_printf(pState->out, "PRAGMA writable_schema = on;\n");
7684 shellPrepare(pState->db, &rc,
danb40af492019-04-22 20:52:12 +00007685 "SELECT sql FROM recovery.schema "
dan38f9c712019-04-23 18:03:02 +00007686 "WHERE type='table' AND sql LIKE 'create table%'", &pStmt
danb40af492019-04-22 20:52:12 +00007687 );
7688 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
7689 const char *zCreateTable = (const char*)sqlite3_column_text(pStmt, 0);
dan38f9c712019-04-23 18:03:02 +00007690 raw_printf(pState->out, "CREATE TABLE IF NOT EXISTS %s;\n",
7691 &zCreateTable[12]
7692 );
danb40af492019-04-22 20:52:12 +00007693 }
7694 shellFinalize(&rc, pStmt);
7695 }
7696
dan98c5ad32019-04-26 21:11:37 +00007697 /* Figure out if an orphan table will be required. And if so, how many
7698 ** user columns it should contain */
7699 shellPrepare(pState->db, &rc,
dan98779652019-05-09 14:15:19 +00007700 "SELECT coalesce(max(maxlen), -2) FROM recovery.map WHERE root>1"
dan98c5ad32019-04-26 21:11:37 +00007701 , &pLoop
7702 );
7703 if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pLoop) ){
7704 nOrphan = sqlite3_column_int(pLoop, 0);
7705 }
7706 shellFinalize(&rc, pLoop);
7707 pLoop = 0;
dan98c5ad32019-04-26 21:11:37 +00007708
danefa363b2019-04-24 20:48:55 +00007709 shellPrepare(pState->db, &rc,
7710 "SELECT pgno FROM recovery.map WHERE root=?", &pPages
7711 );
dan8cce6b82019-09-14 16:44:51 +00007712
danefa363b2019-04-24 20:48:55 +00007713 shellPrepare(pState->db, &rc,
dan8cce6b82019-09-14 16:44:51 +00007714 "SELECT max(field), group_concat(shell_escape_crnl(quote"
7715 "(case when (? AND field<0) then NULL else value end)"
7716 "), ', ')"
dan9443dbc2019-07-24 20:10:27 +00007717 ", min(field) "
danefa363b2019-04-24 20:48:55 +00007718 "FROM sqlite_dbdata WHERE pgno = ? AND field != ?"
7719 "GROUP BY cell", &pCells
7720 );
7721
dan68cb86e2019-04-20 20:57:28 +00007722 /* Loop through each root page. */
danb40af492019-04-22 20:52:12 +00007723 shellPrepare(pState->db, &rc,
7724 "SELECT root, intkey, max(maxlen) FROM recovery.map"
dan38f9c712019-04-23 18:03:02 +00007725 " WHERE root>1 GROUP BY root, intkey ORDER BY root=("
7726 " SELECT rootpage FROM recovery.schema WHERE name='sqlite_sequence'"
7727 ")", &pLoop
danb40af492019-04-22 20:52:12 +00007728 );
dan68cb86e2019-04-20 20:57:28 +00007729 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pLoop) ){
7730 int iRoot = sqlite3_column_int(pLoop, 0);
danb40af492019-04-22 20:52:12 +00007731 int bIntkey = sqlite3_column_int(pLoop, 1);
7732 int nCol = sqlite3_column_int(pLoop, 2);
dan98c5ad32019-04-26 21:11:37 +00007733 int bNoop = 0;
dan68cb86e2019-04-20 20:57:28 +00007734 RecoverTable *pTab;
7735
dan9443dbc2019-07-24 20:10:27 +00007736 assert( bIntkey==0 || bIntkey==1 );
dan42ebb012019-04-27 18:47:03 +00007737 pTab = recoverFindTable(pState, &rc, iRoot, bIntkey, nCol, &bNoop);
dan98c5ad32019-04-26 21:11:37 +00007738 if( bNoop || rc ) continue;
dan98779652019-05-09 14:15:19 +00007739 if( pTab==0 ){
7740 if( pOrphan==0 ){
7741 pOrphan = recoverOrphanTable(pState, &rc, zLostAndFound, nOrphan);
7742 }
7743 pTab = pOrphan;
7744 if( pTab==0 ) break;
7745 }
dan98c5ad32019-04-26 21:11:37 +00007746
drha2de66c2019-08-06 20:26:17 +00007747 if( 0==sqlite3_stricmp(pTab->zQuoted, "\"sqlite_sequence\"") ){
dan98c5ad32019-04-26 21:11:37 +00007748 raw_printf(pState->out, "DELETE FROM sqlite_sequence;\n");
7749 }
7750 sqlite3_bind_int(pPages, 1, iRoot);
dan8cce6b82019-09-14 16:44:51 +00007751 if( bRowids==0 && pTab->iPk<0 ){
7752 sqlite3_bind_int(pCells, 1, 1);
7753 }else{
7754 sqlite3_bind_int(pCells, 1, 0);
7755 }
7756 sqlite3_bind_int(pCells, 3, pTab->iPk);
dan98c5ad32019-04-26 21:11:37 +00007757
7758 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pPages) ){
7759 int iPgno = sqlite3_column_int(pPages, 0);
dan8cce6b82019-09-14 16:44:51 +00007760 sqlite3_bind_int(pCells, 2, iPgno);
dan98c5ad32019-04-26 21:11:37 +00007761 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pCells) ){
7762 int nField = sqlite3_column_int(pCells, 0);
dan9443dbc2019-07-24 20:10:27 +00007763 int iMin = sqlite3_column_int(pCells, 2);
dan98c5ad32019-04-26 21:11:37 +00007764 const char *zVal = (const char*)sqlite3_column_text(pCells, 1);
7765
dan9443dbc2019-07-24 20:10:27 +00007766 RecoverTable *pTab2 = pTab;
7767 if( pTab!=pOrphan && (iMin<0)!=bIntkey ){
7768 if( pOrphan==0 ){
7769 pOrphan = recoverOrphanTable(pState, &rc, zLostAndFound, nOrphan);
7770 }
7771 pTab2 = pOrphan;
7772 if( pTab2==0 ) break;
7773 }
7774
dan98c5ad32019-04-26 21:11:37 +00007775 nField = nField+1;
dan9443dbc2019-07-24 20:10:27 +00007776 if( pTab2==pOrphan ){
dan98c5ad32019-04-26 21:11:37 +00007777 raw_printf(pState->out,
7778 "INSERT INTO %s VALUES(%d, %d, %d, %s%s%s);\n",
dan9443dbc2019-07-24 20:10:27 +00007779 pTab2->zQuoted, iRoot, iPgno, nField,
7780 iMin<0 ? "" : "NULL, ", zVal, pTab2->azlCol[nField]
dan98c5ad32019-04-26 21:11:37 +00007781 );
7782 }else{
danefa363b2019-04-24 20:48:55 +00007783 raw_printf(pState->out, "INSERT INTO %s(%s) VALUES( %s );\n",
dan9443dbc2019-07-24 20:10:27 +00007784 pTab2->zQuoted, pTab2->azlCol[nField], zVal
danefa363b2019-04-24 20:48:55 +00007785 );
7786 }
dan68cb86e2019-04-20 20:57:28 +00007787 }
dan98c5ad32019-04-26 21:11:37 +00007788 shellReset(&rc, pCells);
dan68cb86e2019-04-20 20:57:28 +00007789 }
dan98c5ad32019-04-26 21:11:37 +00007790 shellReset(&rc, pPages);
7791 if( pTab!=pOrphan ) recoverFreeTable(pTab);
dan68cb86e2019-04-20 20:57:28 +00007792 }
7793 shellFinalize(&rc, pLoop);
danefa363b2019-04-24 20:48:55 +00007794 shellFinalize(&rc, pPages);
7795 shellFinalize(&rc, pCells);
dan98c5ad32019-04-26 21:11:37 +00007796 recoverFreeTable(pOrphan);
dan68cb86e2019-04-20 20:57:28 +00007797
dan38f9c712019-04-23 18:03:02 +00007798 /* The rest of the schema */
danb40af492019-04-22 20:52:12 +00007799 if( rc==SQLITE_OK ){
dan38f9c712019-04-23 18:03:02 +00007800 sqlite3_stmt *pStmt = 0;
7801 shellPrepare(pState->db, &rc,
7802 "SELECT sql, name FROM recovery.schema "
danb1825882019-04-23 20:48:32 +00007803 "WHERE sql NOT LIKE 'create table%'", &pStmt
dan38f9c712019-04-23 18:03:02 +00007804 );
7805 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
7806 const char *zSql = (const char*)sqlite3_column_text(pStmt, 0);
7807 if( sqlite3_strnicmp(zSql, "create virt", 11)==0 ){
7808 const char *zName = (const char*)sqlite3_column_text(pStmt, 1);
7809 char *zPrint = shellMPrintf(&rc,
drh067b92b2020-06-19 15:24:12 +00007810 "INSERT INTO sqlite_schema VALUES('table', %Q, %Q, 0, %Q)",
dan38f9c712019-04-23 18:03:02 +00007811 zName, zName, zSql
7812 );
7813 raw_printf(pState->out, "%s;\n", zPrint);
7814 sqlite3_free(zPrint);
7815 }else{
7816 raw_printf(pState->out, "%s;\n", zSql);
7817 }
7818 }
7819 shellFinalize(&rc, pStmt);
7820 }
7821
7822 if( rc==SQLITE_OK ){
7823 raw_printf(pState->out, "PRAGMA writable_schema = off;\n");
danb40af492019-04-22 20:52:12 +00007824 raw_printf(pState->out, "COMMIT;\n");
7825 }
dan68cb86e2019-04-20 20:57:28 +00007826 sqlite3_exec(pState->db, "DETACH recovery", 0, 0, 0);
7827 return rc;
7828}
dan1b162162019-04-27 20:15:15 +00007829#endif /* !(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB) */
dan68cb86e2019-04-20 20:57:28 +00007830
larrybr42de1c52022-02-13 22:18:22 +00007831
7832/*
7833 * zAutoColumn(zCol, &db, ?) => Maybe init db, add column zCol to it.
7834 * zAutoColumn(0, &db, ?) => (db!=0) Form columns spec for CREATE TABLE,
7835 * close db and set it to 0, and return the columns spec, to later
7836 * be sqlite3_free()'ed by the caller.
7837 * The return is 0 when either:
7838 * (a) The db was not initialized and zCol==0 (There are no columns.)
7839 * (b) zCol!=0 (Column was added, db initialized as needed.)
7840 * The 3rd argument, pRenamed, references an out parameter. If the
larrybr33633862022-02-14 01:12:46 +00007841 * pointer is non-zero, its referent will be set to a summary of renames
7842 * done if renaming was necessary, or set to 0 if none was done. The out
7843 * string (if any) must be sqlite3_free()'ed by the caller.
larrybr42de1c52022-02-13 22:18:22 +00007844 */
7845#ifdef SHELL_DEBUG
7846#define rc_err_oom_die(rc) \
7847 if( rc==SQLITE_NOMEM ) shell_check_oom(0); \
7848 else if(!(rc==SQLITE_OK||rc==SQLITE_DONE)) \
7849 fprintf(stderr,"E:%d\n",rc), assert(0)
7850#else
7851static void rc_err_oom_die(int rc){
7852 if( rc==SQLITE_NOMEM ) shell_check_oom(0);
7853 assert(rc==SQLITE_OK||rc==SQLITE_DONE);
7854}
7855#endif
7856
7857#ifdef SHELL_COLFIX_DB /* If this is set, the DB can be in a file. */
7858static char zCOL_DB[] = SHELL_STRINGIFY(SHELL_COLFIX_DB);
7859#else /* Otherwise, memory is faster/better for the transient DB. */
7860static const char *zCOL_DB = ":memory:";
7861#endif
7862
7863/* Define character (as C string) to separate generated column ordinal
7864 * from protected part of incoming column names. This defaults to "_"
7865 * so that incoming column identifiers that did not need not be quoted
7866 * remain usable without being quoted. It must be one character.
7867 */
7868#ifndef SHELL_AUTOCOLUMN_SEP
7869# define AUTOCOLUMN_SEP "_"
7870#else
7871# define AUTOCOLUMN_SEP SHELL_STRINGIFY(SHELL_AUTOCOLUMN_SEP)
7872#endif
7873
larrybr33633862022-02-14 01:12:46 +00007874static char *zAutoColumn(const char *zColNew, sqlite3 **pDb, char **pzRenamed){
larrybr42de1c52022-02-13 22:18:22 +00007875 /* Queries and D{D,M}L used here */
7876 static const char * const zTabMake = "\
7877CREATE TABLE ColNames(\
7878 cpos INTEGER PRIMARY KEY,\
larrybr33633862022-02-14 01:12:46 +00007879 name TEXT, nlen INT, chop INT, reps INT, suff TEXT);\
7880CREATE VIEW RepeatedNames AS \
7881SELECT DISTINCT t.name FROM ColNames t \
7882WHERE t.name COLLATE NOCASE IN (\
7883 SELECT o.name FROM ColNames o WHERE o.cpos<>t.cpos\
7884);\
larrybr42de1c52022-02-13 22:18:22 +00007885";
7886 static const char * const zTabFill = "\
7887INSERT INTO ColNames(name,nlen,chop,reps,suff)\
7888 VALUES(iif(length(?1)>0,?1,'?'),max(length(?1),1),0,0,'')\
7889";
7890 static const char * const zHasDupes = "\
7891SELECT count(DISTINCT (substring(name,1,nlen-chop)||suff) COLLATE NOCASE)\
7892 <count(name) FROM ColNames\
7893";
larrybr33633862022-02-14 01:12:46 +00007894#ifdef SHELL_COLUMN_RENAME_CLEAN
larrybr42de1c52022-02-13 22:18:22 +00007895 static const char * const zDedoctor = "\
7896UPDATE ColNames SET chop=iif(\
7897 (substring(name,nlen,1) BETWEEN '0' AND '9')\
7898 AND (rtrim(name,'0123456790') glob '*"AUTOCOLUMN_SEP"'),\
7899 nlen-length(rtrim(name, '"AUTOCOLUMN_SEP"0123456789')),\
7900 0\
7901)\
7902";
larrybr33633862022-02-14 01:12:46 +00007903#endif
larrybr42de1c52022-02-13 22:18:22 +00007904 static const char * const zSetReps = "\
7905UPDATE ColNames AS t SET reps=\
7906(SELECT count(*) FROM ColNames d \
7907 WHERE substring(t.name,1,t.nlen-t.chop)=substring(d.name,1,d.nlen-d.chop)\
7908 COLLATE NOCASE\
7909)\
7910";
7911#ifdef SQLITE_ENABLE_MATH_FUNCTIONS
7912 static const char * const zColDigits = "\
7913SELECT CAST(ceil(log(count(*)+0.5)) AS INT) FROM ColNames \
7914";
7915#endif
7916 static const char * const zRenameRank =
larrybr33633862022-02-14 01:12:46 +00007917#ifdef SHELL_COLUMN_RENAME_CLEAN
larrybr42de1c52022-02-13 22:18:22 +00007918 "UPDATE ColNames AS t SET suff="
7919 "iif(reps>1, printf('%c%0*d', '"AUTOCOLUMN_SEP"', $1, cpos), '')"
larrybr33633862022-02-14 01:12:46 +00007920#else /* ...RENAME_MINIMAL_ONE_PASS */
7921"WITH Lzn(nlz) AS (" /* Find minimum extraneous leading 0's for uniqueness */
7922" SELECT 0 AS nlz"
7923" UNION"
7924" SELECT nlz+1 AS nlz FROM Lzn"
7925" WHERE EXISTS("
7926" SELECT 1"
7927" FROM ColNames t, ColNames o"
7928" WHERE"
7929" iif(t.name IN (SELECT * FROM RepeatedNames),"
7930" printf('%s"AUTOCOLUMN_SEP"%s',"
7931" t.name, substring(printf('%.*c%0.*d',nlz+1,'0',$1,t.cpos),2)),"
7932" t.name"
7933" )"
7934" ="
7935" iif(o.name IN (SELECT * FROM RepeatedNames),"
7936" printf('%s"AUTOCOLUMN_SEP"%s',"
7937" o.name, substring(printf('%.*c%0.*d',nlz+1,'0',$1,o.cpos),2)),"
7938" o.name"
7939" )"
7940" COLLATE NOCASE"
7941" AND o.cpos<>t.cpos"
7942" GROUP BY t.cpos"
7943" )"
7944") UPDATE Colnames AS t SET"
7945" chop = 0," /* No chopping, never touch incoming names. */
7946" suff = iif(name IN (SELECT * FROM RepeatedNames),"
7947" printf('"AUTOCOLUMN_SEP"%s', substring("
7948" printf('%.*c%0.*d',(SELECT max(nlz) FROM Lzn)+1,'0',1,t.cpos),2)),"
7949" ''"
7950" )"
larrybr42de1c52022-02-13 22:18:22 +00007951#endif
7952 ;
7953 static const char * const zCollectVar = "\
7954SELECT\
7955 '('||x'0a'\
7956 || group_concat(\
7957 cname||' TEXT',\
7958 ','||iif((cpos-1)%4>0, ' ', x'0a'||' '))\
7959 ||')' AS ColsSpec \
7960FROM (\
7961 SELECT cpos, printf('\"%w\"',printf('%.*s%s', nlen-chop,name,suff)) AS cname \
7962 FROM ColNames ORDER BY cpos\
7963)";
larrybr33633862022-02-14 01:12:46 +00007964 static const char * const zRenamesDone =
7965 "SELECT group_concat("
7966 " printf('\"%w\" to \"%w\"',name,printf('%.*s%s', nlen-chop, name, suff)),"
7967 " ','||x'0a')"
7968 "FROM ColNames WHERE suff<>'' OR chop!=0"
7969 ;
larrybr42de1c52022-02-13 22:18:22 +00007970 int rc;
7971 sqlite3_stmt *pStmt = 0;
7972 assert(pDb!=0);
7973 if( zColNew ){
7974 /* Add initial or additional column. Init db if necessary. */
7975 if( *pDb==0 ){
7976 if( SQLITE_OK!=sqlite3_open(zCOL_DB, pDb) ) return 0;
7977#ifdef SHELL_COLFIX_DB
7978 if(*zCOL_DB!=':')
larrybr33633862022-02-14 01:12:46 +00007979 sqlite3_exec(*pDb,"drop table if exists ColNames;"
7980 "drop view if exists RepeatedNames;",0,0,0);
larrybr42de1c52022-02-13 22:18:22 +00007981#endif
7982 rc = sqlite3_exec(*pDb, zTabMake, 0, 0, 0);
7983 rc_err_oom_die(rc);
7984 }
7985 assert(*pDb!=0);
7986 rc = sqlite3_prepare_v2(*pDb, zTabFill, -1, &pStmt, 0);
7987 rc_err_oom_die(rc);
7988 rc = sqlite3_bind_text(pStmt, 1, zColNew, -1, 0);
7989 rc_err_oom_die(rc);
7990 rc = sqlite3_step(pStmt);
7991 rc_err_oom_die(rc);
7992 sqlite3_finalize(pStmt);
7993 return 0;
7994 }else if( *pDb==0 ){
7995 return 0;
7996 }else{
7997 /* Formulate the columns spec, close the DB, zero *pDb. */
7998 char *zColsSpec = 0;
7999 int hasDupes = db_int(*pDb, zHasDupes);
8000#ifdef SQLITE_ENABLE_MATH_FUNCTIONS
8001 int nDigits = (hasDupes)? db_int(*pDb, zColDigits) : 0;
8002#else
8003# define nDigits 2
8004#endif
8005 if( hasDupes ){
larrybr33633862022-02-14 01:12:46 +00008006#ifdef SHELL_COLUMN_RENAME_CLEAN
larrybr42de1c52022-02-13 22:18:22 +00008007 rc = sqlite3_exec(*pDb, zDedoctor, 0, 0, 0);
8008 rc_err_oom_die(rc);
larrybr33633862022-02-14 01:12:46 +00008009#endif
larrybr42de1c52022-02-13 22:18:22 +00008010 rc = sqlite3_exec(*pDb, zSetReps, 0, 0, 0);
8011 rc_err_oom_die(rc);
8012 rc = sqlite3_prepare_v2(*pDb, zRenameRank, -1, &pStmt, 0);
8013 rc_err_oom_die(rc);
8014 sqlite3_bind_int(pStmt, 1, nDigits);
8015 rc = sqlite3_step(pStmt);
8016 sqlite3_finalize(pStmt);
8017 assert(rc==SQLITE_DONE);
8018 }
8019 assert(db_int(*pDb, zHasDupes)==0); /* Consider: remove this */
8020 rc = sqlite3_prepare_v2(*pDb, zCollectVar, -1, &pStmt, 0);
8021 rc_err_oom_die(rc);
8022 rc = sqlite3_step(pStmt);
8023 if( rc==SQLITE_ROW ){
8024 zColsSpec = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 0));
8025 }else{
8026 zColsSpec = 0;
8027 }
larrybr33633862022-02-14 01:12:46 +00008028 if( pzRenamed!=0 ){
8029 if( !hasDupes ) *pzRenamed = 0;
8030 else{
8031 sqlite3_finalize(pStmt);
8032 if( SQLITE_OK==sqlite3_prepare_v2(*pDb, zRenamesDone, -1, &pStmt, 0)
8033 && SQLITE_ROW==sqlite3_step(pStmt) ){
8034 *pzRenamed = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 0));
8035 }else
8036 *pzRenamed = 0;
8037 }
8038 }
larrybr42de1c52022-02-13 22:18:22 +00008039 sqlite3_finalize(pStmt);
8040 sqlite3_close(*pDb);
8041 *pDb = 0;
8042 return zColsSpec;
8043 }
8044}
8045
drh2ce15c32017-07-11 13:34:40 +00008046/*
8047** If an input line begins with "." then invoke this routine to
8048** process that line.
8049**
8050** Return 1 on error, 2 to exit, and 0 otherwise.
8051*/
8052static int do_meta_command(char *zLine, ShellState *p){
8053 int h = 1;
8054 int nArg = 0;
8055 int n, c;
8056 int rc = 0;
drh5df84282019-08-17 19:45:25 +00008057 char *azArg[52];
drh2ce15c32017-07-11 13:34:40 +00008058
dan6b046be2018-01-09 15:25:55 +00008059#ifndef SQLITE_OMIT_VIRTUALTABLE
dan43efc182017-12-19 17:42:13 +00008060 if( p->expert.pExpert ){
8061 expertFinish(p, 1, 0);
8062 }
dan6b046be2018-01-09 15:25:55 +00008063#endif
dan43efc182017-12-19 17:42:13 +00008064
drh2ce15c32017-07-11 13:34:40 +00008065 /* Parse the input line into tokens.
8066 */
drh5df84282019-08-17 19:45:25 +00008067 while( zLine[h] && nArg<ArraySize(azArg)-1 ){
drh2ce15c32017-07-11 13:34:40 +00008068 while( IsSpace(zLine[h]) ){ h++; }
8069 if( zLine[h]==0 ) break;
8070 if( zLine[h]=='\'' || zLine[h]=='"' ){
8071 int delim = zLine[h++];
8072 azArg[nArg++] = &zLine[h];
8073 while( zLine[h] && zLine[h]!=delim ){
8074 if( zLine[h]=='\\' && delim=='"' && zLine[h+1]!=0 ) h++;
8075 h++;
8076 }
8077 if( zLine[h]==delim ){
8078 zLine[h++] = 0;
8079 }
8080 if( delim=='"' ) resolve_backslashes(azArg[nArg-1]);
8081 }else{
8082 azArg[nArg++] = &zLine[h];
8083 while( zLine[h] && !IsSpace(zLine[h]) ){ h++; }
8084 if( zLine[h] ) zLine[h++] = 0;
8085 resolve_backslashes(azArg[nArg-1]);
8086 }
8087 }
drh5df84282019-08-17 19:45:25 +00008088 azArg[nArg] = 0;
drh2ce15c32017-07-11 13:34:40 +00008089
8090 /* Process the input line.
8091 */
8092 if( nArg==0 ) return 0; /* no tokens, no error */
8093 n = strlen30(azArg[0]);
8094 c = azArg[0][0];
drh13c20932018-01-10 21:41:55 +00008095 clearTempFile(p);
drh2ce15c32017-07-11 13:34:40 +00008096
8097#ifndef SQLITE_OMIT_AUTHORIZATION
8098 if( c=='a' && strncmp(azArg[0], "auth", n)==0 ){
8099 if( nArg!=2 ){
8100 raw_printf(stderr, "Usage: .auth ON|OFF\n");
8101 rc = 1;
8102 goto meta_command_exit;
8103 }
8104 open_db(p, 0);
8105 if( booleanValue(azArg[1]) ){
8106 sqlite3_set_authorizer(p->db, shellAuth, p);
drhb97e2ad2021-08-26 18:31:39 +00008107 }else if( p->bSafeModePersist ){
8108 sqlite3_set_authorizer(p->db, safeModeAuth, p);
drh2ce15c32017-07-11 13:34:40 +00008109 }else{
8110 sqlite3_set_authorizer(p->db, 0, 0);
8111 }
8112 }else
8113#endif
8114
drhe37c0e12018-01-06 19:19:50 +00008115#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
8116 if( c=='a' && strncmp(azArg[0], "archive", n)==0 ){
danfd0245d2017-12-07 15:44:29 +00008117 open_db(p, 0);
drhb97e2ad2021-08-26 18:31:39 +00008118 failIfSafeMode(p, "cannot run .archive in safe mode");
drhd0f9cdc2018-05-17 14:09:06 +00008119 rc = arDotCommand(p, 0, azArg, nArg);
danfd0245d2017-12-07 15:44:29 +00008120 }else
8121#endif
8122
drh2ce15c32017-07-11 13:34:40 +00008123 if( (c=='b' && n>=3 && strncmp(azArg[0], "backup", n)==0)
8124 || (c=='s' && n>=3 && strncmp(azArg[0], "save", n)==0)
8125 ){
8126 const char *zDestFile = 0;
8127 const char *zDb = 0;
8128 sqlite3 *pDest;
8129 sqlite3_backup *pBackup;
8130 int j;
drha50bffb2018-12-08 01:09:14 +00008131 int bAsync = 0;
drh69ed38a2018-05-14 00:23:08 +00008132 const char *zVfs = 0;
drhb97e2ad2021-08-26 18:31:39 +00008133 failIfSafeMode(p, "cannot run .%s in safe mode", azArg[0]);
drh2ce15c32017-07-11 13:34:40 +00008134 for(j=1; j<nArg; j++){
8135 const char *z = azArg[j];
8136 if( z[0]=='-' ){
drh69ed38a2018-05-14 00:23:08 +00008137 if( z[1]=='-' ) z++;
8138 if( strcmp(z, "-append")==0 ){
8139 zVfs = "apndvfs";
8140 }else
drha50bffb2018-12-08 01:09:14 +00008141 if( strcmp(z, "-async")==0 ){
8142 bAsync = 1;
8143 }else
drh2ce15c32017-07-11 13:34:40 +00008144 {
8145 utf8_printf(stderr, "unknown option: %s\n", azArg[j]);
8146 return 1;
8147 }
8148 }else if( zDestFile==0 ){
8149 zDestFile = azArg[j];
8150 }else if( zDb==0 ){
8151 zDb = zDestFile;
8152 zDestFile = azArg[j];
8153 }else{
drha50bffb2018-12-08 01:09:14 +00008154 raw_printf(stderr, "Usage: .backup ?DB? ?OPTIONS? FILENAME\n");
drh2ce15c32017-07-11 13:34:40 +00008155 return 1;
8156 }
8157 }
8158 if( zDestFile==0 ){
8159 raw_printf(stderr, "missing FILENAME argument on .backup\n");
8160 return 1;
8161 }
8162 if( zDb==0 ) zDb = "main";
drh69ed38a2018-05-14 00:23:08 +00008163 rc = sqlite3_open_v2(zDestFile, &pDest,
8164 SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE, zVfs);
drh2ce15c32017-07-11 13:34:40 +00008165 if( rc!=SQLITE_OK ){
8166 utf8_printf(stderr, "Error: cannot open \"%s\"\n", zDestFile);
drh9e804032018-05-18 17:11:50 +00008167 close_db(pDest);
drh2ce15c32017-07-11 13:34:40 +00008168 return 1;
8169 }
drha50bffb2018-12-08 01:09:14 +00008170 if( bAsync ){
8171 sqlite3_exec(pDest, "PRAGMA synchronous=OFF; PRAGMA journal_mode=OFF;",
8172 0, 0, 0);
8173 }
drh2ce15c32017-07-11 13:34:40 +00008174 open_db(p, 0);
8175 pBackup = sqlite3_backup_init(pDest, "main", p->db, zDb);
8176 if( pBackup==0 ){
8177 utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(pDest));
drh9e804032018-05-18 17:11:50 +00008178 close_db(pDest);
drh2ce15c32017-07-11 13:34:40 +00008179 return 1;
8180 }
8181 while( (rc = sqlite3_backup_step(pBackup,100))==SQLITE_OK ){}
8182 sqlite3_backup_finish(pBackup);
8183 if( rc==SQLITE_DONE ){
8184 rc = 0;
8185 }else{
8186 utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(pDest));
8187 rc = 1;
8188 }
drh9e804032018-05-18 17:11:50 +00008189 close_db(pDest);
drh2ce15c32017-07-11 13:34:40 +00008190 }else
8191
8192 if( c=='b' && n>=3 && strncmp(azArg[0], "bail", n)==0 ){
8193 if( nArg==2 ){
8194 bail_on_error = booleanValue(azArg[1]);
8195 }else{
8196 raw_printf(stderr, "Usage: .bail on|off\n");
8197 rc = 1;
8198 }
8199 }else
8200
8201 if( c=='b' && n>=3 && strncmp(azArg[0], "binary", n)==0 ){
8202 if( nArg==2 ){
8203 if( booleanValue(azArg[1]) ){
8204 setBinaryMode(p->out, 1);
8205 }else{
8206 setTextMode(p->out, 1);
8207 }
8208 }else{
8209 raw_printf(stderr, "Usage: .binary on|off\n");
8210 rc = 1;
8211 }
8212 }else
8213
drh37407122021-07-23 18:43:58 +00008214 /* The undocumented ".breakpoint" command causes a call to the no-op
8215 ** routine named test_breakpoint().
8216 */
8217 if( c=='b' && n>=3 && strncmp(azArg[0], "breakpoint", n)==0 ){
8218 test_breakpoint();
8219 }else
8220
drh2ce15c32017-07-11 13:34:40 +00008221 if( c=='c' && strcmp(azArg[0],"cd")==0 ){
drhb97e2ad2021-08-26 18:31:39 +00008222 failIfSafeMode(p, "cannot run .cd in safe mode");
drh2ce15c32017-07-11 13:34:40 +00008223 if( nArg==2 ){
8224#if defined(_WIN32) || defined(WIN32)
8225 wchar_t *z = sqlite3_win32_utf8_to_unicode(azArg[1]);
8226 rc = !SetCurrentDirectoryW(z);
8227 sqlite3_free(z);
8228#else
8229 rc = chdir(azArg[1]);
8230#endif
8231 if( rc ){
8232 utf8_printf(stderr, "Cannot change to directory \"%s\"\n", azArg[1]);
8233 rc = 1;
8234 }
8235 }else{
8236 raw_printf(stderr, "Usage: .cd DIRECTORY\n");
8237 rc = 1;
8238 }
8239 }else
8240
drh2ce15c32017-07-11 13:34:40 +00008241 if( c=='c' && n>=3 && strncmp(azArg[0], "changes", n)==0 ){
8242 if( nArg==2 ){
8243 setOrClearFlag(p, SHFLG_CountChanges, azArg[1]);
8244 }else{
8245 raw_printf(stderr, "Usage: .changes on|off\n");
8246 rc = 1;
8247 }
8248 }else
8249
8250 /* Cancel output redirection, if it is currently set (by .testcase)
8251 ** Then read the content of the testcase-out.txt file and compare against
8252 ** azArg[1]. If there are differences, report an error and exit.
8253 */
8254 if( c=='c' && n>=3 && strncmp(azArg[0], "check", n)==0 ){
8255 char *zRes = 0;
8256 output_reset(p);
8257 if( nArg!=2 ){
8258 raw_printf(stderr, "Usage: .check GLOB-PATTERN\n");
8259 rc = 2;
8260 }else if( (zRes = readFile("testcase-out.txt", 0))==0 ){
8261 raw_printf(stderr, "Error: cannot read 'testcase-out.txt'\n");
8262 rc = 2;
8263 }else if( testcase_glob(azArg[1],zRes)==0 ){
8264 utf8_printf(stderr,
8265 "testcase-%s FAILED\n Expected: [%s]\n Got: [%s]\n",
8266 p->zTestcase, azArg[1], zRes);
drhf30d3452017-10-17 13:44:46 +00008267 rc = 1;
drh2ce15c32017-07-11 13:34:40 +00008268 }else{
8269 utf8_printf(stdout, "testcase-%s ok\n", p->zTestcase);
8270 p->nCheck++;
8271 }
8272 sqlite3_free(zRes);
8273 }else
8274
8275 if( c=='c' && strncmp(azArg[0], "clone", n)==0 ){
drhb97e2ad2021-08-26 18:31:39 +00008276 failIfSafeMode(p, "cannot run .clone in safe mode");
drh2ce15c32017-07-11 13:34:40 +00008277 if( nArg==2 ){
8278 tryToClone(p, azArg[1]);
8279 }else{
8280 raw_printf(stderr, "Usage: .clone FILENAME\n");
8281 rc = 1;
8282 }
8283 }else
8284
drh37407122021-07-23 18:43:58 +00008285 if( c=='c' && strncmp(azArg[0], "connection", n)==0 ){
8286 if( nArg==1 ){
8287 /* List available connections */
8288 int i;
8289 for(i=0; i<ArraySize(p->aAuxDb); i++){
8290 const char *zFile = p->aAuxDb[i].zDbFilename;
8291 if( p->aAuxDb[i].db==0 && p->pAuxDb!=&p->aAuxDb[i] ){
8292 zFile = "(not open)";
8293 }else if( zFile==0 ){
8294 zFile = "(memory)";
8295 }else if( zFile[0]==0 ){
8296 zFile = "(temporary-file)";
8297 }
8298 if( p->pAuxDb == &p->aAuxDb[i] ){
8299 utf8_printf(stdout, "ACTIVE %d: %s\n", i, zFile);
8300 }else if( p->aAuxDb[i].db!=0 ){
8301 utf8_printf(stdout, " %d: %s\n", i, zFile);
8302 }
8303 }
8304 }else if( nArg==2 && IsDigit(azArg[1][0]) && azArg[1][1]==0 ){
8305 int i = azArg[1][0] - '0';
8306 if( p->pAuxDb != &p->aAuxDb[i] && i>=0 && i<ArraySize(p->aAuxDb) ){
8307 p->pAuxDb->db = p->db;
8308 p->pAuxDb = &p->aAuxDb[i];
8309 globalDb = p->db = p->pAuxDb->db;
8310 p->pAuxDb->db = 0;
8311 }
8312 }else if( nArg==3 && strcmp(azArg[1], "close")==0
8313 && IsDigit(azArg[2][0]) && azArg[2][1]==0 ){
8314 int i = azArg[2][0] - '0';
8315 if( i<0 || i>=ArraySize(p->aAuxDb) ){
8316 /* No-op */
8317 }else if( p->pAuxDb == &p->aAuxDb[i] ){
8318 raw_printf(stderr, "cannot close the active database connection\n");
8319 rc = 1;
8320 }else if( p->aAuxDb[i].db ){
8321 session_close_all(p, i);
8322 close_db(p->aAuxDb[i].db);
8323 p->aAuxDb[i].db = 0;
8324 }
8325 }else{
8326 raw_printf(stderr, "Usage: .connection [close] [CONNECTION-NUMBER]\n");
8327 rc = 1;
8328 }
8329 }else
8330
drh2ce15c32017-07-11 13:34:40 +00008331 if( c=='d' && n>1 && strncmp(azArg[0], "databases", n)==0 ){
drh60081a02020-08-26 19:07:18 +00008332 char **azName = 0;
8333 int nName = 0;
8334 sqlite3_stmt *pStmt;
drh60081a02020-08-26 19:07:18 +00008335 int i;
drh2ce15c32017-07-11 13:34:40 +00008336 open_db(p, 0);
drh60081a02020-08-26 19:07:18 +00008337 rc = sqlite3_prepare_v2(p->db, "PRAGMA database_list", -1, &pStmt, 0);
8338 if( rc ){
8339 utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
drh2ce15c32017-07-11 13:34:40 +00008340 rc = 1;
drh60081a02020-08-26 19:07:18 +00008341 }else{
8342 while( sqlite3_step(pStmt)==SQLITE_ROW ){
8343 const char *zSchema = (const char *)sqlite3_column_text(pStmt,1);
8344 const char *zFile = (const char*)sqlite3_column_text(pStmt,2);
drh621a5e02021-12-16 17:35:27 +00008345 if( zSchema==0 || zFile==0 ) continue;
drh60081a02020-08-26 19:07:18 +00008346 azName = sqlite3_realloc(azName, (nName+1)*2*sizeof(char*));
drhe3e25652021-12-16 13:29:28 +00008347 shell_check_oom(azName);
drh60081a02020-08-26 19:07:18 +00008348 azName[nName*2] = strdup(zSchema);
8349 azName[nName*2+1] = strdup(zFile);
8350 nName++;
8351 }
drh2ce15c32017-07-11 13:34:40 +00008352 }
drh60081a02020-08-26 19:07:18 +00008353 sqlite3_finalize(pStmt);
8354 for(i=0; i<nName; i++){
8355 int eTxn = sqlite3_txn_state(p->db, azName[i*2]);
8356 int bRdonly = sqlite3_db_readonly(p->db, azName[i*2]);
8357 const char *z = azName[i*2+1];
8358 utf8_printf(p->out, "%s: %s %s%s\n",
8359 azName[i*2],
8360 z && z[0] ? z : "\"\"",
8361 bRdonly ? "r/o" : "r/w",
8362 eTxn==SQLITE_TXN_NONE ? "" :
8363 eTxn==SQLITE_TXN_READ ? " read-txn" : " write-txn");
8364 free(azName[i*2]);
8365 free(azName[i*2+1]);
8366 }
8367 sqlite3_free(azName);
drh2ce15c32017-07-11 13:34:40 +00008368 }else
8369
drh7df01192018-04-28 12:43:16 +00008370 if( c=='d' && n>=3 && strncmp(azArg[0], "dbconfig", n)==0 ){
drheb7f2a02018-09-26 18:02:32 +00008371 static const struct DbConfigChoices {
8372 const char *zName;
8373 int op;
8374 } aDbConfig[] = {
drhb945bcd2019-12-31 22:52:10 +00008375 { "defensive", SQLITE_DBCONFIG_DEFENSIVE },
8376 { "dqs_ddl", SQLITE_DBCONFIG_DQS_DDL },
8377 { "dqs_dml", SQLITE_DBCONFIG_DQS_DML },
drh0a6873b2019-06-14 21:25:25 +00008378 { "enable_fkey", SQLITE_DBCONFIG_ENABLE_FKEY },
drhb945bcd2019-12-31 22:52:10 +00008379 { "enable_qpsg", SQLITE_DBCONFIG_ENABLE_QPSG },
drh0a6873b2019-06-14 21:25:25 +00008380 { "enable_trigger", SQLITE_DBCONFIG_ENABLE_TRIGGER },
drh11d88e62019-08-15 21:27:20 +00008381 { "enable_view", SQLITE_DBCONFIG_ENABLE_VIEW },
drh0a6873b2019-06-14 21:25:25 +00008382 { "fts3_tokenizer", SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER },
drhb945bcd2019-12-31 22:52:10 +00008383 { "legacy_alter_table", SQLITE_DBCONFIG_LEGACY_ALTER_TABLE },
8384 { "legacy_file_format", SQLITE_DBCONFIG_LEGACY_FILE_FORMAT },
drh0a6873b2019-06-14 21:25:25 +00008385 { "load_extension", SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION },
8386 { "no_ckpt_on_close", SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE },
drh0a6873b2019-06-14 21:25:25 +00008387 { "reset_database", SQLITE_DBCONFIG_RESET_DATABASE },
drhb945bcd2019-12-31 22:52:10 +00008388 { "trigger_eqp", SQLITE_DBCONFIG_TRIGGER_EQP },
drhb77da372020-01-07 16:09:11 +00008389 { "trusted_schema", SQLITE_DBCONFIG_TRUSTED_SCHEMA },
dan07312a62019-06-21 14:05:27 +00008390 { "writable_schema", SQLITE_DBCONFIG_WRITABLE_SCHEMA },
drh7df01192018-04-28 12:43:16 +00008391 };
8392 int ii, v;
8393 open_db(p, 0);
8394 for(ii=0; ii<ArraySize(aDbConfig); ii++){
8395 if( nArg>1 && strcmp(azArg[1], aDbConfig[ii].zName)!=0 ) continue;
8396 if( nArg>=3 ){
8397 sqlite3_db_config(p->db, aDbConfig[ii].op, booleanValue(azArg[2]), 0);
8398 }
8399 sqlite3_db_config(p->db, aDbConfig[ii].op, -1, &v);
drhb945bcd2019-12-31 22:52:10 +00008400 utf8_printf(p->out, "%19s %s\n", aDbConfig[ii].zName, v ? "on" : "off");
drh7df01192018-04-28 12:43:16 +00008401 if( nArg>1 ) break;
8402 }
8403 if( nArg>1 && ii==ArraySize(aDbConfig) ){
8404 utf8_printf(stderr, "Error: unknown dbconfig \"%s\"\n", azArg[1]);
8405 utf8_printf(stderr, "Enter \".dbconfig\" with no arguments for a list\n");
8406 }
8407 }else
8408
8409 if( c=='d' && n>=3 && strncmp(azArg[0], "dbinfo", n)==0 ){
drh2ce15c32017-07-11 13:34:40 +00008410 rc = shell_dbinfo_command(p, nArg, azArg);
8411 }else
8412
dan1b162162019-04-27 20:15:15 +00008413#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
dan68cb86e2019-04-20 20:57:28 +00008414 if( c=='r' && strncmp(azArg[0], "recover", n)==0 ){
8415 open_db(p, 0);
danb9b71db2019-04-25 16:20:40 +00008416 rc = recoverDatabaseCmd(p, nArg, azArg);
dan68cb86e2019-04-20 20:57:28 +00008417 }else
dan1b162162019-04-27 20:15:15 +00008418#endif /* !(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB) */
dan68cb86e2019-04-20 20:57:28 +00008419
drh2ce15c32017-07-11 13:34:40 +00008420 if( c=='d' && strncmp(azArg[0], "dump", n)==0 ){
drh8e9297f2020-03-25 12:50:13 +00008421 char *zLike = 0;
8422 char *zSql;
drh2ce15c32017-07-11 13:34:40 +00008423 int i;
8424 int savedShowHeader = p->showHeader;
drhf213b332018-07-05 17:35:46 +00008425 int savedShellFlags = p->shellFlgs;
drhc1962192020-10-12 16:54:28 +00008426 ShellClearFlag(p,
8427 SHFLG_PreserveRowid|SHFLG_Newlines|SHFLG_Echo
8428 |SHFLG_DumpDataOnly|SHFLG_DumpNoSys);
drh2ce15c32017-07-11 13:34:40 +00008429 for(i=1; i<nArg; i++){
8430 if( azArg[i][0]=='-' ){
8431 const char *z = azArg[i]+1;
8432 if( z[0]=='-' ) z++;
8433 if( strcmp(z,"preserve-rowids")==0 ){
8434#ifdef SQLITE_OMIT_VIRTUALTABLE
8435 raw_printf(stderr, "The --preserve-rowids option is not compatible"
8436 " with SQLITE_OMIT_VIRTUALTABLE\n");
8437 rc = 1;
drh1d29fd82020-05-29 19:03:03 +00008438 sqlite3_free(zLike);
drh2ce15c32017-07-11 13:34:40 +00008439 goto meta_command_exit;
8440#else
8441 ShellSetFlag(p, SHFLG_PreserveRowid);
8442#endif
8443 }else
8444 if( strcmp(z,"newlines")==0 ){
8445 ShellSetFlag(p, SHFLG_Newlines);
8446 }else
drhc1962192020-10-12 16:54:28 +00008447 if( strcmp(z,"data-only")==0 ){
8448 ShellSetFlag(p, SHFLG_DumpDataOnly);
8449 }else
8450 if( strcmp(z,"nosys")==0 ){
8451 ShellSetFlag(p, SHFLG_DumpNoSys);
8452 }else
drh2ce15c32017-07-11 13:34:40 +00008453 {
8454 raw_printf(stderr, "Unknown option \"%s\" on \".dump\"\n", azArg[i]);
8455 rc = 1;
drh1d29fd82020-05-29 19:03:03 +00008456 sqlite3_free(zLike);
drh2ce15c32017-07-11 13:34:40 +00008457 goto meta_command_exit;
8458 }
drh2ce15c32017-07-11 13:34:40 +00008459 }else{
dan78a9d752021-05-25 11:39:14 +00008460 /* azArg[i] contains a LIKE pattern. This ".dump" request should
8461 ** only dump data for tables for which either the table name matches
8462 ** the LIKE pattern, or the table appears to be a shadow table of
8463 ** a virtual table for which the name matches the LIKE pattern.
8464 */
8465 char *zExpr = sqlite3_mprintf(
8466 "name LIKE %Q ESCAPE '\\' OR EXISTS ("
8467 " SELECT 1 FROM sqlite_schema WHERE "
8468 " name LIKE %Q ESCAPE '\\' AND"
8469 " sql LIKE 'CREATE VIRTUAL TABLE%%' AND"
8470 " substr(o.name, 1, length(name)+1) == (name||'_')"
8471 ")", azArg[i], azArg[i]
8472 );
8473
8474 if( zLike ){
8475 zLike = sqlite3_mprintf("%z OR %z", zLike, zExpr);
8476 }else{
8477 zLike = zExpr;
8478 }
drh2ce15c32017-07-11 13:34:40 +00008479 }
8480 }
dan68cb86e2019-04-20 20:57:28 +00008481
drh2ce15c32017-07-11 13:34:40 +00008482 open_db(p, 0);
dan68cb86e2019-04-20 20:57:28 +00008483
drhc1962192020-10-12 16:54:28 +00008484 if( (p->shellFlgs & SHFLG_DumpDataOnly)==0 ){
8485 /* When playing back a "dump", the content might appear in an order
8486 ** which causes immediate foreign key constraints to be violated.
8487 ** So disable foreign-key constraint enforcement to prevent problems. */
8488 raw_printf(p->out, "PRAGMA foreign_keys=OFF;\n");
8489 raw_printf(p->out, "BEGIN TRANSACTION;\n");
8490 }
drh2ce15c32017-07-11 13:34:40 +00008491 p->writableSchema = 0;
8492 p->showHeader = 0;
8493 /* Set writable_schema=ON since doing so forces SQLite to initialize
drh067b92b2020-06-19 15:24:12 +00008494 ** as much of the schema as it can even if the sqlite_schema table is
drh2ce15c32017-07-11 13:34:40 +00008495 ** corrupt. */
8496 sqlite3_exec(p->db, "SAVEPOINT dump; PRAGMA writable_schema=ON", 0, 0, 0);
8497 p->nErr = 0;
drh8e9297f2020-03-25 12:50:13 +00008498 if( zLike==0 ) zLike = sqlite3_mprintf("true");
8499 zSql = sqlite3_mprintf(
dan78a9d752021-05-25 11:39:14 +00008500 "SELECT name, type, sql FROM sqlite_schema AS o "
drh8e9297f2020-03-25 12:50:13 +00008501 "WHERE (%s) AND type=='table'"
8502 " AND sql NOT NULL"
8503 " ORDER BY tbl_name='sqlite_sequence', rowid",
8504 zLike
8505 );
8506 run_schema_dump_query(p,zSql);
8507 sqlite3_free(zSql);
drhc1962192020-10-12 16:54:28 +00008508 if( (p->shellFlgs & SHFLG_DumpDataOnly)==0 ){
8509 zSql = sqlite3_mprintf(
dan78a9d752021-05-25 11:39:14 +00008510 "SELECT sql FROM sqlite_schema AS o "
drhc1962192020-10-12 16:54:28 +00008511 "WHERE (%s) AND sql NOT NULL"
8512 " AND type IN ('index','trigger','view')",
8513 zLike
8514 );
8515 run_table_dump_query(p, zSql);
8516 sqlite3_free(zSql);
8517 }
drh8e9297f2020-03-25 12:50:13 +00008518 sqlite3_free(zLike);
drh2ce15c32017-07-11 13:34:40 +00008519 if( p->writableSchema ){
8520 raw_printf(p->out, "PRAGMA writable_schema=OFF;\n");
8521 p->writableSchema = 0;
8522 }
8523 sqlite3_exec(p->db, "PRAGMA writable_schema=OFF;", 0, 0, 0);
8524 sqlite3_exec(p->db, "RELEASE dump;", 0, 0, 0);
drhc1962192020-10-12 16:54:28 +00008525 if( (p->shellFlgs & SHFLG_DumpDataOnly)==0 ){
8526 raw_printf(p->out, p->nErr?"ROLLBACK; -- due to errors\n":"COMMIT;\n");
8527 }
drh2ce15c32017-07-11 13:34:40 +00008528 p->showHeader = savedShowHeader;
drhf213b332018-07-05 17:35:46 +00008529 p->shellFlgs = savedShellFlags;
drh2ce15c32017-07-11 13:34:40 +00008530 }else
8531
8532 if( c=='e' && strncmp(azArg[0], "echo", n)==0 ){
8533 if( nArg==2 ){
8534 setOrClearFlag(p, SHFLG_Echo, azArg[1]);
8535 }else{
8536 raw_printf(stderr, "Usage: .echo on|off\n");
8537 rc = 1;
8538 }
8539 }else
8540
8541 if( c=='e' && strncmp(azArg[0], "eqp", n)==0 ){
8542 if( nArg==2 ){
drhe2ca99c2018-05-02 00:33:43 +00008543 p->autoEQPtest = 0;
drhb4e50392019-01-26 15:40:04 +00008544 if( p->autoEQPtrace ){
8545 if( p->db ) sqlite3_exec(p->db, "PRAGMA vdbe_trace=OFF;", 0, 0, 0);
8546 p->autoEQPtrace = 0;
8547 }
drh2ce15c32017-07-11 13:34:40 +00008548 if( strcmp(azArg[1],"full")==0 ){
drhada70452017-12-21 21:02:27 +00008549 p->autoEQP = AUTOEQP_full;
8550 }else if( strcmp(azArg[1],"trigger")==0 ){
8551 p->autoEQP = AUTOEQP_trigger;
drhb4e50392019-01-26 15:40:04 +00008552#ifdef SQLITE_DEBUG
drhe2ca99c2018-05-02 00:33:43 +00008553 }else if( strcmp(azArg[1],"test")==0 ){
8554 p->autoEQP = AUTOEQP_on;
8555 p->autoEQPtest = 1;
drhb4e50392019-01-26 15:40:04 +00008556 }else if( strcmp(azArg[1],"trace")==0 ){
8557 p->autoEQP = AUTOEQP_full;
8558 p->autoEQPtrace = 1;
8559 open_db(p, 0);
drh067b92b2020-06-19 15:24:12 +00008560 sqlite3_exec(p->db, "SELECT name FROM sqlite_schema LIMIT 1", 0, 0, 0);
drhb4e50392019-01-26 15:40:04 +00008561 sqlite3_exec(p->db, "PRAGMA vdbe_trace=ON;", 0, 0, 0);
8562#endif
drh2ce15c32017-07-11 13:34:40 +00008563 }else{
mistachkinb71aa092018-01-23 00:05:18 +00008564 p->autoEQP = (u8)booleanValue(azArg[1]);
drh2ce15c32017-07-11 13:34:40 +00008565 }
8566 }else{
drhb4e50392019-01-26 15:40:04 +00008567 raw_printf(stderr, "Usage: .eqp off|on|trace|trigger|full\n");
drh2ce15c32017-07-11 13:34:40 +00008568 rc = 1;
8569 }
8570 }else
8571
8572 if( c=='e' && strncmp(azArg[0], "exit", n)==0 ){
8573 if( nArg>1 && (rc = (int)integerValue(azArg[1]))!=0 ) exit(rc);
8574 rc = 2;
8575 }else
8576
8577 /* The ".explain" command is automatic now. It is largely pointless. It
8578 ** retained purely for backwards compatibility */
8579 if( c=='e' && strncmp(azArg[0], "explain", n)==0 ){
8580 int val = 1;
8581 if( nArg>=2 ){
8582 if( strcmp(azArg[1],"auto")==0 ){
8583 val = 99;
8584 }else{
8585 val = booleanValue(azArg[1]);
8586 }
8587 }
8588 if( val==1 && p->mode!=MODE_Explain ){
8589 p->normalMode = p->mode;
8590 p->mode = MODE_Explain;
8591 p->autoExplain = 0;
8592 }else if( val==0 ){
8593 if( p->mode==MODE_Explain ) p->mode = p->normalMode;
8594 p->autoExplain = 0;
8595 }else if( val==99 ){
8596 if( p->mode==MODE_Explain ) p->mode = p->normalMode;
8597 p->autoExplain = 1;
8598 }
8599 }else
8600
dan6b046be2018-01-09 15:25:55 +00008601#ifndef SQLITE_OMIT_VIRTUALTABLE
dan43efc182017-12-19 17:42:13 +00008602 if( c=='e' && strncmp(azArg[0], "expert", n)==0 ){
drhfe463172021-12-16 17:57:21 +00008603 if( p->bSafeMode ){
8604 raw_printf(stderr,
8605 "Cannot run experimental commands such as \"%s\" in safe mode\n",
8606 azArg[0]);
8607 rc = 1;
8608 }else{
8609 open_db(p, 0);
8610 expertDotCommand(p, azArg, nArg);
8611 }
dan43efc182017-12-19 17:42:13 +00008612 }else
dan6b046be2018-01-09 15:25:55 +00008613#endif
dan43efc182017-12-19 17:42:13 +00008614
drhd985f722019-06-05 14:29:53 +00008615 if( c=='f' && strncmp(azArg[0], "filectrl", n)==0 ){
8616 static const struct {
8617 const char *zCtrlName; /* Name of a test-control option */
8618 int ctrlCode; /* Integer code for that option */
8619 const char *zUsage; /* Usage notes */
8620 } aCtrl[] = {
drhd985f722019-06-05 14:29:53 +00008621 { "chunk_size", SQLITE_FCNTL_CHUNK_SIZE, "SIZE" },
drh18a4bbd2020-12-17 15:17:42 +00008622 { "data_version", SQLITE_FCNTL_DATA_VERSION, "" },
drhd985f722019-06-05 14:29:53 +00008623 { "has_moved", SQLITE_FCNTL_HAS_MOVED, "" },
8624 { "lock_timeout", SQLITE_FCNTL_LOCK_TIMEOUT, "MILLISEC" },
drh18a4bbd2020-12-17 15:17:42 +00008625 { "persist_wal", SQLITE_FCNTL_PERSIST_WAL, "[BOOLEAN]" },
8626 /* { "pragma", SQLITE_FCNTL_PRAGMA, "NAME ARG" },*/
8627 { "psow", SQLITE_FCNTL_POWERSAFE_OVERWRITE, "[BOOLEAN]" },
drh541ef2c2020-04-20 16:21:30 +00008628 { "reserve_bytes", SQLITE_FCNTL_RESERVE_BYTES, "[N]" },
drh18a4bbd2020-12-17 15:17:42 +00008629 { "size_limit", SQLITE_FCNTL_SIZE_LIMIT, "[LIMIT]" },
8630 { "tempfilename", SQLITE_FCNTL_TEMPFILENAME, "" },
8631 /* { "win32_av_retry", SQLITE_FCNTL_WIN32_AV_RETRY, "COUNT DELAY" },*/
drhd985f722019-06-05 14:29:53 +00008632 };
8633 int filectrl = -1;
8634 int iCtrl = -1;
drh4245e042019-06-13 13:52:46 +00008635 sqlite3_int64 iRes = 0; /* Integer result to display if rc2==1 */
8636 int isOk = 0; /* 0: usage 1: %lld 2: no-result */
drhd985f722019-06-05 14:29:53 +00008637 int n2, i;
8638 const char *zCmd = 0;
drh541ef2c2020-04-20 16:21:30 +00008639 const char *zSchema = 0;
drhd985f722019-06-05 14:29:53 +00008640
8641 open_db(p, 0);
8642 zCmd = nArg>=2 ? azArg[1] : "help";
8643
drh541ef2c2020-04-20 16:21:30 +00008644 if( zCmd[0]=='-'
8645 && (strcmp(zCmd,"--schema")==0 || strcmp(zCmd,"-schema")==0)
8646 && nArg>=4
8647 ){
8648 zSchema = azArg[2];
8649 for(i=3; i<nArg; i++) azArg[i-2] = azArg[i];
8650 nArg -= 2;
8651 zCmd = azArg[1];
8652 }
8653
drhd985f722019-06-05 14:29:53 +00008654 /* The argument can optionally begin with "-" or "--" */
8655 if( zCmd[0]=='-' && zCmd[1] ){
8656 zCmd++;
8657 if( zCmd[0]=='-' && zCmd[1] ) zCmd++;
8658 }
8659
8660 /* --help lists all file-controls */
8661 if( strcmp(zCmd,"help")==0 ){
8662 utf8_printf(p->out, "Available file-controls:\n");
8663 for(i=0; i<ArraySize(aCtrl); i++){
8664 utf8_printf(p->out, " .filectrl %s %s\n",
8665 aCtrl[i].zCtrlName, aCtrl[i].zUsage);
8666 }
8667 rc = 1;
8668 goto meta_command_exit;
8669 }
8670
8671 /* convert filectrl text option to value. allow any unique prefix
8672 ** of the option name, or a numerical value. */
8673 n2 = strlen30(zCmd);
8674 for(i=0; i<ArraySize(aCtrl); i++){
8675 if( strncmp(zCmd, aCtrl[i].zCtrlName, n2)==0 ){
8676 if( filectrl<0 ){
8677 filectrl = aCtrl[i].ctrlCode;
8678 iCtrl = i;
8679 }else{
8680 utf8_printf(stderr, "Error: ambiguous file-control: \"%s\"\n"
8681 "Use \".filectrl --help\" for help\n", zCmd);
8682 rc = 1;
8683 goto meta_command_exit;
8684 }
8685 }
8686 }
8687 if( filectrl<0 ){
8688 utf8_printf(stderr,"Error: unknown file-control: %s\n"
8689 "Use \".filectrl --help\" for help\n", zCmd);
8690 }else{
8691 switch(filectrl){
8692 case SQLITE_FCNTL_SIZE_LIMIT: {
8693 if( nArg!=2 && nArg!=3 ) break;
8694 iRes = nArg==3 ? integerValue(azArg[2]) : -1;
drh541ef2c2020-04-20 16:21:30 +00008695 sqlite3_file_control(p->db, zSchema, SQLITE_FCNTL_SIZE_LIMIT, &iRes);
drhd985f722019-06-05 14:29:53 +00008696 isOk = 1;
8697 break;
8698 }
8699 case SQLITE_FCNTL_LOCK_TIMEOUT:
8700 case SQLITE_FCNTL_CHUNK_SIZE: {
8701 int x;
8702 if( nArg!=3 ) break;
8703 x = (int)integerValue(azArg[2]);
drh541ef2c2020-04-20 16:21:30 +00008704 sqlite3_file_control(p->db, zSchema, filectrl, &x);
drhd985f722019-06-05 14:29:53 +00008705 isOk = 2;
8706 break;
8707 }
8708 case SQLITE_FCNTL_PERSIST_WAL:
8709 case SQLITE_FCNTL_POWERSAFE_OVERWRITE: {
8710 int x;
8711 if( nArg!=2 && nArg!=3 ) break;
8712 x = nArg==3 ? booleanValue(azArg[2]) : -1;
drh541ef2c2020-04-20 16:21:30 +00008713 sqlite3_file_control(p->db, zSchema, filectrl, &x);
drhd985f722019-06-05 14:29:53 +00008714 iRes = x;
8715 isOk = 1;
8716 break;
8717 }
drh18a4bbd2020-12-17 15:17:42 +00008718 case SQLITE_FCNTL_DATA_VERSION:
drhd985f722019-06-05 14:29:53 +00008719 case SQLITE_FCNTL_HAS_MOVED: {
8720 int x;
8721 if( nArg!=2 ) break;
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 }
8727 case SQLITE_FCNTL_TEMPFILENAME: {
8728 char *z = 0;
8729 if( nArg!=2 ) break;
drh541ef2c2020-04-20 16:21:30 +00008730 sqlite3_file_control(p->db, zSchema, filectrl, &z);
drhd985f722019-06-05 14:29:53 +00008731 if( z ){
8732 utf8_printf(p->out, "%s\n", z);
8733 sqlite3_free(z);
8734 }
8735 isOk = 2;
8736 break;
8737 }
drh541ef2c2020-04-20 16:21:30 +00008738 case SQLITE_FCNTL_RESERVE_BYTES: {
8739 int x;
8740 if( nArg>=3 ){
8741 x = atoi(azArg[2]);
8742 sqlite3_file_control(p->db, zSchema, filectrl, &x);
8743 }
8744 x = -1;
8745 sqlite3_file_control(p->db, zSchema, filectrl, &x);
8746 utf8_printf(p->out,"%d\n", x);
8747 isOk = 2;
8748 break;
8749 }
drhd985f722019-06-05 14:29:53 +00008750 }
8751 }
8752 if( isOk==0 && iCtrl>=0 ){
8753 utf8_printf(p->out, "Usage: .filectrl %s %s\n", zCmd,aCtrl[iCtrl].zUsage);
8754 rc = 1;
8755 }else if( isOk==1 ){
drhe2500762019-06-13 14:07:41 +00008756 char zBuf[100];
8757 sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld", iRes);
8758 raw_printf(p->out, "%s\n", zBuf);
drhd985f722019-06-05 14:29:53 +00008759 }
8760 }else
8761
drh2ce15c32017-07-11 13:34:40 +00008762 if( c=='f' && strncmp(azArg[0], "fullschema", n)==0 ){
8763 ShellState data;
drh2ce15c32017-07-11 13:34:40 +00008764 int doStats = 0;
8765 memcpy(&data, p, sizeof(data));
8766 data.showHeader = 0;
8767 data.cMode = data.mode = MODE_Semi;
8768 if( nArg==2 && optionMatch(azArg[1], "indent") ){
8769 data.cMode = data.mode = MODE_Pretty;
8770 nArg = 1;
8771 }
8772 if( nArg!=1 ){
8773 raw_printf(stderr, "Usage: .fullschema ?--indent?\n");
8774 rc = 1;
8775 goto meta_command_exit;
8776 }
8777 open_db(p, 0);
8778 rc = sqlite3_exec(p->db,
8779 "SELECT sql FROM"
8780 " (SELECT sql sql, type type, tbl_name tbl_name, name name, rowid x"
drh067b92b2020-06-19 15:24:12 +00008781 " FROM sqlite_schema UNION ALL"
8782 " SELECT sql, type, tbl_name, name, rowid FROM sqlite_temp_schema) "
drh2ce15c32017-07-11 13:34:40 +00008783 "WHERE type!='meta' AND sql NOTNULL AND name NOT LIKE 'sqlite_%' "
drh69935c02021-06-25 11:14:10 +00008784 "ORDER BY x",
drhf83d5012021-05-03 13:35:00 +00008785 callback, &data, 0
drh2ce15c32017-07-11 13:34:40 +00008786 );
8787 if( rc==SQLITE_OK ){
8788 sqlite3_stmt *pStmt;
8789 rc = sqlite3_prepare_v2(p->db,
drh067b92b2020-06-19 15:24:12 +00008790 "SELECT rowid FROM sqlite_schema"
drh2ce15c32017-07-11 13:34:40 +00008791 " WHERE name GLOB 'sqlite_stat[134]'",
8792 -1, &pStmt, 0);
8793 doStats = sqlite3_step(pStmt)==SQLITE_ROW;
8794 sqlite3_finalize(pStmt);
8795 }
8796 if( doStats==0 ){
8797 raw_printf(p->out, "/* No STAT tables available */\n");
8798 }else{
drh067b92b2020-06-19 15:24:12 +00008799 raw_printf(p->out, "ANALYZE sqlite_schema;\n");
drh2ce15c32017-07-11 13:34:40 +00008800 data.cMode = data.mode = MODE_Insert;
8801 data.zDestTable = "sqlite_stat1";
drhf83d5012021-05-03 13:35:00 +00008802 shell_exec(&data, "SELECT * FROM sqlite_stat1", 0);
drh2ce15c32017-07-11 13:34:40 +00008803 data.zDestTable = "sqlite_stat4";
drhf83d5012021-05-03 13:35:00 +00008804 shell_exec(&data, "SELECT * FROM sqlite_stat4", 0);
drh067b92b2020-06-19 15:24:12 +00008805 raw_printf(p->out, "ANALYZE sqlite_schema;\n");
drh2ce15c32017-07-11 13:34:40 +00008806 }
8807 }else
8808
8809 if( c=='h' && strncmp(azArg[0], "headers", n)==0 ){
8810 if( nArg==2 ){
8811 p->showHeader = booleanValue(azArg[1]);
drhc0605082020-06-05 00:54:27 +00008812 p->shellFlgs |= SHFLG_HeaderSet;
drh2ce15c32017-07-11 13:34:40 +00008813 }else{
8814 raw_printf(stderr, "Usage: .headers on|off\n");
8815 rc = 1;
8816 }
8817 }else
8818
8819 if( c=='h' && strncmp(azArg[0], "help", n)==0 ){
drh98aa2ab2018-09-26 16:53:51 +00008820 if( nArg>=2 ){
drhe93f8262018-10-11 16:53:37 +00008821 n = showHelp(p->out, azArg[1]);
drh98aa2ab2018-09-26 16:53:51 +00008822 if( n==0 ){
8823 utf8_printf(p->out, "Nothing matches '%s'\n", azArg[1]);
8824 }
8825 }else{
8826 showHelp(p->out, 0);
8827 }
drh2ce15c32017-07-11 13:34:40 +00008828 }else
8829
8830 if( c=='i' && strncmp(azArg[0], "import", n)==0 ){
drhccb37812020-03-09 15:39:39 +00008831 char *zTable = 0; /* Insert data into this table */
larrybr53e11862022-03-06 23:41:21 +00008832 char *zSchema = 0; /* within this schema (may default to "main") */
drhccb37812020-03-09 15:39:39 +00008833 char *zFile = 0; /* Name of file to extra content from */
drh2ce15c32017-07-11 13:34:40 +00008834 sqlite3_stmt *pStmt = NULL; /* A statement */
8835 int nCol; /* Number of columns in the table */
8836 int nByte; /* Number of bytes in an SQL string */
8837 int i, j; /* Loop counters */
8838 int needCommit; /* True to COMMIT or ROLLBACK at end */
8839 int nSep; /* Number of bytes in p->colSeparator[] */
8840 char *zSql; /* An SQL statement */
larrybr41f46702022-03-07 00:14:52 +00008841 char *zFullTabName; /* Table name with schema if applicable */
drh2ce15c32017-07-11 13:34:40 +00008842 ImportCtx sCtx; /* Reader context */
8843 char *(SQLITE_CDECL *xRead)(ImportCtx*); /* Func to read one value */
drhccb37812020-03-09 15:39:39 +00008844 int eVerbose = 0; /* Larger for more console output */
8845 int nSkip = 0; /* Initial lines to skip */
8846 int useOutputMode = 1; /* Use output mode to determine separators */
drhe684ac62022-03-08 13:59:46 +00008847 char *zCreate = 0; /* CREATE TABLE statement text */
drh2ce15c32017-07-11 13:34:40 +00008848
drhb97e2ad2021-08-26 18:31:39 +00008849 failIfSafeMode(p, "cannot run .import in safe mode");
drhccb37812020-03-09 15:39:39 +00008850 memset(&sCtx, 0, sizeof(sCtx));
larrybr6ac9a5c2021-10-28 19:49:23 +00008851 sCtx.z = sqlite3_malloc64(120);
8852 if( sCtx.z==0 ){
8853 import_cleanup(&sCtx);
8854 shell_out_of_memory();
8855 }
drhccb37812020-03-09 15:39:39 +00008856 if( p->mode==MODE_Ascii ){
8857 xRead = ascii_read_one_field;
8858 }else{
8859 xRead = csv_read_one_field;
8860 }
8861 for(i=1; i<nArg; i++){
8862 char *z = azArg[i];
8863 if( z[0]=='-' && z[1]=='-' ) z++;
8864 if( z[0]!='-' ){
8865 if( zFile==0 ){
8866 zFile = z;
8867 }else if( zTable==0 ){
8868 zTable = z;
8869 }else{
8870 utf8_printf(p->out, "ERROR: extra argument: \"%s\". Usage:\n", z);
8871 showHelp(p->out, "import");
8872 rc = 1;
8873 goto meta_command_exit;
8874 }
8875 }else if( strcmp(z,"-v")==0 ){
8876 eVerbose++;
larrybr738d7b92022-01-13 21:22:54 +00008877 }else if( strcmp(z,"-schema")==0 && i<nArg-1 ){
8878 zSchema = azArg[++i];
drhccb37812020-03-09 15:39:39 +00008879 }else if( strcmp(z,"-skip")==0 && i<nArg-1 ){
8880 nSkip = integerValue(azArg[++i]);
8881 }else if( strcmp(z,"-ascii")==0 ){
8882 sCtx.cColSep = SEP_Unit[0];
8883 sCtx.cRowSep = SEP_Record[0];
8884 xRead = ascii_read_one_field;
8885 useOutputMode = 0;
8886 }else if( strcmp(z,"-csv")==0 ){
8887 sCtx.cColSep = ',';
8888 sCtx.cRowSep = '\n';
8889 xRead = csv_read_one_field;
8890 useOutputMode = 0;
8891 }else{
8892 utf8_printf(p->out, "ERROR: unknown option: \"%s\". Usage:\n", z);
8893 showHelp(p->out, "import");
8894 rc = 1;
8895 goto meta_command_exit;
8896 }
8897 }
8898 if( zTable==0 ){
8899 utf8_printf(p->out, "ERROR: missing %s argument. Usage:\n",
8900 zFile==0 ? "FILE" : "TABLE");
8901 showHelp(p->out, "import");
8902 rc = 1;
drh2ce15c32017-07-11 13:34:40 +00008903 goto meta_command_exit;
8904 }
drh2ce15c32017-07-11 13:34:40 +00008905 seenInterrupt = 0;
drh2ce15c32017-07-11 13:34:40 +00008906 open_db(p, 0);
drhccb37812020-03-09 15:39:39 +00008907 if( useOutputMode ){
8908 /* If neither the --csv or --ascii options are specified, then set
8909 ** the column and row separator characters from the output mode. */
8910 nSep = strlen30(p->colSeparator);
8911 if( nSep==0 ){
8912 raw_printf(stderr,
8913 "Error: non-null column separator required for import\n");
8914 rc = 1;
8915 goto meta_command_exit;
8916 }
8917 if( nSep>1 ){
8918 raw_printf(stderr,
8919 "Error: multi-character column separators not allowed"
8920 " for import\n");
8921 rc = 1;
8922 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");
8928 rc = 1;
8929 goto meta_command_exit;
8930 }
8931 if( nSep==2 && p->mode==MODE_Csv && strcmp(p->rowSeparator,SEP_CrLf)==0 ){
8932 /* When importing CSV (only), if the row separator is set to the
8933 ** default output row separator, change it to the default input
8934 ** row separator. This avoids having to maintain different input
8935 ** and output row separators. */
8936 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
8937 nSep = strlen30(p->rowSeparator);
8938 }
8939 if( nSep>1 ){
8940 raw_printf(stderr, "Error: multi-character row separators not allowed"
8941 " for import\n");
8942 rc = 1;
8943 goto meta_command_exit;
8944 }
8945 sCtx.cColSep = p->colSeparator[0];
8946 sCtx.cRowSep = p->rowSeparator[0];
drh2ce15c32017-07-11 13:34:40 +00008947 }
8948 sCtx.zFile = zFile;
8949 sCtx.nLine = 1;
8950 if( sCtx.zFile[0]=='|' ){
8951#ifdef SQLITE_OMIT_POPEN
8952 raw_printf(stderr, "Error: pipes are not supported in this OS\n");
drhccb37812020-03-09 15:39:39 +00008953 rc = 1;
8954 goto meta_command_exit;
drh2ce15c32017-07-11 13:34:40 +00008955#else
8956 sCtx.in = popen(sCtx.zFile+1, "r");
8957 sCtx.zFile = "<pipe>";
drh97767842020-05-29 19:39:35 +00008958 sCtx.xCloser = pclose;
drh2ce15c32017-07-11 13:34:40 +00008959#endif
8960 }else{
8961 sCtx.in = fopen(sCtx.zFile, "rb");
drh97767842020-05-29 19:39:35 +00008962 sCtx.xCloser = fclose;
drh2ce15c32017-07-11 13:34:40 +00008963 }
drh2ce15c32017-07-11 13:34:40 +00008964 if( sCtx.in==0 ){
8965 utf8_printf(stderr, "Error: cannot open \"%s\"\n", zFile);
drhccb37812020-03-09 15:39:39 +00008966 rc = 1;
dan07ed9c12021-11-02 14:01:41 +00008967 import_cleanup(&sCtx);
drhccb37812020-03-09 15:39:39 +00008968 goto meta_command_exit;
drh2ce15c32017-07-11 13:34:40 +00008969 }
drhccb37812020-03-09 15:39:39 +00008970 if( eVerbose>=2 || (eVerbose>=1 && useOutputMode) ){
8971 char zSep[2];
8972 zSep[1] = 0;
8973 zSep[0] = sCtx.cColSep;
8974 utf8_printf(p->out, "Column separator ");
8975 output_c_string(p->out, zSep);
8976 utf8_printf(p->out, ", row separator ");
8977 zSep[0] = sCtx.cRowSep;
8978 output_c_string(p->out, zSep);
8979 utf8_printf(p->out, "\n");
8980 }
larrybr53e11862022-03-06 23:41:21 +00008981 /* Below, resources must be freed before exit. */
drhccb37812020-03-09 15:39:39 +00008982 while( (nSkip--)>0 ){
8983 while( xRead(&sCtx) && sCtx.cTerm==sCtx.cColSep ){}
drhccb37812020-03-09 15:39:39 +00008984 }
larrybr53e11862022-03-06 23:41:21 +00008985 if( zSchema!=0 ){
larrybr41f46702022-03-07 00:14:52 +00008986 zFullTabName = sqlite3_mprintf("\"%w\".\"%w\"", zSchema, zTable);
larrybr53e11862022-03-06 23:41:21 +00008987 }else{
larrybr41f46702022-03-07 00:14:52 +00008988 zFullTabName = sqlite3_mprintf("\"%w\"", zTable);
larrybr53e11862022-03-06 23:41:21 +00008989 }
larrybr41f46702022-03-07 00:14:52 +00008990 zSql = sqlite3_mprintf("SELECT * FROM %s", zFullTabName);
8991 if( zSql==0 || zFullTabName==0 ){
drh97767842020-05-29 19:39:35 +00008992 import_cleanup(&sCtx);
drh4b5345c2018-04-24 13:07:40 +00008993 shell_out_of_memory();
drh2ce15c32017-07-11 13:34:40 +00008994 }
8995 nByte = strlen30(zSql);
8996 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
8997 import_append_char(&sCtx, 0); /* To ensure sCtx.z is allocated */
8998 if( rc && sqlite3_strglob("no such table: *", sqlite3_errmsg(p->db))==0 ){
larrybr58a53d62022-02-10 03:21:48 +00008999 sqlite3 *dbCols = 0;
larrybr33633862022-02-14 01:12:46 +00009000 char *zRenames = 0;
larrybr58a53d62022-02-10 03:21:48 +00009001 char *zColDefs;
drhe684ac62022-03-08 13:59:46 +00009002 zCreate = sqlite3_mprintf("CREATE TABLE %s", zFullTabName);
drh2ce15c32017-07-11 13:34:40 +00009003 while( xRead(&sCtx) ){
larrybra0337272022-02-11 13:40:25 +00009004 zAutoColumn(sCtx.z, &dbCols, 0);
drh2ce15c32017-07-11 13:34:40 +00009005 if( sCtx.cTerm!=sCtx.cColSep ) break;
larrybr4c5c6212022-02-11 01:21:09 +00009006 }
larrybr33633862022-02-14 01:12:46 +00009007 zColDefs = zAutoColumn(0, &dbCols, &zRenames);
9008 if( zRenames!=0 ){
larrybra0337272022-02-11 13:40:25 +00009009 utf8_printf((stdin_is_interactive && p->in==stdin)? p->out : stderr,
larrybr33633862022-02-14 01:12:46 +00009010 "Columns renamed during .import %s due to duplicates:\n"
9011 "%s\n", sCtx.zFile, zRenames);
9012 sqlite3_free(zRenames);
larrybra0337272022-02-11 13:40:25 +00009013 }
larrybr58a53d62022-02-10 03:21:48 +00009014 assert(dbCols==0);
9015 if( zColDefs==0 ){
drh2ce15c32017-07-11 13:34:40 +00009016 utf8_printf(stderr,"%s: empty file\n", sCtx.zFile);
larrybr53e11862022-03-06 23:41:21 +00009017 import_fail:
9018 sqlite3_free(zCreate);
9019 sqlite3_free(zSql);
larrybr41f46702022-03-07 00:14:52 +00009020 sqlite3_free(zFullTabName);
larrybr53e11862022-03-06 23:41:21 +00009021 import_cleanup(&sCtx);
drhccb37812020-03-09 15:39:39 +00009022 rc = 1;
9023 goto meta_command_exit;
drh2ce15c32017-07-11 13:34:40 +00009024 }
larrybr58a53d62022-02-10 03:21:48 +00009025 zCreate = sqlite3_mprintf("%z%z\n", zCreate, zColDefs);
drhccb37812020-03-09 15:39:39 +00009026 if( eVerbose>=1 ){
9027 utf8_printf(p->out, "%s\n", zCreate);
9028 }
drh2ce15c32017-07-11 13:34:40 +00009029 rc = sqlite3_exec(p->db, zCreate, 0, 0, 0);
drh2ce15c32017-07-11 13:34:40 +00009030 if( rc ){
larrybrce0b5e42022-01-14 16:29:45 +00009031 utf8_printf(stderr, "%s failed:\n%s\n", zCreate, sqlite3_errmsg(p->db));
larrybr53e11862022-03-06 23:41:21 +00009032 goto import_fail;
drh2ce15c32017-07-11 13:34:40 +00009033 }
larrybrce0b5e42022-01-14 16:29:45 +00009034 sqlite3_free(zCreate);
larrybr53e11862022-03-06 23:41:21 +00009035 zCreate = 0;
drh2ce15c32017-07-11 13:34:40 +00009036 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
9037 }
drh2ce15c32017-07-11 13:34:40 +00009038 if( rc ){
9039 if (pStmt) sqlite3_finalize(pStmt);
9040 utf8_printf(stderr,"Error: %s\n", sqlite3_errmsg(p->db));
larrybr53e11862022-03-06 23:41:21 +00009041 goto import_fail;
drh2ce15c32017-07-11 13:34:40 +00009042 }
larrybr53e11862022-03-06 23:41:21 +00009043 sqlite3_free(zSql);
drh2ce15c32017-07-11 13:34:40 +00009044 nCol = sqlite3_column_count(pStmt);
9045 sqlite3_finalize(pStmt);
9046 pStmt = 0;
9047 if( nCol==0 ) return 0; /* no columns, no error */
9048 zSql = sqlite3_malloc64( nByte*2 + 20 + nCol*2 );
9049 if( zSql==0 ){
drh97767842020-05-29 19:39:35 +00009050 import_cleanup(&sCtx);
drh4b5345c2018-04-24 13:07:40 +00009051 shell_out_of_memory();
drh2ce15c32017-07-11 13:34:40 +00009052 }
larrybr41f46702022-03-07 00:14:52 +00009053 sqlite3_snprintf(nByte+20, zSql, "INSERT INTO %s VALUES(?", zFullTabName);
drh2ce15c32017-07-11 13:34:40 +00009054 j = strlen30(zSql);
9055 for(i=1; i<nCol; i++){
9056 zSql[j++] = ',';
9057 zSql[j++] = '?';
9058 }
9059 zSql[j++] = ')';
9060 zSql[j] = 0;
drhccb37812020-03-09 15:39:39 +00009061 if( eVerbose>=2 ){
9062 utf8_printf(p->out, "Insert using: %s\n", zSql);
9063 }
drh2ce15c32017-07-11 13:34:40 +00009064 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
drh2ce15c32017-07-11 13:34:40 +00009065 if( rc ){
9066 utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
9067 if (pStmt) sqlite3_finalize(pStmt);
larrybr53e11862022-03-06 23:41:21 +00009068 goto import_fail;
drh2ce15c32017-07-11 13:34:40 +00009069 }
larrybr53e11862022-03-06 23:41:21 +00009070 sqlite3_free(zSql);
larrybr41f46702022-03-07 00:14:52 +00009071 sqlite3_free(zFullTabName);
drh2ce15c32017-07-11 13:34:40 +00009072 needCommit = sqlite3_get_autocommit(p->db);
9073 if( needCommit ) sqlite3_exec(p->db, "BEGIN", 0, 0, 0);
9074 do{
9075 int startLine = sCtx.nLine;
9076 for(i=0; i<nCol; i++){
9077 char *z = xRead(&sCtx);
9078 /*
9079 ** Did we reach end-of-file before finding any columns?
9080 ** If so, stop instead of NULL filling the remaining columns.
9081 */
9082 if( z==0 && i==0 ) break;
9083 /*
9084 ** Did we reach end-of-file OR end-of-line before finding any
9085 ** columns in ASCII mode? If so, stop instead of NULL filling
9086 ** the remaining columns.
9087 */
9088 if( p->mode==MODE_Ascii && (z==0 || z[0]==0) && i==0 ) break;
9089 sqlite3_bind_text(pStmt, i+1, z, -1, SQLITE_TRANSIENT);
9090 if( i<nCol-1 && sCtx.cTerm!=sCtx.cColSep ){
9091 utf8_printf(stderr, "%s:%d: expected %d columns but found %d - "
9092 "filling the rest with NULL\n",
9093 sCtx.zFile, startLine, nCol, i+1);
9094 i += 2;
9095 while( i<=nCol ){ sqlite3_bind_null(pStmt, i); i++; }
9096 }
9097 }
9098 if( sCtx.cTerm==sCtx.cColSep ){
9099 do{
9100 xRead(&sCtx);
9101 i++;
9102 }while( sCtx.cTerm==sCtx.cColSep );
9103 utf8_printf(stderr, "%s:%d: expected %d columns but found %d - "
9104 "extras ignored\n",
9105 sCtx.zFile, startLine, nCol, i);
9106 }
9107 if( i>=nCol ){
9108 sqlite3_step(pStmt);
9109 rc = sqlite3_reset(pStmt);
9110 if( rc!=SQLITE_OK ){
9111 utf8_printf(stderr, "%s:%d: INSERT failed: %s\n", sCtx.zFile,
9112 startLine, sqlite3_errmsg(p->db));
drhccb37812020-03-09 15:39:39 +00009113 sCtx.nErr++;
9114 }else{
9115 sCtx.nRow++;
drh2ce15c32017-07-11 13:34:40 +00009116 }
9117 }
9118 }while( sCtx.cTerm!=EOF );
9119
drh97767842020-05-29 19:39:35 +00009120 import_cleanup(&sCtx);
drh2ce15c32017-07-11 13:34:40 +00009121 sqlite3_finalize(pStmt);
9122 if( needCommit ) sqlite3_exec(p->db, "COMMIT", 0, 0, 0);
drhccb37812020-03-09 15:39:39 +00009123 if( eVerbose>0 ){
9124 utf8_printf(p->out,
9125 "Added %d rows with %d errors using %d lines of input\n",
9126 sCtx.nRow, sCtx.nErr, sCtx.nLine-1);
9127 }
drh2ce15c32017-07-11 13:34:40 +00009128 }else
9129
9130#ifndef SQLITE_UNTESTABLE
9131 if( c=='i' && strncmp(azArg[0], "imposter", n)==0 ){
9132 char *zSql;
9133 char *zCollist = 0;
9134 sqlite3_stmt *pStmt;
9135 int tnum = 0;
drh491c5be2019-10-18 15:58:50 +00009136 int isWO = 0; /* True if making an imposter of a WITHOUT ROWID table */
9137 int lenPK = 0; /* Length of the PRIMARY KEY string for isWO tables */
drh2ce15c32017-07-11 13:34:40 +00009138 int i;
drh48d219a2018-04-23 18:38:48 +00009139 if( !(nArg==3 || (nArg==2 && sqlite3_stricmp(azArg[1],"off")==0)) ){
9140 utf8_printf(stderr, "Usage: .imposter INDEX IMPOSTER\n"
9141 " .imposter off\n");
drh491c5be2019-10-18 15:58:50 +00009142 /* Also allowed, but not documented:
9143 **
9144 ** .imposter TABLE IMPOSTER
9145 **
9146 ** where TABLE is a WITHOUT ROWID table. In that case, the
9147 ** imposter is another WITHOUT ROWID table with the columns in
9148 ** storage order. */
drh2ce15c32017-07-11 13:34:40 +00009149 rc = 1;
9150 goto meta_command_exit;
9151 }
9152 open_db(p, 0);
drh48d219a2018-04-23 18:38:48 +00009153 if( nArg==2 ){
9154 sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 0, 1);
9155 goto meta_command_exit;
9156 }
drh491c5be2019-10-18 15:58:50 +00009157 zSql = sqlite3_mprintf(
drh067b92b2020-06-19 15:24:12 +00009158 "SELECT rootpage, 0 FROM sqlite_schema"
drh491c5be2019-10-18 15:58:50 +00009159 " WHERE name='%q' AND type='index'"
9160 "UNION ALL "
drh067b92b2020-06-19 15:24:12 +00009161 "SELECT rootpage, 1 FROM sqlite_schema"
drh491c5be2019-10-18 15:58:50 +00009162 " WHERE name='%q' AND type='table'"
9163 " AND sql LIKE '%%without%%rowid%%'",
9164 azArg[1], azArg[1]
9165 );
drh2ce15c32017-07-11 13:34:40 +00009166 sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
9167 sqlite3_free(zSql);
9168 if( sqlite3_step(pStmt)==SQLITE_ROW ){
9169 tnum = sqlite3_column_int(pStmt, 0);
drh491c5be2019-10-18 15:58:50 +00009170 isWO = sqlite3_column_int(pStmt, 1);
drh2ce15c32017-07-11 13:34:40 +00009171 }
9172 sqlite3_finalize(pStmt);
drh2ce15c32017-07-11 13:34:40 +00009173 zSql = sqlite3_mprintf("PRAGMA index_xinfo='%q'", azArg[1]);
9174 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
9175 sqlite3_free(zSql);
9176 i = 0;
drhe85e1da2021-10-01 21:01:07 +00009177 while( rc==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW ){
drh2ce15c32017-07-11 13:34:40 +00009178 char zLabel[20];
9179 const char *zCol = (const char*)sqlite3_column_text(pStmt,2);
9180 i++;
9181 if( zCol==0 ){
9182 if( sqlite3_column_int(pStmt,1)==-1 ){
9183 zCol = "_ROWID_";
9184 }else{
9185 sqlite3_snprintf(sizeof(zLabel),zLabel,"expr%d",i);
9186 zCol = zLabel;
9187 }
9188 }
drh491c5be2019-10-18 15:58:50 +00009189 if( isWO && lenPK==0 && sqlite3_column_int(pStmt,5)==0 && zCollist ){
9190 lenPK = (int)strlen(zCollist);
9191 }
drh2ce15c32017-07-11 13:34:40 +00009192 if( zCollist==0 ){
9193 zCollist = sqlite3_mprintf("\"%w\"", zCol);
9194 }else{
9195 zCollist = sqlite3_mprintf("%z,\"%w\"", zCollist, zCol);
9196 }
9197 }
9198 sqlite3_finalize(pStmt);
drh491c5be2019-10-18 15:58:50 +00009199 if( i==0 || tnum==0 ){
9200 utf8_printf(stderr, "no such index: \"%s\"\n", azArg[1]);
9201 rc = 1;
9202 sqlite3_free(zCollist);
9203 goto meta_command_exit;
9204 }
9205 if( lenPK==0 ) lenPK = 100000;
drh2ce15c32017-07-11 13:34:40 +00009206 zSql = sqlite3_mprintf(
drh491c5be2019-10-18 15:58:50 +00009207 "CREATE TABLE \"%w\"(%s,PRIMARY KEY(%.*s))WITHOUT ROWID",
9208 azArg[2], zCollist, lenPK, zCollist);
drh2ce15c32017-07-11 13:34:40 +00009209 sqlite3_free(zCollist);
9210 rc = sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 1, tnum);
9211 if( rc==SQLITE_OK ){
9212 rc = sqlite3_exec(p->db, zSql, 0, 0, 0);
9213 sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 0, 0);
9214 if( rc ){
9215 utf8_printf(stderr, "Error in [%s]: %s\n", zSql, sqlite3_errmsg(p->db));
9216 }else{
9217 utf8_printf(stdout, "%s;\n", zSql);
9218 raw_printf(stdout,
drh491c5be2019-10-18 15:58:50 +00009219 "WARNING: writing to an imposter table will corrupt the \"%s\" %s!\n",
9220 azArg[1], isWO ? "table" : "index"
drh2ce15c32017-07-11 13:34:40 +00009221 );
9222 }
9223 }else{
9224 raw_printf(stderr, "SQLITE_TESTCTRL_IMPOSTER returns %d\n", rc);
9225 rc = 1;
9226 }
9227 sqlite3_free(zSql);
9228 }else
9229#endif /* !defined(SQLITE_OMIT_TEST_CONTROL) */
9230
9231#ifdef SQLITE_ENABLE_IOTRACE
9232 if( c=='i' && strncmp(azArg[0], "iotrace", n)==0 ){
9233 SQLITE_API extern void (SQLITE_CDECL *sqlite3IoTrace)(const char*, ...);
9234 if( iotrace && iotrace!=stdout ) fclose(iotrace);
9235 iotrace = 0;
9236 if( nArg<2 ){
9237 sqlite3IoTrace = 0;
9238 }else if( strcmp(azArg[1], "-")==0 ){
9239 sqlite3IoTrace = iotracePrintf;
9240 iotrace = stdout;
9241 }else{
9242 iotrace = fopen(azArg[1], "w");
9243 if( iotrace==0 ){
9244 utf8_printf(stderr, "Error: cannot open \"%s\"\n", azArg[1]);
9245 sqlite3IoTrace = 0;
9246 rc = 1;
9247 }else{
9248 sqlite3IoTrace = iotracePrintf;
9249 }
9250 }
9251 }else
9252#endif
9253
9254 if( c=='l' && n>=5 && strncmp(azArg[0], "limits", n)==0 ){
9255 static const struct {
9256 const char *zLimitName; /* Name of a limit */
9257 int limitCode; /* Integer code for that limit */
9258 } aLimit[] = {
9259 { "length", SQLITE_LIMIT_LENGTH },
9260 { "sql_length", SQLITE_LIMIT_SQL_LENGTH },
9261 { "column", SQLITE_LIMIT_COLUMN },
9262 { "expr_depth", SQLITE_LIMIT_EXPR_DEPTH },
9263 { "compound_select", SQLITE_LIMIT_COMPOUND_SELECT },
9264 { "vdbe_op", SQLITE_LIMIT_VDBE_OP },
9265 { "function_arg", SQLITE_LIMIT_FUNCTION_ARG },
9266 { "attached", SQLITE_LIMIT_ATTACHED },
9267 { "like_pattern_length", SQLITE_LIMIT_LIKE_PATTERN_LENGTH },
9268 { "variable_number", SQLITE_LIMIT_VARIABLE_NUMBER },
9269 { "trigger_depth", SQLITE_LIMIT_TRIGGER_DEPTH },
9270 { "worker_threads", SQLITE_LIMIT_WORKER_THREADS },
9271 };
9272 int i, n2;
9273 open_db(p, 0);
9274 if( nArg==1 ){
9275 for(i=0; i<ArraySize(aLimit); i++){
9276 printf("%20s %d\n", aLimit[i].zLimitName,
9277 sqlite3_limit(p->db, aLimit[i].limitCode, -1));
9278 }
9279 }else if( nArg>3 ){
9280 raw_printf(stderr, "Usage: .limit NAME ?NEW-VALUE?\n");
9281 rc = 1;
9282 goto meta_command_exit;
9283 }else{
9284 int iLimit = -1;
9285 n2 = strlen30(azArg[1]);
9286 for(i=0; i<ArraySize(aLimit); i++){
9287 if( sqlite3_strnicmp(aLimit[i].zLimitName, azArg[1], n2)==0 ){
9288 if( iLimit<0 ){
9289 iLimit = i;
9290 }else{
9291 utf8_printf(stderr, "ambiguous limit: \"%s\"\n", azArg[1]);
9292 rc = 1;
9293 goto meta_command_exit;
9294 }
9295 }
9296 }
9297 if( iLimit<0 ){
9298 utf8_printf(stderr, "unknown limit: \"%s\"\n"
9299 "enter \".limits\" with no arguments for a list.\n",
9300 azArg[1]);
9301 rc = 1;
9302 goto meta_command_exit;
9303 }
9304 if( nArg==3 ){
9305 sqlite3_limit(p->db, aLimit[iLimit].limitCode,
9306 (int)integerValue(azArg[2]));
9307 }
9308 printf("%20s %d\n", aLimit[iLimit].zLimitName,
9309 sqlite3_limit(p->db, aLimit[iLimit].limitCode, -1));
9310 }
9311 }else
9312
9313 if( c=='l' && n>2 && strncmp(azArg[0], "lint", n)==0 ){
9314 open_db(p, 0);
9315 lintDotCommand(p, azArg, nArg);
9316 }else
9317
9318#ifndef SQLITE_OMIT_LOAD_EXTENSION
9319 if( c=='l' && strncmp(azArg[0], "load", n)==0 ){
9320 const char *zFile, *zProc;
9321 char *zErrMsg = 0;
drhb97e2ad2021-08-26 18:31:39 +00009322 failIfSafeMode(p, "cannot run .load in safe mode");
drh2ce15c32017-07-11 13:34:40 +00009323 if( nArg<2 ){
9324 raw_printf(stderr, "Usage: .load FILE ?ENTRYPOINT?\n");
9325 rc = 1;
9326 goto meta_command_exit;
9327 }
9328 zFile = azArg[1];
9329 zProc = nArg>=3 ? azArg[2] : 0;
9330 open_db(p, 0);
9331 rc = sqlite3_load_extension(p->db, zFile, zProc, &zErrMsg);
9332 if( rc!=SQLITE_OK ){
9333 utf8_printf(stderr, "Error: %s\n", zErrMsg);
9334 sqlite3_free(zErrMsg);
9335 rc = 1;
9336 }
9337 }else
9338#endif
9339
9340 if( c=='l' && strncmp(azArg[0], "log", n)==0 ){
drhb97e2ad2021-08-26 18:31:39 +00009341 failIfSafeMode(p, "cannot run .log in safe mode");
drh2ce15c32017-07-11 13:34:40 +00009342 if( nArg!=2 ){
9343 raw_printf(stderr, "Usage: .log FILENAME\n");
9344 rc = 1;
9345 }else{
9346 const char *zFile = azArg[1];
9347 output_file_close(p->pLog);
drha92a01a2018-01-10 22:15:37 +00009348 p->pLog = output_file_open(zFile, 0);
drh2ce15c32017-07-11 13:34:40 +00009349 }
9350 }else
9351
9352 if( c=='m' && strncmp(azArg[0], "mode", n)==0 ){
drhe40f2862022-01-31 14:14:29 +00009353 const char *zMode = 0;
9354 const char *zTabname = 0;
9355 int i, n2;
larrybrcc4d55c2022-02-01 02:50:45 +00009356 ColModeOpts cmOpts = ColModeOpts_default;
drhe40f2862022-01-31 14:14:29 +00009357 for(i=1; i<nArg; i++){
9358 const char *z = azArg[i];
9359 if( optionMatch(z,"wrap") && i+1<nArg ){
larrybrcc4d55c2022-02-01 02:50:45 +00009360 cmOpts.iWrap = integerValue(azArg[++i]);
drhca1776b2022-02-01 12:28:17 +00009361 }else if( optionMatch(z,"ww") ){
9362 cmOpts.bWordWrap = 1;
larrybrcc4d55c2022-02-01 02:50:45 +00009363 }else if( optionMatch(z,"wordwrap") && i+1<nArg ){
9364 cmOpts.bWordWrap = (u8)booleanValue(azArg[++i]);
drhe40f2862022-01-31 14:14:29 +00009365 }else if( optionMatch(z,"quote") ){
larrybrcc4d55c2022-02-01 02:50:45 +00009366 cmOpts.bQuote = 1;
drhe40f2862022-01-31 14:14:29 +00009367 }else if( optionMatch(z,"noquote") ){
larrybrcc4d55c2022-02-01 02:50:45 +00009368 cmOpts.bQuote = 0;
drhe40f2862022-01-31 14:14:29 +00009369 }else if( zMode==0 ){
9370 zMode = z;
drhca1776b2022-02-01 12:28:17 +00009371 /* Apply defaults for qbox pseudo-mods. If that
larrybrcc4d55c2022-02-01 02:50:45 +00009372 * overwrites already-set values, user was informed of this.
9373 */
9374 if( strcmp(z, "qbox")==0 ){
9375 ColModeOpts cmo = ColModeOpts_default_qbox;
9376 zMode = "box";
9377 cmOpts = cmo;
larrybrcc4d55c2022-02-01 02:50:45 +00009378 }
drhe40f2862022-01-31 14:14:29 +00009379 }else if( zTabname==0 ){
9380 zTabname = z;
9381 }else if( z[0]=='-' ){
9382 utf8_printf(stderr, "unknown option: %s\n", z);
9383 utf8_printf(stderr, "options:\n"
9384 " --noquote\n"
9385 " --quote\n"
larrybrcc4d55c2022-02-01 02:50:45 +00009386 " --wordwrap on/off\n"
drhca1776b2022-02-01 12:28:17 +00009387 " --wrap N\n"
9388 " --ww\n");
drhe40f2862022-01-31 14:14:29 +00009389 rc = 1;
9390 goto meta_command_exit;
9391 }else{
9392 utf8_printf(stderr, "extra argument: \"%s\"\n", z);
9393 rc = 1;
9394 goto meta_command_exit;
9395 }
9396 }
9397 if( zMode==0 ){
9398 if( p->mode==MODE_Column
9399 || (p->mode>=MODE_Markdown && p->mode<=MODE_Box)
9400 ){
larrybrcc4d55c2022-02-01 02:50:45 +00009401 raw_printf
9402 (p->out,
9403 "current output mode: %s --wrap %d --wordwrap %s --%squote\n",
9404 modeDescr[p->mode], p->cmOpts.iWrap,
9405 p->cmOpts.bWordWrap ? "on" : "off",
9406 p->cmOpts.bQuote ? "" : "no");
drhe40f2862022-01-31 14:14:29 +00009407 }else{
9408 raw_printf(p->out, "current output mode: %s\n", modeDescr[p->mode]);
9409 }
drhe40f2862022-01-31 14:14:29 +00009410 zMode = modeDescr[p->mode];
9411 }
9412 n2 = strlen30(zMode);
9413 if( strncmp(zMode,"lines",n2)==0 ){
drh2ce15c32017-07-11 13:34:40 +00009414 p->mode = MODE_Line;
9415 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
drhe40f2862022-01-31 14:14:29 +00009416 }else if( strncmp(zMode,"columns",n2)==0 ){
drh2ce15c32017-07-11 13:34:40 +00009417 p->mode = MODE_Column;
drhc0605082020-06-05 00:54:27 +00009418 if( (p->shellFlgs & SHFLG_HeaderSet)==0 ){
9419 p->showHeader = 1;
9420 }
drh2ce15c32017-07-11 13:34:40 +00009421 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
larrybrcc4d55c2022-02-01 02:50:45 +00009422 p->cmOpts = cmOpts;
drhe40f2862022-01-31 14:14:29 +00009423 }else if( strncmp(zMode,"list",n2)==0 ){
drh2ce15c32017-07-11 13:34:40 +00009424 p->mode = MODE_List;
9425 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Column);
9426 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
drhe40f2862022-01-31 14:14:29 +00009427 }else if( strncmp(zMode,"html",n2)==0 ){
drh2ce15c32017-07-11 13:34:40 +00009428 p->mode = MODE_Html;
drhe40f2862022-01-31 14:14:29 +00009429 }else if( strncmp(zMode,"tcl",n2)==0 ){
drh2ce15c32017-07-11 13:34:40 +00009430 p->mode = MODE_Tcl;
9431 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Space);
9432 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
drhe40f2862022-01-31 14:14:29 +00009433 }else if( strncmp(zMode,"csv",n2)==0 ){
drh2ce15c32017-07-11 13:34:40 +00009434 p->mode = MODE_Csv;
9435 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Comma);
9436 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_CrLf);
drhe40f2862022-01-31 14:14:29 +00009437 }else if( strncmp(zMode,"tabs",n2)==0 ){
drh2ce15c32017-07-11 13:34:40 +00009438 p->mode = MODE_List;
9439 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Tab);
drhe40f2862022-01-31 14:14:29 +00009440 }else if( strncmp(zMode,"insert",n2)==0 ){
drh2ce15c32017-07-11 13:34:40 +00009441 p->mode = MODE_Insert;
drhe40f2862022-01-31 14:14:29 +00009442 set_table_name(p, zTabname ? zTabname : "table");
9443 }else if( strncmp(zMode,"quote",n2)==0 ){
drh2ce15c32017-07-11 13:34:40 +00009444 p->mode = MODE_Quote;
drhc6835732020-05-28 20:37:17 +00009445 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Comma);
9446 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
drhe40f2862022-01-31 14:14:29 +00009447 }else if( strncmp(zMode,"ascii",n2)==0 ){
drh2ce15c32017-07-11 13:34:40 +00009448 p->mode = MODE_Ascii;
9449 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Unit);
9450 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Record);
drhe40f2862022-01-31 14:14:29 +00009451 }else if( strncmp(zMode,"markdown",n2)==0 ){
drh30c54a02020-05-28 23:49:50 +00009452 p->mode = MODE_Markdown;
larrybrcc4d55c2022-02-01 02:50:45 +00009453 p->cmOpts = cmOpts;
drhe40f2862022-01-31 14:14:29 +00009454 }else if( strncmp(zMode,"table",n2)==0 ){
drh30c54a02020-05-28 23:49:50 +00009455 p->mode = MODE_Table;
larrybrcc4d55c2022-02-01 02:50:45 +00009456 p->cmOpts = cmOpts;
drhe40f2862022-01-31 14:14:29 +00009457 }else if( strncmp(zMode,"box",n2)==0 ){
drh0908e382020-06-04 18:05:39 +00009458 p->mode = MODE_Box;
larrybrcc4d55c2022-02-01 02:50:45 +00009459 p->cmOpts = cmOpts;
drhe40f2862022-01-31 14:14:29 +00009460 }else if( strncmp(zMode,"count",n2)==0 ){
drh5d88be82021-12-09 16:17:43 +00009461 p->mode = MODE_Count;
drhe40f2862022-01-31 14:14:29 +00009462 }else if( strncmp(zMode,"off",n2)==0 ){
drh5d88be82021-12-09 16:17:43 +00009463 p->mode = MODE_Off;
drhe40f2862022-01-31 14:14:29 +00009464 }else if( strncmp(zMode,"json",n2)==0 ){
drh30c54a02020-05-28 23:49:50 +00009465 p->mode = MODE_Json;
drh2ce15c32017-07-11 13:34:40 +00009466 }else{
9467 raw_printf(stderr, "Error: mode should be one of: "
drh0908e382020-06-04 18:05:39 +00009468 "ascii box column csv html insert json line list markdown "
drhca1776b2022-02-01 12:28:17 +00009469 "qbox quote table tabs tcl\n");
drh2ce15c32017-07-11 13:34:40 +00009470 rc = 1;
9471 }
9472 p->cMode = p->mode;
9473 }else
9474
drhb97e2ad2021-08-26 18:31:39 +00009475 if( c=='n' && strcmp(azArg[0], "nonce")==0 ){
9476 if( nArg!=2 ){
9477 raw_printf(stderr, "Usage: .nonce NONCE\n");
9478 rc = 1;
9479 }else if( p->zNonce==0 || strcmp(azArg[1],p->zNonce)!=0 ){
drhfe463172021-12-16 17:57:21 +00009480 raw_printf(stderr, "line %d: incorrect nonce: \"%s\"\n",
9481 p->lineno, azArg[1]);
drhb97e2ad2021-08-26 18:31:39 +00009482 exit(1);
drhe85e1da2021-10-01 21:01:07 +00009483 }else{
9484 p->bSafeMode = 0;
9485 return 0; /* Return immediately to bypass the safe mode reset
9486 ** at the end of this procedure */
drhb97e2ad2021-08-26 18:31:39 +00009487 }
drhb97e2ad2021-08-26 18:31:39 +00009488 }else
9489
drh2ce15c32017-07-11 13:34:40 +00009490 if( c=='n' && strncmp(azArg[0], "nullvalue", n)==0 ){
9491 if( nArg==2 ){
9492 sqlite3_snprintf(sizeof(p->nullValue), p->nullValue,
9493 "%.*s", (int)ArraySize(p->nullValue)-1, azArg[1]);
9494 }else{
9495 raw_printf(stderr, "Usage: .nullvalue STRING\n");
9496 rc = 1;
9497 }
9498 }else
9499
9500 if( c=='o' && strncmp(azArg[0], "open", n)==0 && n>=2 ){
drh61fd4b92021-12-16 14:59:25 +00009501 const char *zFN = 0; /* Pointer to constant filename */
drhf30bbce2020-12-02 18:27:48 +00009502 char *zNewFilename = 0; /* Name of the database file to open */
9503 int iName = 1; /* Index in azArg[] of the filename */
9504 int newFlag = 0; /* True to delete file before opening */
dan1872c5b2021-12-02 14:16:30 +00009505 int openMode = SHELL_OPEN_UNSPEC;
9506
drh2ce15c32017-07-11 13:34:40 +00009507 /* Check for command-line arguments */
drhf30bbce2020-12-02 18:27:48 +00009508 for(iName=1; iName<nArg; iName++){
drh2ce15c32017-07-11 13:34:40 +00009509 const char *z = azArg[iName];
9510 if( optionMatch(z,"new") ){
9511 newFlag = 1;
drh3baed312018-03-08 18:14:41 +00009512#ifdef SQLITE_HAVE_ZLIB
drh1fa6d9f2018-01-06 21:46:01 +00009513 }else if( optionMatch(z, "zip") ){
dan1872c5b2021-12-02 14:16:30 +00009514 openMode = SHELL_OPEN_ZIPFILE;
drh1fa6d9f2018-01-06 21:46:01 +00009515#endif
9516 }else if( optionMatch(z, "append") ){
dan1872c5b2021-12-02 14:16:30 +00009517 openMode = SHELL_OPEN_APPENDVFS;
drhee269a62018-02-14 23:27:43 +00009518 }else if( optionMatch(z, "readonly") ){
dan1872c5b2021-12-02 14:16:30 +00009519 openMode = SHELL_OPEN_READONLY;
drh0933aad2019-11-18 17:46:38 +00009520 }else if( optionMatch(z, "nofollow") ){
9521 p->openFlags |= SQLITE_OPEN_NOFOLLOW;
drh8d889af2021-05-08 17:18:23 +00009522#ifndef SQLITE_OMIT_DESERIALIZE
drh60f34ae2018-10-30 13:19:49 +00009523 }else if( optionMatch(z, "deserialize") ){
dan1872c5b2021-12-02 14:16:30 +00009524 openMode = SHELL_OPEN_DESERIALIZE;
drh33746482018-12-13 15:06:26 +00009525 }else if( optionMatch(z, "hexdb") ){
dan1872c5b2021-12-02 14:16:30 +00009526 openMode = SHELL_OPEN_HEXDB;
drh6ca64482019-01-22 16:06:20 +00009527 }else if( optionMatch(z, "maxsize") && iName+1<nArg ){
9528 p->szMax = integerValue(azArg[++iName]);
drh8d889af2021-05-08 17:18:23 +00009529#endif /* SQLITE_OMIT_DESERIALIZE */
drh2ce15c32017-07-11 13:34:40 +00009530 }else if( z[0]=='-' ){
9531 utf8_printf(stderr, "unknown option: %s\n", z);
9532 rc = 1;
9533 goto meta_command_exit;
drh61fd4b92021-12-16 14:59:25 +00009534 }else if( zFN ){
drhf30bbce2020-12-02 18:27:48 +00009535 utf8_printf(stderr, "extra argument: \"%s\"\n", z);
9536 rc = 1;
9537 goto meta_command_exit;
9538 }else{
drh61fd4b92021-12-16 14:59:25 +00009539 zFN = z;
drh2ce15c32017-07-11 13:34:40 +00009540 }
9541 }
dan1872c5b2021-12-02 14:16:30 +00009542
9543 /* Close the existing database */
9544 session_close_all(p, -1);
9545 close_db(p->db);
9546 p->db = 0;
9547 p->pAuxDb->zDbFilename = 0;
9548 sqlite3_free(p->pAuxDb->zFreeOnClose);
9549 p->pAuxDb->zFreeOnClose = 0;
9550 p->openMode = openMode;
9551 p->openFlags = 0;
9552 p->szMax = 0;
9553
drh2ce15c32017-07-11 13:34:40 +00009554 /* If a filename is specified, try to open it first */
drh61fd4b92021-12-16 14:59:25 +00009555 if( zFN || p->openMode==SHELL_OPEN_HEXDB ){
drhc320e062021-12-24 19:44:11 +00009556 if( newFlag && zFN && !p->bSafeMode ) shellDeleteFile(zFN);
drhb97e2ad2021-08-26 18:31:39 +00009557 if( p->bSafeMode
9558 && p->openMode!=SHELL_OPEN_HEXDB
drhc320e062021-12-24 19:44:11 +00009559 && zFN
9560 && strcmp(zFN,":memory:")!=0
drhb97e2ad2021-08-26 18:31:39 +00009561 ){
9562 failIfSafeMode(p, "cannot open disk-based database files in safe mode");
9563 }
drh61fd4b92021-12-16 14:59:25 +00009564 if( zFN ){
9565 zNewFilename = sqlite3_mprintf("%s", zFN);
9566 shell_check_oom(zNewFilename);
9567 }else{
9568 zNewFilename = 0;
9569 }
drh37407122021-07-23 18:43:58 +00009570 p->pAuxDb->zDbFilename = zNewFilename;
drhbe4ccb22018-05-17 20:04:24 +00009571 open_db(p, OPEN_DB_KEEPALIVE);
drh2ce15c32017-07-11 13:34:40 +00009572 if( p->db==0 ){
9573 utf8_printf(stderr, "Error: cannot open '%s'\n", zNewFilename);
9574 sqlite3_free(zNewFilename);
9575 }else{
drh37407122021-07-23 18:43:58 +00009576 p->pAuxDb->zFreeOnClose = zNewFilename;
drh2ce15c32017-07-11 13:34:40 +00009577 }
9578 }
9579 if( p->db==0 ){
9580 /* As a fall-back open a TEMP database */
drh37407122021-07-23 18:43:58 +00009581 p->pAuxDb->zDbFilename = 0;
drh2ce15c32017-07-11 13:34:40 +00009582 open_db(p, 0);
9583 }
9584 }else
9585
drh13c20932018-01-10 21:41:55 +00009586 if( (c=='o'
9587 && (strncmp(azArg[0], "output", n)==0||strncmp(azArg[0], "once", n)==0))
9588 || (c=='e' && n==5 && strcmp(azArg[0],"excel")==0)
drh2ce15c32017-07-11 13:34:40 +00009589 ){
drh4b0229a2021-02-17 13:19:22 +00009590 char *zFile = 0;
drha92a01a2018-01-10 22:15:37 +00009591 int bTxtMode = 0;
drh7a431002020-04-18 14:12:00 +00009592 int i;
9593 int eMode = 0;
9594 int bBOM = 0;
drh5415ab42020-04-23 20:45:46 +00009595 int bOnce = 0; /* 0: .output, 1: .once, 2: .excel */
drh7a431002020-04-18 14:12:00 +00009596
drhb97e2ad2021-08-26 18:31:39 +00009597 failIfSafeMode(p, "cannot run .%s in safe mode", azArg[0]);
drh7a431002020-04-18 14:12:00 +00009598 if( c=='e' ){
9599 eMode = 'x';
9600 bOnce = 2;
9601 }else if( strncmp(azArg[0],"once",n)==0 ){
9602 bOnce = 1;
drh13c20932018-01-10 21:41:55 +00009603 }
drh7a431002020-04-18 14:12:00 +00009604 for(i=1; i<nArg; i++){
9605 char *z = azArg[i];
9606 if( z[0]=='-' ){
9607 if( z[1]=='-' ) z++;
9608 if( strcmp(z,"-bom")==0 ){
9609 bBOM = 1;
9610 }else if( c!='e' && strcmp(z,"-x")==0 ){
9611 eMode = 'x'; /* spreadsheet */
9612 }else if( c!='e' && strcmp(z,"-e")==0 ){
9613 eMode = 'e'; /* text editor */
9614 }else{
9615 utf8_printf(p->out, "ERROR: unknown option: \"%s\". Usage:\n",
9616 azArg[i]);
9617 showHelp(p->out, azArg[0]);
9618 rc = 1;
9619 goto meta_command_exit;
9620 }
drh4b0229a2021-02-17 13:19:22 +00009621 }else if( zFile==0 && eMode!='e' && eMode!='x' ){
9622 zFile = sqlite3_mprintf("%s", z);
drhe3e25652021-12-16 13:29:28 +00009623 if( zFile && zFile[0]=='|' ){
drh4b0229a2021-02-17 13:19:22 +00009624 while( i+1<nArg ) zFile = sqlite3_mprintf("%z %s", zFile, azArg[++i]);
9625 break;
9626 }
drh7a431002020-04-18 14:12:00 +00009627 }else{
9628 utf8_printf(p->out,"ERROR: extra parameter: \"%s\". Usage:\n",
9629 azArg[i]);
9630 showHelp(p->out, azArg[0]);
drh2ce15c32017-07-11 13:34:40 +00009631 rc = 1;
drh4b0229a2021-02-17 13:19:22 +00009632 sqlite3_free(zFile);
drh2ce15c32017-07-11 13:34:40 +00009633 goto meta_command_exit;
9634 }
drh7a431002020-04-18 14:12:00 +00009635 }
drhe3e25652021-12-16 13:29:28 +00009636 if( zFile==0 ){
9637 zFile = sqlite3_mprintf("stdout");
9638 }
drh7a431002020-04-18 14:12:00 +00009639 if( bOnce ){
drh2ce15c32017-07-11 13:34:40 +00009640 p->outCount = 2;
9641 }else{
9642 p->outCount = 0;
9643 }
9644 output_reset(p);
drh04a28c32018-01-31 01:38:44 +00009645#ifndef SQLITE_NOHAVE_SYSTEM
drh7a431002020-04-18 14:12:00 +00009646 if( eMode=='e' || eMode=='x' ){
drh3c484e82018-01-10 22:27:21 +00009647 p->doXdgOpen = 1;
9648 outputModePush(p);
drh7a431002020-04-18 14:12:00 +00009649 if( eMode=='x' ){
9650 /* spreadsheet mode. Output as CSV. */
drh13c20932018-01-10 21:41:55 +00009651 newTempFile(p, "csv");
drh7a431002020-04-18 14:12:00 +00009652 ShellClearFlag(p, SHFLG_Echo);
drh13c20932018-01-10 21:41:55 +00009653 p->mode = MODE_Csv;
9654 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Comma);
9655 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_CrLf);
9656 }else{
drh7a431002020-04-18 14:12:00 +00009657 /* text editor mode */
drh13c20932018-01-10 21:41:55 +00009658 newTempFile(p, "txt");
drha92a01a2018-01-10 22:15:37 +00009659 bTxtMode = 1;
drh13c20932018-01-10 21:41:55 +00009660 }
drh4b0229a2021-02-17 13:19:22 +00009661 sqlite3_free(zFile);
9662 zFile = sqlite3_mprintf("%s", p->zTempFile);
drh13c20932018-01-10 21:41:55 +00009663 }
drh04a28c32018-01-31 01:38:44 +00009664#endif /* SQLITE_NOHAVE_SYSTEM */
drhe3e25652021-12-16 13:29:28 +00009665 shell_check_oom(zFile);
drh2ce15c32017-07-11 13:34:40 +00009666 if( zFile[0]=='|' ){
9667#ifdef SQLITE_OMIT_POPEN
9668 raw_printf(stderr, "Error: pipes are not supported in this OS\n");
9669 rc = 1;
9670 p->out = stdout;
9671#else
9672 p->out = popen(zFile + 1, "w");
9673 if( p->out==0 ){
9674 utf8_printf(stderr,"Error: cannot open pipe \"%s\"\n", zFile + 1);
9675 p->out = stdout;
9676 rc = 1;
9677 }else{
drh7a431002020-04-18 14:12:00 +00009678 if( bBOM ) fprintf(p->out,"\357\273\277");
drh2ce15c32017-07-11 13:34:40 +00009679 sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", zFile);
9680 }
9681#endif
9682 }else{
drha92a01a2018-01-10 22:15:37 +00009683 p->out = output_file_open(zFile, bTxtMode);
drh2ce15c32017-07-11 13:34:40 +00009684 if( p->out==0 ){
9685 if( strcmp(zFile,"off")!=0 ){
9686 utf8_printf(stderr,"Error: cannot write to \"%s\"\n", zFile);
9687 }
9688 p->out = stdout;
9689 rc = 1;
9690 } else {
drh7a431002020-04-18 14:12:00 +00009691 if( bBOM ) fprintf(p->out,"\357\273\277");
drh2ce15c32017-07-11 13:34:40 +00009692 sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", zFile);
9693 }
9694 }
drh4b0229a2021-02-17 13:19:22 +00009695 sqlite3_free(zFile);
drh2ce15c32017-07-11 13:34:40 +00009696 }else
9697
drh9cb02642019-02-28 20:10:52 +00009698 if( c=='p' && n>=3 && strncmp(azArg[0], "parameter", n)==0 ){
9699 open_db(p,0);
9700 if( nArg<=1 ) goto parameter_syntax_error;
9701
9702 /* .parameter clear
9703 ** Clear all bind parameters by dropping the TEMP table that holds them.
9704 */
9705 if( nArg==2 && strcmp(azArg[1],"clear")==0 ){
drh65c29fd2019-03-25 21:56:26 +00009706 sqlite3_exec(p->db, "DROP TABLE IF EXISTS temp.sqlite_parameters;",
drh9cb02642019-02-28 20:10:52 +00009707 0, 0, 0);
9708 }else
9709
9710 /* .parameter list
9711 ** List all bind parameters.
9712 */
9713 if( nArg==2 && strcmp(azArg[1],"list")==0 ){
9714 sqlite3_stmt *pStmt = 0;
9715 int rx;
9716 int len = 0;
9717 rx = sqlite3_prepare_v2(p->db,
9718 "SELECT max(length(key)) "
drh65c29fd2019-03-25 21:56:26 +00009719 "FROM temp.sqlite_parameters;", -1, &pStmt, 0);
drh9cb02642019-02-28 20:10:52 +00009720 if( rx==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW ){
9721 len = sqlite3_column_int(pStmt, 0);
9722 if( len>40 ) len = 40;
9723 }
9724 sqlite3_finalize(pStmt);
9725 pStmt = 0;
9726 if( len ){
9727 rx = sqlite3_prepare_v2(p->db,
9728 "SELECT key, quote(value) "
drh65c29fd2019-03-25 21:56:26 +00009729 "FROM temp.sqlite_parameters;", -1, &pStmt, 0);
drhe85e1da2021-10-01 21:01:07 +00009730 while( rx==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW ){
drh9cb02642019-02-28 20:10:52 +00009731 utf8_printf(p->out, "%-*s %s\n", len, sqlite3_column_text(pStmt,0),
9732 sqlite3_column_text(pStmt,1));
9733 }
9734 sqlite3_finalize(pStmt);
9735 }
9736 }else
9737
9738 /* .parameter init
9739 ** Make sure the TEMP table used to hold bind parameters exists.
9740 ** Create it if necessary.
9741 */
9742 if( nArg==2 && strcmp(azArg[1],"init")==0 ){
9743 bind_table_init(p);
9744 }else
9745
9746 /* .parameter set NAME VALUE
9747 ** Set or reset a bind parameter. NAME should be the full parameter
9748 ** name exactly as it appears in the query. (ex: $abc, @def). The
9749 ** VALUE can be in either SQL literal notation, or if not it will be
9750 ** understood to be a text string.
9751 */
9752 if( nArg==4 && strcmp(azArg[1],"set")==0 ){
9753 int rx;
9754 char *zSql;
9755 sqlite3_stmt *pStmt;
9756 const char *zKey = azArg[2];
9757 const char *zValue = azArg[3];
9758 bind_table_init(p);
9759 zSql = sqlite3_mprintf(
drh65c29fd2019-03-25 21:56:26 +00009760 "REPLACE INTO temp.sqlite_parameters(key,value)"
drh9cb02642019-02-28 20:10:52 +00009761 "VALUES(%Q,%s);", zKey, zValue);
drhe3e25652021-12-16 13:29:28 +00009762 shell_check_oom(zSql);
drh9cb02642019-02-28 20:10:52 +00009763 pStmt = 0;
9764 rx = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
9765 sqlite3_free(zSql);
9766 if( rx!=SQLITE_OK ){
9767 sqlite3_finalize(pStmt);
9768 pStmt = 0;
9769 zSql = sqlite3_mprintf(
drh65c29fd2019-03-25 21:56:26 +00009770 "REPLACE INTO temp.sqlite_parameters(key,value)"
drh9cb02642019-02-28 20:10:52 +00009771 "VALUES(%Q,%Q);", zKey, zValue);
drhe3e25652021-12-16 13:29:28 +00009772 shell_check_oom(zSql);
drh9cb02642019-02-28 20:10:52 +00009773 rx = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
9774 sqlite3_free(zSql);
9775 if( rx!=SQLITE_OK ){
9776 utf8_printf(p->out, "Error: %s\n", sqlite3_errmsg(p->db));
9777 sqlite3_finalize(pStmt);
9778 pStmt = 0;
9779 rc = 1;
9780 }
9781 }
9782 sqlite3_step(pStmt);
9783 sqlite3_finalize(pStmt);
9784 }else
9785
9786 /* .parameter unset NAME
9787 ** Remove the NAME binding from the parameter binding table, if it
9788 ** exists.
9789 */
9790 if( nArg==3 && strcmp(azArg[1],"unset")==0 ){
9791 char *zSql = sqlite3_mprintf(
drh65c29fd2019-03-25 21:56:26 +00009792 "DELETE FROM temp.sqlite_parameters WHERE key=%Q", azArg[2]);
drhe3e25652021-12-16 13:29:28 +00009793 shell_check_oom(zSql);
drh9cb02642019-02-28 20:10:52 +00009794 sqlite3_exec(p->db, zSql, 0, 0, 0);
9795 sqlite3_free(zSql);
9796 }else
9797 /* If no command name matches, show a syntax error */
9798 parameter_syntax_error:
9799 showHelp(p->out, "parameter");
9800 }else
9801
drh2ce15c32017-07-11 13:34:40 +00009802 if( c=='p' && n>=3 && strncmp(azArg[0], "print", n)==0 ){
9803 int i;
9804 for(i=1; i<nArg; i++){
9805 if( i>1 ) raw_printf(p->out, " ");
9806 utf8_printf(p->out, "%s", azArg[i]);
9807 }
9808 raw_printf(p->out, "\n");
9809 }else
9810
drh569b1d92019-02-05 20:51:41 +00009811#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
drh3f83f592019-02-04 14:53:18 +00009812 if( c=='p' && n>=3 && strncmp(azArg[0], "progress", n)==0 ){
9813 int i;
drhfc4eeef2019-02-05 19:48:46 +00009814 int nn = 0;
drh3f83f592019-02-04 14:53:18 +00009815 p->flgProgress = 0;
9816 p->mxProgress = 0;
9817 p->nProgress = 0;
9818 for(i=1; i<nArg; i++){
9819 const char *z = azArg[i];
9820 if( z[0]=='-' ){
9821 z++;
9822 if( z[0]=='-' ) z++;
9823 if( strcmp(z,"quiet")==0 || strcmp(z,"q")==0 ){
drhfc4eeef2019-02-05 19:48:46 +00009824 p->flgProgress |= SHELL_PROGRESS_QUIET;
drh3f83f592019-02-04 14:53:18 +00009825 continue;
9826 }
9827 if( strcmp(z,"reset")==0 ){
drhfc4eeef2019-02-05 19:48:46 +00009828 p->flgProgress |= SHELL_PROGRESS_RESET;
drh3f83f592019-02-04 14:53:18 +00009829 continue;
9830 }
9831 if( strcmp(z,"once")==0 ){
drhfc4eeef2019-02-05 19:48:46 +00009832 p->flgProgress |= SHELL_PROGRESS_ONCE;
drh3f83f592019-02-04 14:53:18 +00009833 continue;
9834 }
9835 if( strcmp(z,"limit")==0 ){
9836 if( i+1>=nArg ){
9837 utf8_printf(stderr, "Error: missing argument on --limit\n");
9838 rc = 1;
9839 goto meta_command_exit;
9840 }else{
9841 p->mxProgress = (int)integerValue(azArg[++i]);
9842 }
9843 continue;
9844 }
9845 utf8_printf(stderr, "Error: unknown option: \"%s\"\n", azArg[i]);
9846 rc = 1;
9847 goto meta_command_exit;
9848 }else{
drhfc4eeef2019-02-05 19:48:46 +00009849 nn = (int)integerValue(z);
drh3f83f592019-02-04 14:53:18 +00009850 }
9851 }
9852 open_db(p, 0);
drhfc4eeef2019-02-05 19:48:46 +00009853 sqlite3_progress_handler(p->db, nn, progress_handler, p);
drh3f83f592019-02-04 14:53:18 +00009854 }else
drh569b1d92019-02-05 20:51:41 +00009855#endif /* SQLITE_OMIT_PROGRESS_CALLBACK */
drh3f83f592019-02-04 14:53:18 +00009856
drh2ce15c32017-07-11 13:34:40 +00009857 if( c=='p' && strncmp(azArg[0], "prompt", n)==0 ){
9858 if( nArg >= 2) {
9859 strncpy(mainPrompt,azArg[1],(int)ArraySize(mainPrompt)-1);
9860 }
9861 if( nArg >= 3) {
9862 strncpy(continuePrompt,azArg[2],(int)ArraySize(continuePrompt)-1);
9863 }
9864 }else
9865
9866 if( c=='q' && strncmp(azArg[0], "quit", n)==0 ){
9867 rc = 2;
9868 }else
9869
9870 if( c=='r' && n>=3 && strncmp(azArg[0], "read", n)==0 ){
drh60379d42018-12-13 18:30:01 +00009871 FILE *inSaved = p->in;
drh2c8ee022018-12-13 18:59:30 +00009872 int savedLineno = p->lineno;
drhb97e2ad2021-08-26 18:31:39 +00009873 failIfSafeMode(p, "cannot run .read in safe mode");
drh2ce15c32017-07-11 13:34:40 +00009874 if( nArg!=2 ){
9875 raw_printf(stderr, "Usage: .read FILE\n");
9876 rc = 1;
9877 goto meta_command_exit;
9878 }
drh30497f42020-08-26 10:50:48 +00009879 if( azArg[1][0]=='|' ){
drh9d59e3b2021-03-12 01:49:08 +00009880#ifdef SQLITE_OMIT_POPEN
9881 raw_printf(stderr, "Error: pipes are not supported in this OS\n");
9882 rc = 1;
9883 p->out = stdout;
9884#else
drh30497f42020-08-26 10:50:48 +00009885 p->in = popen(azArg[1]+1, "r");
9886 if( p->in==0 ){
9887 utf8_printf(stderr, "Error: cannot open \"%s\"\n", azArg[1]);
9888 rc = 1;
9889 }else{
9890 rc = process_input(p);
9891 pclose(p->in);
9892 }
drh9d59e3b2021-03-12 01:49:08 +00009893#endif
larrybrd96bcc72021-09-17 21:12:47 +00009894 }else if( (p->in = openChrSource(azArg[1]))==0 ){
drh2ce15c32017-07-11 13:34:40 +00009895 utf8_printf(stderr,"Error: cannot open \"%s\"\n", azArg[1]);
9896 rc = 1;
9897 }else{
drh60379d42018-12-13 18:30:01 +00009898 rc = process_input(p);
9899 fclose(p->in);
drh2ce15c32017-07-11 13:34:40 +00009900 }
drh60379d42018-12-13 18:30:01 +00009901 p->in = inSaved;
drh2c8ee022018-12-13 18:59:30 +00009902 p->lineno = savedLineno;
drh2ce15c32017-07-11 13:34:40 +00009903 }else
9904
9905 if( c=='r' && n>=3 && strncmp(azArg[0], "restore", n)==0 ){
9906 const char *zSrcFile;
9907 const char *zDb;
9908 sqlite3 *pSrc;
9909 sqlite3_backup *pBackup;
9910 int nTimeout = 0;
9911
drhb97e2ad2021-08-26 18:31:39 +00009912 failIfSafeMode(p, "cannot run .restore in safe mode");
drh2ce15c32017-07-11 13:34:40 +00009913 if( nArg==2 ){
9914 zSrcFile = azArg[1];
9915 zDb = "main";
9916 }else if( nArg==3 ){
9917 zSrcFile = azArg[2];
9918 zDb = azArg[1];
9919 }else{
9920 raw_printf(stderr, "Usage: .restore ?DB? FILE\n");
9921 rc = 1;
9922 goto meta_command_exit;
9923 }
9924 rc = sqlite3_open(zSrcFile, &pSrc);
9925 if( rc!=SQLITE_OK ){
9926 utf8_printf(stderr, "Error: cannot open \"%s\"\n", zSrcFile);
drh9e804032018-05-18 17:11:50 +00009927 close_db(pSrc);
drh2ce15c32017-07-11 13:34:40 +00009928 return 1;
9929 }
9930 open_db(p, 0);
9931 pBackup = sqlite3_backup_init(p->db, zDb, pSrc, "main");
9932 if( pBackup==0 ){
9933 utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
drh9e804032018-05-18 17:11:50 +00009934 close_db(pSrc);
drh2ce15c32017-07-11 13:34:40 +00009935 return 1;
9936 }
9937 while( (rc = sqlite3_backup_step(pBackup,100))==SQLITE_OK
9938 || rc==SQLITE_BUSY ){
9939 if( rc==SQLITE_BUSY ){
9940 if( nTimeout++ >= 3 ) break;
9941 sqlite3_sleep(100);
9942 }
9943 }
9944 sqlite3_backup_finish(pBackup);
9945 if( rc==SQLITE_DONE ){
9946 rc = 0;
9947 }else if( rc==SQLITE_BUSY || rc==SQLITE_LOCKED ){
9948 raw_printf(stderr, "Error: source database is busy\n");
9949 rc = 1;
9950 }else{
9951 utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
9952 rc = 1;
9953 }
drh9e804032018-05-18 17:11:50 +00009954 close_db(pSrc);
drh2ce15c32017-07-11 13:34:40 +00009955 }else
9956
drh2ce15c32017-07-11 13:34:40 +00009957 if( c=='s' && strncmp(azArg[0], "scanstats", n)==0 ){
9958 if( nArg==2 ){
mistachkinb71aa092018-01-23 00:05:18 +00009959 p->scanstatsOn = (u8)booleanValue(azArg[1]);
drh2ce15c32017-07-11 13:34:40 +00009960#ifndef SQLITE_ENABLE_STMT_SCANSTATUS
9961 raw_printf(stderr, "Warning: .scanstats not available in this build.\n");
9962#endif
9963 }else{
9964 raw_printf(stderr, "Usage: .scanstats on|off\n");
9965 rc = 1;
9966 }
9967 }else
9968
9969 if( c=='s' && strncmp(azArg[0], "schema", n)==0 ){
9970 ShellText sSelect;
9971 ShellState data;
9972 char *zErrMsg = 0;
drh667a2a22018-01-02 00:04:37 +00009973 const char *zDiv = "(";
drhceba7922018-01-01 21:28:25 +00009974 const char *zName = 0;
drh2ce15c32017-07-11 13:34:40 +00009975 int iSchema = 0;
drhceba7922018-01-01 21:28:25 +00009976 int bDebug = 0;
drhbbb29ec2020-10-12 14:56:47 +00009977 int bNoSystemTabs = 0;
drhceba7922018-01-01 21:28:25 +00009978 int ii;
drh2ce15c32017-07-11 13:34:40 +00009979
9980 open_db(p, 0);
9981 memcpy(&data, p, sizeof(data));
9982 data.showHeader = 0;
9983 data.cMode = data.mode = MODE_Semi;
9984 initText(&sSelect);
drhceba7922018-01-01 21:28:25 +00009985 for(ii=1; ii<nArg; ii++){
9986 if( optionMatch(azArg[ii],"indent") ){
9987 data.cMode = data.mode = MODE_Pretty;
9988 }else if( optionMatch(azArg[ii],"debug") ){
9989 bDebug = 1;
drhbbb29ec2020-10-12 14:56:47 +00009990 }else if( optionMatch(azArg[ii],"nosys") ){
9991 bNoSystemTabs = 1;
9992 }else if( azArg[ii][0]=='-' ){
9993 utf8_printf(stderr, "Unknown option: \"%s\"\n", azArg[ii]);
9994 rc = 1;
9995 goto meta_command_exit;
drhceba7922018-01-01 21:28:25 +00009996 }else if( zName==0 ){
9997 zName = azArg[ii];
drh2ce15c32017-07-11 13:34:40 +00009998 }else{
drhbbb29ec2020-10-12 14:56:47 +00009999 raw_printf(stderr, "Usage: .schema ?--indent? ?--nosys? ?LIKE-PATTERN?\n");
drhceba7922018-01-01 21:28:25 +000010000 rc = 1;
10001 goto meta_command_exit;
drh2ce15c32017-07-11 13:34:40 +000010002 }
drh2ce15c32017-07-11 13:34:40 +000010003 }
drhceba7922018-01-01 21:28:25 +000010004 if( zName!=0 ){
drh067b92b2020-06-19 15:24:12 +000010005 int isSchema = sqlite3_strlike(zName, "sqlite_master", '\\')==0
drh346a70c2020-06-15 20:27:35 +000010006 || sqlite3_strlike(zName, "sqlite_schema", '\\')==0
10007 || sqlite3_strlike(zName,"sqlite_temp_master", '\\')==0
10008 || sqlite3_strlike(zName,"sqlite_temp_schema", '\\')==0;
drh067b92b2020-06-19 15:24:12 +000010009 if( isSchema ){
drh2ce15c32017-07-11 13:34:40 +000010010 char *new_argv[2], *new_colv[2];
drhc22b7162018-01-01 20:11:23 +000010011 new_argv[0] = sqlite3_mprintf(
10012 "CREATE TABLE %s (\n"
drh2ce15c32017-07-11 13:34:40 +000010013 " type text,\n"
10014 " name text,\n"
10015 " tbl_name text,\n"
10016 " rootpage integer,\n"
10017 " sql text\n"
drh346a70c2020-06-15 20:27:35 +000010018 ")", zName);
drhe3e25652021-12-16 13:29:28 +000010019 shell_check_oom(new_argv[0]);
drh2ce15c32017-07-11 13:34:40 +000010020 new_argv[1] = 0;
10021 new_colv[0] = "sql";
10022 new_colv[1] = 0;
10023 callback(&data, 1, new_argv, new_colv);
drhc22b7162018-01-01 20:11:23 +000010024 sqlite3_free(new_argv[0]);
drh2ce15c32017-07-11 13:34:40 +000010025 }
drh2ce15c32017-07-11 13:34:40 +000010026 }
10027 if( zDiv ){
10028 sqlite3_stmt *pStmt = 0;
10029 rc = sqlite3_prepare_v2(p->db, "SELECT name FROM pragma_database_list",
10030 -1, &pStmt, 0);
10031 if( rc ){
10032 utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
10033 sqlite3_finalize(pStmt);
10034 rc = 1;
10035 goto meta_command_exit;
10036 }
10037 appendText(&sSelect, "SELECT sql FROM", 0);
10038 iSchema = 0;
10039 while( sqlite3_step(pStmt)==SQLITE_ROW ){
10040 const char *zDb = (const char*)sqlite3_column_text(pStmt, 0);
10041 char zScNum[30];
10042 sqlite3_snprintf(sizeof(zScNum), zScNum, "%d", ++iSchema);
10043 appendText(&sSelect, zDiv, 0);
10044 zDiv = " UNION ALL ";
drhceba7922018-01-01 21:28:25 +000010045 appendText(&sSelect, "SELECT shell_add_schema(sql,", 0);
10046 if( sqlite3_stricmp(zDb, "main")!=0 ){
drhea38f4f2019-07-13 17:21:47 +000010047 appendText(&sSelect, zDb, '\'');
drh2ce15c32017-07-11 13:34:40 +000010048 }else{
drhceba7922018-01-01 21:28:25 +000010049 appendText(&sSelect, "NULL", 0);
drh2ce15c32017-07-11 13:34:40 +000010050 }
drhceba7922018-01-01 21:28:25 +000010051 appendText(&sSelect, ",name) AS sql, type, tbl_name, name, rowid,", 0);
10052 appendText(&sSelect, zScNum, 0);
10053 appendText(&sSelect, " AS snum, ", 0);
10054 appendText(&sSelect, zDb, '\'');
10055 appendText(&sSelect, " AS sname FROM ", 0);
drhea38f4f2019-07-13 17:21:47 +000010056 appendText(&sSelect, zDb, quoteChar(zDb));
drh067b92b2020-06-19 15:24:12 +000010057 appendText(&sSelect, ".sqlite_schema", 0);
drh2ce15c32017-07-11 13:34:40 +000010058 }
10059 sqlite3_finalize(pStmt);
drhcc3f3d12019-08-17 15:27:58 +000010060#ifndef SQLITE_OMIT_INTROSPECTION_PRAGMAS
drh667a2a22018-01-02 00:04:37 +000010061 if( zName ){
10062 appendText(&sSelect,
10063 " UNION ALL SELECT shell_module_schema(name),"
drhe2754c12019-08-26 12:50:01 +000010064 " 'table', name, name, name, 9e+99, 'main' FROM pragma_module_list",
10065 0);
drh667a2a22018-01-02 00:04:37 +000010066 }
drhcde7b772018-01-02 12:50:40 +000010067#endif
drh2ce15c32017-07-11 13:34:40 +000010068 appendText(&sSelect, ") WHERE ", 0);
drhceba7922018-01-01 21:28:25 +000010069 if( zName ){
10070 char *zQarg = sqlite3_mprintf("%Q", zName);
mistachkinc158c072021-12-31 19:08:20 +000010071 int bGlob;
drhe3e25652021-12-16 13:29:28 +000010072 shell_check_oom(zQarg);
mistachkinc158c072021-12-31 19:08:20 +000010073 bGlob = strchr(zName, '*') != 0 || strchr(zName, '?') != 0 ||
10074 strchr(zName, '[') != 0;
drhceba7922018-01-01 21:28:25 +000010075 if( strchr(zName, '.') ){
drh2ce15c32017-07-11 13:34:40 +000010076 appendText(&sSelect, "lower(printf('%s.%s',sname,tbl_name))", 0);
10077 }else{
10078 appendText(&sSelect, "lower(tbl_name)", 0);
10079 }
mistachkin9d107262018-03-23 14:24:34 +000010080 appendText(&sSelect, bGlob ? " GLOB " : " LIKE ", 0);
drh2ce15c32017-07-11 13:34:40 +000010081 appendText(&sSelect, zQarg, 0);
mistachkin9d107262018-03-23 14:24:34 +000010082 if( !bGlob ){
10083 appendText(&sSelect, " ESCAPE '\\' ", 0);
10084 }
drh2ce15c32017-07-11 13:34:40 +000010085 appendText(&sSelect, " AND ", 0);
10086 sqlite3_free(zQarg);
10087 }
drhbbb29ec2020-10-12 14:56:47 +000010088 if( bNoSystemTabs ){
10089 appendText(&sSelect, "name NOT LIKE 'sqlite_%%' AND ", 0);
10090 }
10091 appendText(&sSelect, "sql IS NOT NULL"
drh2ce15c32017-07-11 13:34:40 +000010092 " ORDER BY snum, rowid", 0);
drhceba7922018-01-01 21:28:25 +000010093 if( bDebug ){
10094 utf8_printf(p->out, "SQL: %s;\n", sSelect.z);
10095 }else{
10096 rc = sqlite3_exec(p->db, sSelect.z, callback, &data, &zErrMsg);
10097 }
drh2ce15c32017-07-11 13:34:40 +000010098 freeText(&sSelect);
10099 }
10100 if( zErrMsg ){
10101 utf8_printf(stderr,"Error: %s\n", zErrMsg);
10102 sqlite3_free(zErrMsg);
10103 rc = 1;
10104 }else if( rc != SQLITE_OK ){
10105 raw_printf(stderr,"Error: querying schema information\n");
10106 rc = 1;
10107 }else{
10108 rc = 0;
10109 }
10110 }else
10111
drh2ce15c32017-07-11 13:34:40 +000010112 if( c=='s' && n==11 && strncmp(azArg[0], "selecttrace", n)==0 ){
drhfda8e492020-12-04 16:04:45 +000010113 unsigned int x = nArg>=2 ? (unsigned int)integerValue(azArg[1]) : 0xffffffff;
drhc0622a42020-12-04 01:17:57 +000010114 sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 1, &x);
drh2ce15c32017-07-11 13:34:40 +000010115 }else
drh2ce15c32017-07-11 13:34:40 +000010116
10117#if defined(SQLITE_ENABLE_SESSION)
10118 if( c=='s' && strncmp(azArg[0],"session",n)==0 && n>=3 ){
drh37407122021-07-23 18:43:58 +000010119 struct AuxDb *pAuxDb = p->pAuxDb;
10120 OpenSession *pSession = &pAuxDb->aSession[0];
drh2ce15c32017-07-11 13:34:40 +000010121 char **azCmd = &azArg[1];
10122 int iSes = 0;
10123 int nCmd = nArg - 1;
10124 int i;
10125 if( nArg<=1 ) goto session_syntax_error;
10126 open_db(p, 0);
10127 if( nArg>=3 ){
drh37407122021-07-23 18:43:58 +000010128 for(iSes=0; iSes<pAuxDb->nSession; iSes++){
10129 if( strcmp(pAuxDb->aSession[iSes].zName, azArg[1])==0 ) break;
drh2ce15c32017-07-11 13:34:40 +000010130 }
drh37407122021-07-23 18:43:58 +000010131 if( iSes<pAuxDb->nSession ){
10132 pSession = &pAuxDb->aSession[iSes];
drh2ce15c32017-07-11 13:34:40 +000010133 azCmd++;
10134 nCmd--;
10135 }else{
drh37407122021-07-23 18:43:58 +000010136 pSession = &pAuxDb->aSession[0];
drh2ce15c32017-07-11 13:34:40 +000010137 iSes = 0;
10138 }
10139 }
10140
10141 /* .session attach TABLE
10142 ** Invoke the sqlite3session_attach() interface to attach a particular
10143 ** table so that it is never filtered.
10144 */
10145 if( strcmp(azCmd[0],"attach")==0 ){
10146 if( nCmd!=2 ) goto session_syntax_error;
10147 if( pSession->p==0 ){
10148 session_not_open:
10149 raw_printf(stderr, "ERROR: No sessions are open\n");
10150 }else{
10151 rc = sqlite3session_attach(pSession->p, azCmd[1]);
10152 if( rc ){
10153 raw_printf(stderr, "ERROR: sqlite3session_attach() returns %d\n", rc);
10154 rc = 0;
10155 }
10156 }
10157 }else
10158
10159 /* .session changeset FILE
10160 ** .session patchset FILE
10161 ** Write a changeset or patchset into a file. The file is overwritten.
10162 */
10163 if( strcmp(azCmd[0],"changeset")==0 || strcmp(azCmd[0],"patchset")==0 ){
10164 FILE *out = 0;
drhb97e2ad2021-08-26 18:31:39 +000010165 failIfSafeMode(p, "cannot run \".session %s\" in safe mode", azCmd[0]);
drh2ce15c32017-07-11 13:34:40 +000010166 if( nCmd!=2 ) goto session_syntax_error;
10167 if( pSession->p==0 ) goto session_not_open;
10168 out = fopen(azCmd[1], "wb");
10169 if( out==0 ){
drhe2754c12019-08-26 12:50:01 +000010170 utf8_printf(stderr, "ERROR: cannot open \"%s\" for writing\n",
10171 azCmd[1]);
drh2ce15c32017-07-11 13:34:40 +000010172 }else{
10173 int szChng;
10174 void *pChng;
10175 if( azCmd[0][0]=='c' ){
10176 rc = sqlite3session_changeset(pSession->p, &szChng, &pChng);
10177 }else{
10178 rc = sqlite3session_patchset(pSession->p, &szChng, &pChng);
10179 }
10180 if( rc ){
10181 printf("Error: error code %d\n", rc);
10182 rc = 0;
10183 }
10184 if( pChng
10185 && fwrite(pChng, szChng, 1, out)!=1 ){
10186 raw_printf(stderr, "ERROR: Failed to write entire %d-byte output\n",
10187 szChng);
10188 }
10189 sqlite3_free(pChng);
10190 fclose(out);
10191 }
10192 }else
10193
10194 /* .session close
10195 ** Close the identified session
10196 */
10197 if( strcmp(azCmd[0], "close")==0 ){
10198 if( nCmd!=1 ) goto session_syntax_error;
drh37407122021-07-23 18:43:58 +000010199 if( pAuxDb->nSession ){
drh2ce15c32017-07-11 13:34:40 +000010200 session_close(pSession);
drh37407122021-07-23 18:43:58 +000010201 pAuxDb->aSession[iSes] = pAuxDb->aSession[--pAuxDb->nSession];
drh2ce15c32017-07-11 13:34:40 +000010202 }
10203 }else
10204
10205 /* .session enable ?BOOLEAN?
10206 ** Query or set the enable flag
10207 */
10208 if( strcmp(azCmd[0], "enable")==0 ){
10209 int ii;
10210 if( nCmd>2 ) goto session_syntax_error;
10211 ii = nCmd==1 ? -1 : booleanValue(azCmd[1]);
drh37407122021-07-23 18:43:58 +000010212 if( pAuxDb->nSession ){
drh2ce15c32017-07-11 13:34:40 +000010213 ii = sqlite3session_enable(pSession->p, ii);
10214 utf8_printf(p->out, "session %s enable flag = %d\n",
10215 pSession->zName, ii);
10216 }
10217 }else
10218
10219 /* .session filter GLOB ....
10220 ** Set a list of GLOB patterns of table names to be excluded.
10221 */
10222 if( strcmp(azCmd[0], "filter")==0 ){
10223 int ii, nByte;
10224 if( nCmd<2 ) goto session_syntax_error;
drh37407122021-07-23 18:43:58 +000010225 if( pAuxDb->nSession ){
drh2ce15c32017-07-11 13:34:40 +000010226 for(ii=0; ii<pSession->nFilter; ii++){
10227 sqlite3_free(pSession->azFilter[ii]);
10228 }
10229 sqlite3_free(pSession->azFilter);
10230 nByte = sizeof(pSession->azFilter[0])*(nCmd-1);
10231 pSession->azFilter = sqlite3_malloc( nByte );
10232 if( pSession->azFilter==0 ){
10233 raw_printf(stderr, "Error: out or memory\n");
10234 exit(1);
10235 }
10236 for(ii=1; ii<nCmd; ii++){
drhe3e25652021-12-16 13:29:28 +000010237 char *x = pSession->azFilter[ii-1] = sqlite3_mprintf("%s", azCmd[ii]);
10238 shell_check_oom(x);
drh2ce15c32017-07-11 13:34:40 +000010239 }
10240 pSession->nFilter = ii-1;
10241 }
10242 }else
10243
10244 /* .session indirect ?BOOLEAN?
10245 ** Query or set the indirect flag
10246 */
10247 if( strcmp(azCmd[0], "indirect")==0 ){
10248 int ii;
10249 if( nCmd>2 ) goto session_syntax_error;
10250 ii = nCmd==1 ? -1 : booleanValue(azCmd[1]);
drh37407122021-07-23 18:43:58 +000010251 if( pAuxDb->nSession ){
drh2ce15c32017-07-11 13:34:40 +000010252 ii = sqlite3session_indirect(pSession->p, ii);
10253 utf8_printf(p->out, "session %s indirect flag = %d\n",
10254 pSession->zName, ii);
10255 }
10256 }else
10257
10258 /* .session isempty
10259 ** Determine if the session is empty
10260 */
10261 if( strcmp(azCmd[0], "isempty")==0 ){
10262 int ii;
10263 if( nCmd!=1 ) goto session_syntax_error;
drh37407122021-07-23 18:43:58 +000010264 if( pAuxDb->nSession ){
drh2ce15c32017-07-11 13:34:40 +000010265 ii = sqlite3session_isempty(pSession->p);
10266 utf8_printf(p->out, "session %s isempty flag = %d\n",
10267 pSession->zName, ii);
10268 }
10269 }else
10270
10271 /* .session list
10272 ** List all currently open sessions
10273 */
10274 if( strcmp(azCmd[0],"list")==0 ){
drh37407122021-07-23 18:43:58 +000010275 for(i=0; i<pAuxDb->nSession; i++){
10276 utf8_printf(p->out, "%d %s\n", i, pAuxDb->aSession[i].zName);
drh2ce15c32017-07-11 13:34:40 +000010277 }
10278 }else
10279
10280 /* .session open DB NAME
10281 ** Open a new session called NAME on the attached database DB.
10282 ** DB is normally "main".
10283 */
10284 if( strcmp(azCmd[0],"open")==0 ){
10285 char *zName;
10286 if( nCmd!=3 ) goto session_syntax_error;
10287 zName = azCmd[2];
10288 if( zName[0]==0 ) goto session_syntax_error;
drh37407122021-07-23 18:43:58 +000010289 for(i=0; i<pAuxDb->nSession; i++){
10290 if( strcmp(pAuxDb->aSession[i].zName,zName)==0 ){
drh2ce15c32017-07-11 13:34:40 +000010291 utf8_printf(stderr, "Session \"%s\" already exists\n", zName);
10292 goto meta_command_exit;
10293 }
10294 }
drh37407122021-07-23 18:43:58 +000010295 if( pAuxDb->nSession>=ArraySize(pAuxDb->aSession) ){
10296 raw_printf(stderr, "Maximum of %d sessions\n", ArraySize(pAuxDb->aSession));
drh2ce15c32017-07-11 13:34:40 +000010297 goto meta_command_exit;
10298 }
drh37407122021-07-23 18:43:58 +000010299 pSession = &pAuxDb->aSession[pAuxDb->nSession];
drh2ce15c32017-07-11 13:34:40 +000010300 rc = sqlite3session_create(p->db, azCmd[1], &pSession->p);
10301 if( rc ){
10302 raw_printf(stderr, "Cannot open session: error code=%d\n", rc);
10303 rc = 0;
10304 goto meta_command_exit;
10305 }
10306 pSession->nFilter = 0;
10307 sqlite3session_table_filter(pSession->p, session_filter, pSession);
drh37407122021-07-23 18:43:58 +000010308 pAuxDb->nSession++;
drh2ce15c32017-07-11 13:34:40 +000010309 pSession->zName = sqlite3_mprintf("%s", zName);
drhe3e25652021-12-16 13:29:28 +000010310 shell_check_oom(pSession->zName);
drh2ce15c32017-07-11 13:34:40 +000010311 }else
10312 /* If no command name matches, show a syntax error */
10313 session_syntax_error:
drheb7f2a02018-09-26 18:02:32 +000010314 showHelp(p->out, "session");
drh2ce15c32017-07-11 13:34:40 +000010315 }else
10316#endif
10317
10318#ifdef SQLITE_DEBUG
10319 /* Undocumented commands for internal testing. Subject to change
10320 ** without notice. */
10321 if( c=='s' && n>=10 && strncmp(azArg[0], "selftest-", 9)==0 ){
10322 if( strncmp(azArg[0]+9, "boolean", n-9)==0 ){
10323 int i, v;
10324 for(i=1; i<nArg; i++){
10325 v = booleanValue(azArg[i]);
10326 utf8_printf(p->out, "%s: %d 0x%x\n", azArg[i], v, v);
10327 }
10328 }
10329 if( strncmp(azArg[0]+9, "integer", n-9)==0 ){
10330 int i; sqlite3_int64 v;
10331 for(i=1; i<nArg; i++){
10332 char zBuf[200];
10333 v = integerValue(azArg[i]);
10334 sqlite3_snprintf(sizeof(zBuf),zBuf,"%s: %lld 0x%llx\n", azArg[i],v,v);
10335 utf8_printf(p->out, "%s", zBuf);
10336 }
10337 }
10338 }else
10339#endif
10340
10341 if( c=='s' && n>=4 && strncmp(azArg[0],"selftest",n)==0 ){
10342 int bIsInit = 0; /* True to initialize the SELFTEST table */
10343 int bVerbose = 0; /* Verbose output */
10344 int bSelftestExists; /* True if SELFTEST already exists */
10345 int i, k; /* Loop counters */
10346 int nTest = 0; /* Number of tests runs */
10347 int nErr = 0; /* Number of errors seen */
10348 ShellText str; /* Answer for a query */
10349 sqlite3_stmt *pStmt = 0; /* Query against the SELFTEST table */
10350
10351 open_db(p,0);
10352 for(i=1; i<nArg; i++){
10353 const char *z = azArg[i];
10354 if( z[0]=='-' && z[1]=='-' ) z++;
10355 if( strcmp(z,"-init")==0 ){
10356 bIsInit = 1;
10357 }else
10358 if( strcmp(z,"-v")==0 ){
10359 bVerbose++;
10360 }else
10361 {
10362 utf8_printf(stderr, "Unknown option \"%s\" on \"%s\"\n",
10363 azArg[i], azArg[0]);
10364 raw_printf(stderr, "Should be one of: --init -v\n");
10365 rc = 1;
10366 goto meta_command_exit;
10367 }
10368 }
10369 if( sqlite3_table_column_metadata(p->db,"main","selftest",0,0,0,0,0,0)
10370 != SQLITE_OK ){
10371 bSelftestExists = 0;
10372 }else{
10373 bSelftestExists = 1;
10374 }
10375 if( bIsInit ){
10376 createSelftestTable(p);
10377 bSelftestExists = 1;
10378 }
10379 initText(&str);
10380 appendText(&str, "x", 0);
10381 for(k=bSelftestExists; k>=0; k--){
10382 if( k==1 ){
10383 rc = sqlite3_prepare_v2(p->db,
10384 "SELECT tno,op,cmd,ans FROM selftest ORDER BY tno",
10385 -1, &pStmt, 0);
10386 }else{
10387 rc = sqlite3_prepare_v2(p->db,
10388 "VALUES(0,'memo','Missing SELFTEST table - default checks only',''),"
10389 " (1,'run','PRAGMA integrity_check','ok')",
10390 -1, &pStmt, 0);
10391 }
10392 if( rc ){
10393 raw_printf(stderr, "Error querying the selftest table\n");
10394 rc = 1;
10395 sqlite3_finalize(pStmt);
10396 goto meta_command_exit;
10397 }
10398 for(i=1; sqlite3_step(pStmt)==SQLITE_ROW; i++){
10399 int tno = sqlite3_column_int(pStmt, 0);
10400 const char *zOp = (const char*)sqlite3_column_text(pStmt, 1);
10401 const char *zSql = (const char*)sqlite3_column_text(pStmt, 2);
10402 const char *zAns = (const char*)sqlite3_column_text(pStmt, 3);
10403
drh621a5e02021-12-16 17:35:27 +000010404 if( zOp==0 ) continue;
10405 if( zSql==0 ) continue;
10406 if( zAns==0 ) continue;
drh2ce15c32017-07-11 13:34:40 +000010407 k = 0;
10408 if( bVerbose>0 ){
drh2ce15c32017-07-11 13:34:40 +000010409 printf("%d: %s %s\n", tno, zOp, zSql);
drh2ce15c32017-07-11 13:34:40 +000010410 }
10411 if( strcmp(zOp,"memo")==0 ){
10412 utf8_printf(p->out, "%s\n", zSql);
10413 }else
10414 if( strcmp(zOp,"run")==0 ){
10415 char *zErrMsg = 0;
10416 str.n = 0;
10417 str.z[0] = 0;
10418 rc = sqlite3_exec(p->db, zSql, captureOutputCallback, &str, &zErrMsg);
10419 nTest++;
10420 if( bVerbose ){
10421 utf8_printf(p->out, "Result: %s\n", str.z);
10422 }
10423 if( rc || zErrMsg ){
10424 nErr++;
10425 rc = 1;
10426 utf8_printf(p->out, "%d: error-code-%d: %s\n", tno, rc, zErrMsg);
10427 sqlite3_free(zErrMsg);
10428 }else if( strcmp(zAns,str.z)!=0 ){
10429 nErr++;
10430 rc = 1;
10431 utf8_printf(p->out, "%d: Expected: [%s]\n", tno, zAns);
10432 utf8_printf(p->out, "%d: Got: [%s]\n", tno, str.z);
10433 }
10434 }else
10435 {
10436 utf8_printf(stderr,
10437 "Unknown operation \"%s\" on selftest line %d\n", zOp, tno);
10438 rc = 1;
10439 break;
10440 }
10441 } /* End loop over rows of content from SELFTEST */
10442 sqlite3_finalize(pStmt);
10443 } /* End loop over k */
10444 freeText(&str);
10445 utf8_printf(p->out, "%d errors out of %d tests\n", nErr, nTest);
10446 }else
10447
10448 if( c=='s' && strncmp(azArg[0], "separator", n)==0 ){
10449 if( nArg<2 || nArg>3 ){
10450 raw_printf(stderr, "Usage: .separator COL ?ROW?\n");
10451 rc = 1;
10452 }
10453 if( nArg>=2 ){
10454 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator,
10455 "%.*s", (int)ArraySize(p->colSeparator)-1, azArg[1]);
10456 }
10457 if( nArg>=3 ){
10458 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator,
10459 "%.*s", (int)ArraySize(p->rowSeparator)-1, azArg[2]);
10460 }
10461 }else
10462
10463 if( c=='s' && n>=4 && strncmp(azArg[0],"sha3sum",n)==0 ){
10464 const char *zLike = 0; /* Which table to checksum. 0 means everything */
10465 int i; /* Loop counter */
10466 int bSchema = 0; /* Also hash the schema */
10467 int bSeparate = 0; /* Hash each table separately */
10468 int iSize = 224; /* Hash algorithm to use */
10469 int bDebug = 0; /* Only show the query that would have run */
10470 sqlite3_stmt *pStmt; /* For querying tables names */
10471 char *zSql; /* SQL to be run */
10472 char *zSep; /* Separator */
10473 ShellText sSql; /* Complete SQL for the query to run the hash */
10474 ShellText sQuery; /* Set of queries used to read all content */
10475 open_db(p, 0);
10476 for(i=1; i<nArg; i++){
10477 const char *z = azArg[i];
10478 if( z[0]=='-' ){
10479 z++;
10480 if( z[0]=='-' ) z++;
10481 if( strcmp(z,"schema")==0 ){
10482 bSchema = 1;
10483 }else
10484 if( strcmp(z,"sha3-224")==0 || strcmp(z,"sha3-256")==0
10485 || strcmp(z,"sha3-384")==0 || strcmp(z,"sha3-512")==0
10486 ){
10487 iSize = atoi(&z[5]);
10488 }else
10489 if( strcmp(z,"debug")==0 ){
10490 bDebug = 1;
10491 }else
10492 {
10493 utf8_printf(stderr, "Unknown option \"%s\" on \"%s\"\n",
10494 azArg[i], azArg[0]);
drhe2754c12019-08-26 12:50:01 +000010495 showHelp(p->out, azArg[0]);
drh2ce15c32017-07-11 13:34:40 +000010496 rc = 1;
10497 goto meta_command_exit;
10498 }
10499 }else if( zLike ){
10500 raw_printf(stderr, "Usage: .sha3sum ?OPTIONS? ?LIKE-PATTERN?\n");
10501 rc = 1;
10502 goto meta_command_exit;
10503 }else{
10504 zLike = z;
10505 bSeparate = 1;
drhcedfecf2018-03-23 12:59:10 +000010506 if( sqlite3_strlike("sqlite\\_%", zLike, '\\')==0 ) bSchema = 1;
drh2ce15c32017-07-11 13:34:40 +000010507 }
10508 }
10509 if( bSchema ){
drh067b92b2020-06-19 15:24:12 +000010510 zSql = "SELECT lower(name) FROM sqlite_schema"
drh2ce15c32017-07-11 13:34:40 +000010511 " WHERE type='table' AND coalesce(rootpage,0)>1"
drh067b92b2020-06-19 15:24:12 +000010512 " UNION ALL SELECT 'sqlite_schema'"
drh2ce15c32017-07-11 13:34:40 +000010513 " ORDER BY 1 collate nocase";
10514 }else{
drh067b92b2020-06-19 15:24:12 +000010515 zSql = "SELECT lower(name) FROM sqlite_schema"
drh2ce15c32017-07-11 13:34:40 +000010516 " WHERE type='table' AND coalesce(rootpage,0)>1"
10517 " AND name NOT LIKE 'sqlite_%'"
10518 " ORDER BY 1 collate nocase";
10519 }
10520 sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
10521 initText(&sQuery);
10522 initText(&sSql);
10523 appendText(&sSql, "WITH [sha3sum$query](a,b) AS(",0);
10524 zSep = "VALUES(";
10525 while( SQLITE_ROW==sqlite3_step(pStmt) ){
10526 const char *zTab = (const char*)sqlite3_column_text(pStmt,0);
drh621a5e02021-12-16 17:35:27 +000010527 if( zTab==0 ) continue;
drh2ce15c32017-07-11 13:34:40 +000010528 if( zLike && sqlite3_strlike(zLike, zTab, 0)!=0 ) continue;
10529 if( strncmp(zTab, "sqlite_",7)!=0 ){
10530 appendText(&sQuery,"SELECT * FROM ", 0);
10531 appendText(&sQuery,zTab,'"');
10532 appendText(&sQuery," NOT INDEXED;", 0);
drh067b92b2020-06-19 15:24:12 +000010533 }else if( strcmp(zTab, "sqlite_schema")==0 ){
10534 appendText(&sQuery,"SELECT type,name,tbl_name,sql FROM sqlite_schema"
drh2ce15c32017-07-11 13:34:40 +000010535 " ORDER BY name;", 0);
10536 }else if( strcmp(zTab, "sqlite_sequence")==0 ){
10537 appendText(&sQuery,"SELECT name,seq FROM sqlite_sequence"
10538 " ORDER BY name;", 0);
10539 }else if( strcmp(zTab, "sqlite_stat1")==0 ){
10540 appendText(&sQuery,"SELECT tbl,idx,stat FROM sqlite_stat1"
10541 " ORDER BY tbl,idx;", 0);
drh175b8f02019-08-08 15:24:17 +000010542 }else if( strcmp(zTab, "sqlite_stat4")==0 ){
drh2ce15c32017-07-11 13:34:40 +000010543 appendText(&sQuery, "SELECT * FROM ", 0);
10544 appendText(&sQuery, zTab, 0);
10545 appendText(&sQuery, " ORDER BY tbl, idx, rowid;\n", 0);
10546 }
10547 appendText(&sSql, zSep, 0);
10548 appendText(&sSql, sQuery.z, '\'');
10549 sQuery.n = 0;
10550 appendText(&sSql, ",", 0);
10551 appendText(&sSql, zTab, '\'');
10552 zSep = "),(";
10553 }
10554 sqlite3_finalize(pStmt);
10555 if( bSeparate ){
10556 zSql = sqlite3_mprintf(
10557 "%s))"
10558 " SELECT lower(hex(sha3_query(a,%d))) AS hash, b AS label"
10559 " FROM [sha3sum$query]",
10560 sSql.z, iSize);
10561 }else{
10562 zSql = sqlite3_mprintf(
10563 "%s))"
10564 " SELECT lower(hex(sha3_query(group_concat(a,''),%d))) AS hash"
10565 " FROM [sha3sum$query]",
10566 sSql.z, iSize);
10567 }
drhe3e25652021-12-16 13:29:28 +000010568 shell_check_oom(zSql);
drh2ce15c32017-07-11 13:34:40 +000010569 freeText(&sQuery);
10570 freeText(&sSql);
10571 if( bDebug ){
10572 utf8_printf(p->out, "%s\n", zSql);
10573 }else{
drha10b9992018-03-09 15:24:33 +000010574 shell_exec(p, zSql, 0);
drh2ce15c32017-07-11 13:34:40 +000010575 }
10576 sqlite3_free(zSql);
10577 }else
10578
drh04a28c32018-01-31 01:38:44 +000010579#ifndef SQLITE_NOHAVE_SYSTEM
drh2ce15c32017-07-11 13:34:40 +000010580 if( c=='s'
10581 && (strncmp(azArg[0], "shell", n)==0 || strncmp(azArg[0],"system",n)==0)
10582 ){
10583 char *zCmd;
10584 int i, x;
drhb97e2ad2021-08-26 18:31:39 +000010585 failIfSafeMode(p, "cannot run .%s in safe mode", azArg[0]);
drh2ce15c32017-07-11 13:34:40 +000010586 if( nArg<2 ){
10587 raw_printf(stderr, "Usage: .system COMMAND\n");
10588 rc = 1;
10589 goto meta_command_exit;
10590 }
10591 zCmd = sqlite3_mprintf(strchr(azArg[1],' ')==0?"%s":"\"%s\"", azArg[1]);
drhe3e25652021-12-16 13:29:28 +000010592 for(i=2; i<nArg && zCmd!=0; i++){
drh2ce15c32017-07-11 13:34:40 +000010593 zCmd = sqlite3_mprintf(strchr(azArg[i],' ')==0?"%z %s":"%z \"%s\"",
10594 zCmd, azArg[i]);
10595 }
drhe3e25652021-12-16 13:29:28 +000010596 x = zCmd!=0 ? system(zCmd) : 1;
drh2ce15c32017-07-11 13:34:40 +000010597 sqlite3_free(zCmd);
10598 if( x ) raw_printf(stderr, "System command returns %d\n", x);
10599 }else
drh04a28c32018-01-31 01:38:44 +000010600#endif /* !defined(SQLITE_NOHAVE_SYSTEM) */
drh2ce15c32017-07-11 13:34:40 +000010601
10602 if( c=='s' && strncmp(azArg[0], "show", n)==0 ){
drhada70452017-12-21 21:02:27 +000010603 static const char *azBool[] = { "off", "on", "trigger", "full"};
drha6e6cf22021-01-09 19:10:04 +000010604 const char *zOut;
drh2ce15c32017-07-11 13:34:40 +000010605 int i;
10606 if( nArg!=1 ){
10607 raw_printf(stderr, "Usage: .show\n");
10608 rc = 1;
10609 goto meta_command_exit;
10610 }
10611 utf8_printf(p->out, "%12.12s: %s\n","echo",
10612 azBool[ShellHasFlag(p, SHFLG_Echo)]);
10613 utf8_printf(p->out, "%12.12s: %s\n","eqp", azBool[p->autoEQP&3]);
10614 utf8_printf(p->out, "%12.12s: %s\n","explain",
10615 p->mode==MODE_Explain ? "on" : p->autoExplain ? "auto" : "off");
10616 utf8_printf(p->out,"%12.12s: %s\n","headers", azBool[p->showHeader!=0]);
drhe40f2862022-01-31 14:14:29 +000010617 if( p->mode==MODE_Column
10618 || (p->mode>=MODE_Markdown && p->mode<=MODE_Box)
10619 ){
larrybrcc4d55c2022-02-01 02:50:45 +000010620 utf8_printf
10621 (p->out, "%12.12s: %s --wrap %d --wordwrap %s --%squote\n", "mode",
10622 modeDescr[p->mode], p->cmOpts.iWrap,
10623 p->cmOpts.bWordWrap ? "on" : "off",
10624 p->cmOpts.bQuote ? "" : "no");
drhe40f2862022-01-31 14:14:29 +000010625 }else{
10626 utf8_printf(p->out, "%12.12s: %s\n","mode", modeDescr[p->mode]);
10627 }
drh2ce15c32017-07-11 13:34:40 +000010628 utf8_printf(p->out, "%12.12s: ", "nullvalue");
10629 output_c_string(p->out, p->nullValue);
10630 raw_printf(p->out, "\n");
10631 utf8_printf(p->out,"%12.12s: %s\n","output",
10632 strlen30(p->outfile) ? p->outfile : "stdout");
10633 utf8_printf(p->out,"%12.12s: ", "colseparator");
10634 output_c_string(p->out, p->colSeparator);
10635 raw_printf(p->out, "\n");
10636 utf8_printf(p->out,"%12.12s: ", "rowseparator");
10637 output_c_string(p->out, p->rowSeparator);
10638 raw_printf(p->out, "\n");
drha6e6cf22021-01-09 19:10:04 +000010639 switch( p->statsOn ){
10640 case 0: zOut = "off"; break;
10641 default: zOut = "on"; break;
10642 case 2: zOut = "stmt"; break;
10643 case 3: zOut = "vmstep"; break;
10644 }
10645 utf8_printf(p->out, "%12.12s: %s\n","stats", zOut);
drh2ce15c32017-07-11 13:34:40 +000010646 utf8_printf(p->out, "%12.12s: ", "width");
drh0285d982020-05-29 14:38:43 +000010647 for (i=0;i<p->nWidth;i++) {
drh2ce15c32017-07-11 13:34:40 +000010648 raw_printf(p->out, "%d ", p->colWidth[i]);
10649 }
10650 raw_printf(p->out, "\n");
10651 utf8_printf(p->out, "%12.12s: %s\n", "filename",
drh37407122021-07-23 18:43:58 +000010652 p->pAuxDb->zDbFilename ? p->pAuxDb->zDbFilename : "");
drh2ce15c32017-07-11 13:34:40 +000010653 }else
10654
10655 if( c=='s' && strncmp(azArg[0], "stats", n)==0 ){
10656 if( nArg==2 ){
drha6e6cf22021-01-09 19:10:04 +000010657 if( strcmp(azArg[1],"stmt")==0 ){
10658 p->statsOn = 2;
10659 }else if( strcmp(azArg[1],"vmstep")==0 ){
10660 p->statsOn = 3;
10661 }else{
10662 p->statsOn = (u8)booleanValue(azArg[1]);
10663 }
drh2ce15c32017-07-11 13:34:40 +000010664 }else if( nArg==1 ){
10665 display_stats(p->db, p, 0);
10666 }else{
drha6e6cf22021-01-09 19:10:04 +000010667 raw_printf(stderr, "Usage: .stats ?on|off|stmt|vmstep?\n");
drh2ce15c32017-07-11 13:34:40 +000010668 rc = 1;
10669 }
10670 }else
10671
10672 if( (c=='t' && n>1 && strncmp(azArg[0], "tables", n)==0)
10673 || (c=='i' && (strncmp(azArg[0], "indices", n)==0
10674 || strncmp(azArg[0], "indexes", n)==0) )
10675 ){
10676 sqlite3_stmt *pStmt;
10677 char **azResult;
10678 int nRow, nAlloc;
10679 int ii;
10680 ShellText s;
10681 initText(&s);
10682 open_db(p, 0);
10683 rc = sqlite3_prepare_v2(p->db, "PRAGMA database_list", -1, &pStmt, 0);
drh9e804032018-05-18 17:11:50 +000010684 if( rc ){
10685 sqlite3_finalize(pStmt);
10686 return shellDatabaseError(p->db);
10687 }
drh2ce15c32017-07-11 13:34:40 +000010688
10689 if( nArg>2 && c=='i' ){
10690 /* It is an historical accident that the .indexes command shows an error
10691 ** when called with the wrong number of arguments whereas the .tables
10692 ** command does not. */
10693 raw_printf(stderr, "Usage: .indexes ?LIKE-PATTERN?\n");
10694 rc = 1;
drh9e804032018-05-18 17:11:50 +000010695 sqlite3_finalize(pStmt);
drh2ce15c32017-07-11 13:34:40 +000010696 goto meta_command_exit;
10697 }
10698 for(ii=0; sqlite3_step(pStmt)==SQLITE_ROW; ii++){
10699 const char *zDbName = (const char*)sqlite3_column_text(pStmt, 1);
10700 if( zDbName==0 ) continue;
10701 if( s.z && s.z[0] ) appendText(&s, " UNION ALL ", 0);
10702 if( sqlite3_stricmp(zDbName, "main")==0 ){
10703 appendText(&s, "SELECT name FROM ", 0);
10704 }else{
10705 appendText(&s, "SELECT ", 0);
10706 appendText(&s, zDbName, '\'');
10707 appendText(&s, "||'.'||name FROM ", 0);
10708 }
10709 appendText(&s, zDbName, '"');
drh067b92b2020-06-19 15:24:12 +000010710 appendText(&s, ".sqlite_schema ", 0);
drh2ce15c32017-07-11 13:34:40 +000010711 if( c=='t' ){
10712 appendText(&s," WHERE type IN ('table','view')"
10713 " AND name NOT LIKE 'sqlite_%'"
10714 " AND name LIKE ?1", 0);
10715 }else{
10716 appendText(&s," WHERE type='index'"
10717 " AND tbl_name LIKE ?1", 0);
10718 }
10719 }
10720 rc = sqlite3_finalize(pStmt);
drhe85e1da2021-10-01 21:01:07 +000010721 if( rc==SQLITE_OK ){
10722 appendText(&s, " ORDER BY 1", 0);
10723 rc = sqlite3_prepare_v2(p->db, s.z, -1, &pStmt, 0);
10724 }
drh2ce15c32017-07-11 13:34:40 +000010725 freeText(&s);
10726 if( rc ) return shellDatabaseError(p->db);
10727
10728 /* Run the SQL statement prepared by the above block. Store the results
10729 ** as an array of nul-terminated strings in azResult[]. */
10730 nRow = nAlloc = 0;
10731 azResult = 0;
10732 if( nArg>1 ){
10733 sqlite3_bind_text(pStmt, 1, azArg[1], -1, SQLITE_TRANSIENT);
10734 }else{
10735 sqlite3_bind_text(pStmt, 1, "%", -1, SQLITE_STATIC);
10736 }
10737 while( sqlite3_step(pStmt)==SQLITE_ROW ){
10738 if( nRow>=nAlloc ){
10739 char **azNew;
10740 int n2 = nAlloc*2 + 10;
10741 azNew = sqlite3_realloc64(azResult, sizeof(azResult[0])*n2);
drhe3e25652021-12-16 13:29:28 +000010742 shell_check_oom(azNew);
drh2ce15c32017-07-11 13:34:40 +000010743 nAlloc = n2;
10744 azResult = azNew;
10745 }
10746 azResult[nRow] = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 0));
drhe3e25652021-12-16 13:29:28 +000010747 shell_check_oom(azResult[nRow]);
drh2ce15c32017-07-11 13:34:40 +000010748 nRow++;
10749 }
10750 if( sqlite3_finalize(pStmt)!=SQLITE_OK ){
10751 rc = shellDatabaseError(p->db);
10752 }
10753
10754 /* Pretty-print the contents of array azResult[] to the output */
10755 if( rc==0 && nRow>0 ){
10756 int len, maxlen = 0;
10757 int i, j;
10758 int nPrintCol, nPrintRow;
10759 for(i=0; i<nRow; i++){
10760 len = strlen30(azResult[i]);
10761 if( len>maxlen ) maxlen = len;
10762 }
10763 nPrintCol = 80/(maxlen+2);
10764 if( nPrintCol<1 ) nPrintCol = 1;
10765 nPrintRow = (nRow + nPrintCol - 1)/nPrintCol;
10766 for(i=0; i<nPrintRow; i++){
10767 for(j=i; j<nRow; j+=nPrintRow){
10768 char *zSp = j<nPrintRow ? "" : " ";
10769 utf8_printf(p->out, "%s%-*s", zSp, maxlen,
10770 azResult[j] ? azResult[j]:"");
10771 }
10772 raw_printf(p->out, "\n");
10773 }
10774 }
10775
10776 for(ii=0; ii<nRow; ii++) sqlite3_free(azResult[ii]);
10777 sqlite3_free(azResult);
10778 }else
10779
10780 /* Begin redirecting output to the file "testcase-out.txt" */
10781 if( c=='t' && strcmp(azArg[0],"testcase")==0 ){
10782 output_reset(p);
drha92a01a2018-01-10 22:15:37 +000010783 p->out = output_file_open("testcase-out.txt", 0);
drh2ce15c32017-07-11 13:34:40 +000010784 if( p->out==0 ){
10785 raw_printf(stderr, "Error: cannot open 'testcase-out.txt'\n");
10786 }
10787 if( nArg>=2 ){
10788 sqlite3_snprintf(sizeof(p->zTestcase), p->zTestcase, "%s", azArg[1]);
10789 }else{
10790 sqlite3_snprintf(sizeof(p->zTestcase), p->zTestcase, "?");
10791 }
10792 }else
10793
10794#ifndef SQLITE_UNTESTABLE
drh35f51a42017-11-15 17:07:22 +000010795 if( c=='t' && n>=8 && strncmp(azArg[0], "testctrl", n)==0 ){
drh2ce15c32017-07-11 13:34:40 +000010796 static const struct {
10797 const char *zCtrlName; /* Name of a test-control option */
10798 int ctrlCode; /* Integer code for that option */
drh38ed1ce2021-12-06 15:24:36 +000010799 int unSafe; /* Not valid for --safe mode */
drhef302e82017-11-15 19:14:08 +000010800 const char *zUsage; /* Usage notes */
drh2ce15c32017-07-11 13:34:40 +000010801 } aCtrl[] = {
drh38ed1ce2021-12-06 15:24:36 +000010802 { "always", SQLITE_TESTCTRL_ALWAYS, 1, "BOOLEAN" },
10803 { "assert", SQLITE_TESTCTRL_ASSERT, 1, "BOOLEAN" },
10804 /*{ "benign_malloc_hooks",SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS,1, "" },*/
10805 /*{ "bitvec_test", SQLITE_TESTCTRL_BITVEC_TEST, 1, "" },*/
10806 { "byteorder", SQLITE_TESTCTRL_BYTEORDER, 0, "" },
10807 { "extra_schema_checks",SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS,0,"BOOLEAN" },
10808 /*{ "fault_install", SQLITE_TESTCTRL_FAULT_INSTALL, 1,"" },*/
10809 { "imposter", SQLITE_TESTCTRL_IMPOSTER,1,"SCHEMA ON/OFF ROOTPAGE"},
10810 { "internal_functions", SQLITE_TESTCTRL_INTERNAL_FUNCTIONS,0,"" },
10811 { "localtime_fault", SQLITE_TESTCTRL_LOCALTIME_FAULT,0,"BOOLEAN" },
10812 { "never_corrupt", SQLITE_TESTCTRL_NEVER_CORRUPT,1, "BOOLEAN" },
10813 { "optimizations", SQLITE_TESTCTRL_OPTIMIZATIONS,0,"DISABLE-MASK" },
drh0d9de992017-12-26 18:04:23 +000010814#ifdef YYCOVERAGE
drh38ed1ce2021-12-06 15:24:36 +000010815 { "parser_coverage", SQLITE_TESTCTRL_PARSER_COVERAGE,0,"" },
drh0d9de992017-12-26 18:04:23 +000010816#endif
drh38ed1ce2021-12-06 15:24:36 +000010817 { "pending_byte", SQLITE_TESTCTRL_PENDING_BYTE,0, "OFFSET " },
10818 { "prng_restore", SQLITE_TESTCTRL_PRNG_RESTORE,0, "" },
10819 { "prng_save", SQLITE_TESTCTRL_PRNG_SAVE, 0, "" },
10820 { "prng_seed", SQLITE_TESTCTRL_PRNG_SEED, 0, "SEED ?db?" },
10821 { "seek_count", SQLITE_TESTCTRL_SEEK_COUNT, 0, "" },
10822 { "sorter_mmap", SQLITE_TESTCTRL_SORTER_MMAP, 0, "NMAX" },
10823 { "tune", SQLITE_TESTCTRL_TUNE, 1, "ID VALUE" },
drh2ce15c32017-07-11 13:34:40 +000010824 };
10825 int testctrl = -1;
drhef302e82017-11-15 19:14:08 +000010826 int iCtrl = -1;
10827 int rc2 = 0; /* 0: usage. 1: %d 2: %x 3: no-output */
10828 int isOk = 0;
drh2ce15c32017-07-11 13:34:40 +000010829 int i, n2;
mistachkinc6bc15a2017-11-21 21:14:32 +000010830 const char *zCmd = 0;
10831
drh2ce15c32017-07-11 13:34:40 +000010832 open_db(p, 0);
mistachkinc6bc15a2017-11-21 21:14:32 +000010833 zCmd = nArg>=2 ? azArg[1] : "help";
drh35f51a42017-11-15 17:07:22 +000010834
10835 /* The argument can optionally begin with "-" or "--" */
10836 if( zCmd[0]=='-' && zCmd[1] ){
10837 zCmd++;
10838 if( zCmd[0]=='-' && zCmd[1] ) zCmd++;
10839 }
10840
10841 /* --help lists all test-controls */
10842 if( strcmp(zCmd,"help")==0 ){
10843 utf8_printf(p->out, "Available test-controls:\n");
10844 for(i=0; i<ArraySize(aCtrl); i++){
drhef302e82017-11-15 19:14:08 +000010845 utf8_printf(p->out, " .testctrl %s %s\n",
10846 aCtrl[i].zCtrlName, aCtrl[i].zUsage);
drh35f51a42017-11-15 17:07:22 +000010847 }
10848 rc = 1;
10849 goto meta_command_exit;
10850 }
drh2ce15c32017-07-11 13:34:40 +000010851
10852 /* convert testctrl text option to value. allow any unique prefix
10853 ** of the option name, or a numerical value. */
drh35f51a42017-11-15 17:07:22 +000010854 n2 = strlen30(zCmd);
drh2ce15c32017-07-11 13:34:40 +000010855 for(i=0; i<ArraySize(aCtrl); i++){
drh35f51a42017-11-15 17:07:22 +000010856 if( strncmp(zCmd, aCtrl[i].zCtrlName, n2)==0 ){
drh2ce15c32017-07-11 13:34:40 +000010857 if( testctrl<0 ){
10858 testctrl = aCtrl[i].ctrlCode;
drhef302e82017-11-15 19:14:08 +000010859 iCtrl = i;
drh2ce15c32017-07-11 13:34:40 +000010860 }else{
drh35f51a42017-11-15 17:07:22 +000010861 utf8_printf(stderr, "Error: ambiguous test-control: \"%s\"\n"
10862 "Use \".testctrl --help\" for help\n", zCmd);
10863 rc = 1;
10864 goto meta_command_exit;
drh2ce15c32017-07-11 13:34:40 +000010865 }
10866 }
10867 }
drhef302e82017-11-15 19:14:08 +000010868 if( testctrl<0 ){
drh35f51a42017-11-15 17:07:22 +000010869 utf8_printf(stderr,"Error: unknown test-control: %s\n"
10870 "Use \".testctrl --help\" for help\n", zCmd);
drh38ed1ce2021-12-06 15:24:36 +000010871 }else if( aCtrl[iCtrl].unSafe && p->bSafeMode ){
10872 utf8_printf(stderr,
10873 "line %d: \".testctrl %s\" may not be used in safe mode\n",
10874 p->lineno, aCtrl[iCtrl].zCtrlName);
10875 exit(1);
drh2ce15c32017-07-11 13:34:40 +000010876 }else{
10877 switch(testctrl){
10878
10879 /* sqlite3_test_control(int, db, int) */
10880 case SQLITE_TESTCTRL_OPTIMIZATIONS:
drh2ce15c32017-07-11 13:34:40 +000010881 if( nArg==3 ){
drhaf7b7652021-01-13 19:28:17 +000010882 unsigned int opt = (unsigned int)strtol(azArg[2], 0, 0);
drh2ce15c32017-07-11 13:34:40 +000010883 rc2 = sqlite3_test_control(testctrl, p->db, opt);
drhef302e82017-11-15 19:14:08 +000010884 isOk = 3;
drh2ce15c32017-07-11 13:34:40 +000010885 }
10886 break;
10887
10888 /* sqlite3_test_control(int) */
10889 case SQLITE_TESTCTRL_PRNG_SAVE:
10890 case SQLITE_TESTCTRL_PRNG_RESTORE:
drh2ce15c32017-07-11 13:34:40 +000010891 case SQLITE_TESTCTRL_BYTEORDER:
10892 if( nArg==2 ){
10893 rc2 = sqlite3_test_control(testctrl);
drhef302e82017-11-15 19:14:08 +000010894 isOk = testctrl==SQLITE_TESTCTRL_BYTEORDER ? 1 : 3;
drh2ce15c32017-07-11 13:34:40 +000010895 }
10896 break;
10897
10898 /* sqlite3_test_control(int, uint) */
10899 case SQLITE_TESTCTRL_PENDING_BYTE:
10900 if( nArg==3 ){
10901 unsigned int opt = (unsigned int)integerValue(azArg[2]);
10902 rc2 = sqlite3_test_control(testctrl, opt);
drhef302e82017-11-15 19:14:08 +000010903 isOk = 3;
drh2ce15c32017-07-11 13:34:40 +000010904 }
10905 break;
10906
drh2e6d83b2019-08-03 01:39:20 +000010907 /* sqlite3_test_control(int, int, sqlite3*) */
10908 case SQLITE_TESTCTRL_PRNG_SEED:
10909 if( nArg==3 || nArg==4 ){
drh51755a72019-08-08 19:40:29 +000010910 int ii = (int)integerValue(azArg[2]);
drh2e6d83b2019-08-03 01:39:20 +000010911 sqlite3 *db;
drh41428a92019-08-12 16:25:11 +000010912 if( ii==0 && strcmp(azArg[2],"random")==0 ){
10913 sqlite3_randomness(sizeof(ii),&ii);
10914 printf("-- random seed: %d\n", ii);
10915 }
drh2e6d83b2019-08-03 01:39:20 +000010916 if( nArg==3 ){
10917 db = 0;
10918 }else{
10919 db = p->db;
10920 /* Make sure the schema has been loaded */
10921 sqlite3_table_column_metadata(db, 0, "x", 0, 0, 0, 0, 0, 0);
10922 }
drh51755a72019-08-08 19:40:29 +000010923 rc2 = sqlite3_test_control(testctrl, ii, db);
drh2e6d83b2019-08-03 01:39:20 +000010924 isOk = 3;
10925 }
10926 break;
10927
drh2ce15c32017-07-11 13:34:40 +000010928 /* sqlite3_test_control(int, int) */
10929 case SQLITE_TESTCTRL_ASSERT:
10930 case SQLITE_TESTCTRL_ALWAYS:
drhef302e82017-11-15 19:14:08 +000010931 if( nArg==3 ){
10932 int opt = booleanValue(azArg[2]);
10933 rc2 = sqlite3_test_control(testctrl, opt);
10934 isOk = 1;
10935 }
10936 break;
10937
10938 /* sqlite3_test_control(int, int) */
10939 case SQLITE_TESTCTRL_LOCALTIME_FAULT:
drh2ce15c32017-07-11 13:34:40 +000010940 case SQLITE_TESTCTRL_NEVER_CORRUPT:
10941 if( nArg==3 ){
10942 int opt = booleanValue(azArg[2]);
10943 rc2 = sqlite3_test_control(testctrl, opt);
drhef302e82017-11-15 19:14:08 +000010944 isOk = 3;
drh2ce15c32017-07-11 13:34:40 +000010945 }
10946 break;
10947
drh171c50e2020-01-01 15:43:30 +000010948 /* sqlite3_test_control(sqlite3*) */
10949 case SQLITE_TESTCTRL_INTERNAL_FUNCTIONS:
10950 rc2 = sqlite3_test_control(testctrl, p->db);
drh2a83c102020-01-01 23:02:35 +000010951 isOk = 3;
drh171c50e2020-01-01 15:43:30 +000010952 break;
10953
drh2ce15c32017-07-11 13:34:40 +000010954 case SQLITE_TESTCTRL_IMPOSTER:
10955 if( nArg==5 ){
10956 rc2 = sqlite3_test_control(testctrl, p->db,
10957 azArg[2],
10958 integerValue(azArg[3]),
10959 integerValue(azArg[4]));
drhef302e82017-11-15 19:14:08 +000010960 isOk = 3;
drh2ce15c32017-07-11 13:34:40 +000010961 }
10962 break;
drh0d9de992017-12-26 18:04:23 +000010963
drh37ccfcf2020-08-31 18:49:04 +000010964 case SQLITE_TESTCTRL_SEEK_COUNT: {
10965 u64 x = 0;
10966 rc2 = sqlite3_test_control(testctrl, p->db, &x);
10967 utf8_printf(p->out, "%llu\n", x);
10968 isOk = 3;
10969 break;
10970 }
10971
drh0d9de992017-12-26 18:04:23 +000010972#ifdef YYCOVERAGE
drhf3c12562021-06-04 13:16:46 +000010973 case SQLITE_TESTCTRL_PARSER_COVERAGE: {
drh0d9de992017-12-26 18:04:23 +000010974 if( nArg==2 ){
10975 sqlite3_test_control(testctrl, p->out);
10976 isOk = 3;
10977 }
drhf3c12562021-06-04 13:16:46 +000010978 break;
10979 }
10980#endif
10981#ifdef SQLITE_DEBUG
10982 case SQLITE_TESTCTRL_TUNE: {
10983 if( nArg==4 ){
10984 int id = (int)integerValue(azArg[2]);
drh2d26cfc2021-06-04 13:40:26 +000010985 int val = (int)integerValue(azArg[3]);
10986 sqlite3_test_control(testctrl, id, &val);
10987 isOk = 3;
10988 }else if( nArg==3 ){
10989 int id = (int)integerValue(azArg[2]);
10990 sqlite3_test_control(testctrl, -id, &rc2);
10991 isOk = 1;
10992 }else if( nArg==2 ){
10993 int id = 1;
10994 while(1){
10995 int val = 0;
10996 rc2 = sqlite3_test_control(testctrl, -id, &val);
10997 if( rc2!=SQLITE_OK ) break;
10998 if( id>1 ) utf8_printf(p->out, " ");
10999 utf8_printf(p->out, "%d: %d", id, val);
11000 id++;
11001 }
11002 if( id>1 ) utf8_printf(p->out, "\n");
drhf3c12562021-06-04 13:16:46 +000011003 isOk = 3;
11004 }
11005 break;
11006 }
drh0d9de992017-12-26 18:04:23 +000011007#endif
dan779e9902021-07-28 18:13:28 +000011008 case SQLITE_TESTCTRL_SORTER_MMAP:
11009 if( nArg==3 ){
11010 int opt = (unsigned int)integerValue(azArg[2]);
11011 rc2 = sqlite3_test_control(testctrl, p->db, opt);
11012 isOk = 3;
11013 }
11014 break;
drh2ce15c32017-07-11 13:34:40 +000011015 }
11016 }
drhef302e82017-11-15 19:14:08 +000011017 if( isOk==0 && iCtrl>=0 ){
drhe2754c12019-08-26 12:50:01 +000011018 utf8_printf(p->out, "Usage: .testctrl %s %s\n", zCmd,aCtrl[iCtrl].zUsage);
drhef302e82017-11-15 19:14:08 +000011019 rc = 1;
11020 }else if( isOk==1 ){
11021 raw_printf(p->out, "%d\n", rc2);
11022 }else if( isOk==2 ){
11023 raw_printf(p->out, "0x%08x\n", rc2);
11024 }
drh2ce15c32017-07-11 13:34:40 +000011025 }else
11026#endif /* !defined(SQLITE_UNTESTABLE) */
11027
11028 if( c=='t' && n>4 && strncmp(azArg[0], "timeout", n)==0 ){
11029 open_db(p, 0);
11030 sqlite3_busy_timeout(p->db, nArg>=2 ? (int)integerValue(azArg[1]) : 0);
11031 }else
11032
11033 if( c=='t' && n>=5 && strncmp(azArg[0], "timer", n)==0 ){
11034 if( nArg==2 ){
11035 enableTimer = booleanValue(azArg[1]);
11036 if( enableTimer && !HAS_TIMER ){
11037 raw_printf(stderr, "Error: timer not available on this system.\n");
11038 enableTimer = 0;
11039 }
11040 }else{
11041 raw_printf(stderr, "Usage: .timer on|off\n");
11042 rc = 1;
11043 }
11044 }else
11045
drh707821f2018-12-05 13:39:06 +000011046#ifndef SQLITE_OMIT_TRACE
drh2ce15c32017-07-11 13:34:40 +000011047 if( c=='t' && strncmp(azArg[0], "trace", n)==0 ){
drh707821f2018-12-05 13:39:06 +000011048 int mType = 0;
11049 int jj;
drh2ce15c32017-07-11 13:34:40 +000011050 open_db(p, 0);
drh707821f2018-12-05 13:39:06 +000011051 for(jj=1; jj<nArg; jj++){
11052 const char *z = azArg[jj];
11053 if( z[0]=='-' ){
11054 if( optionMatch(z, "expanded") ){
11055 p->eTraceType = SHELL_TRACE_EXPANDED;
11056 }
11057#ifdef SQLITE_ENABLE_NORMALIZE
11058 else if( optionMatch(z, "normalized") ){
11059 p->eTraceType = SHELL_TRACE_NORMALIZED;
11060 }
11061#endif
11062 else if( optionMatch(z, "plain") ){
11063 p->eTraceType = SHELL_TRACE_PLAIN;
11064 }
11065 else if( optionMatch(z, "profile") ){
11066 mType |= SQLITE_TRACE_PROFILE;
11067 }
11068 else if( optionMatch(z, "row") ){
11069 mType |= SQLITE_TRACE_ROW;
11070 }
11071 else if( optionMatch(z, "stmt") ){
11072 mType |= SQLITE_TRACE_STMT;
11073 }
11074 else if( optionMatch(z, "close") ){
11075 mType |= SQLITE_TRACE_CLOSE;
11076 }
11077 else {
11078 raw_printf(stderr, "Unknown option \"%s\" on \".trace\"\n", z);
11079 rc = 1;
11080 goto meta_command_exit;
11081 }
11082 }else{
11083 output_file_close(p->traceOut);
11084 p->traceOut = output_file_open(azArg[1], 0);
11085 }
drh2ce15c32017-07-11 13:34:40 +000011086 }
drh2ce15c32017-07-11 13:34:40 +000011087 if( p->traceOut==0 ){
11088 sqlite3_trace_v2(p->db, 0, 0, 0);
11089 }else{
drh707821f2018-12-05 13:39:06 +000011090 if( mType==0 ) mType = SQLITE_TRACE_STMT;
11091 sqlite3_trace_v2(p->db, mType, sql_trace_callback, p);
drh2ce15c32017-07-11 13:34:40 +000011092 }
drh2ce15c32017-07-11 13:34:40 +000011093 }else
drh707821f2018-12-05 13:39:06 +000011094#endif /* !defined(SQLITE_OMIT_TRACE) */
drh2ce15c32017-07-11 13:34:40 +000011095
drhe2b7a762019-10-02 00:25:08 +000011096#if defined(SQLITE_DEBUG) && !defined(SQLITE_OMIT_VIRTUALTABLE)
drhcc5979d2019-08-16 22:58:29 +000011097 if( c=='u' && strncmp(azArg[0], "unmodule", n)==0 ){
11098 int ii;
drh8c754a32019-08-19 20:35:30 +000011099 int lenOpt;
drh5df84282019-08-17 19:45:25 +000011100 char *zOpt;
drhcc5979d2019-08-16 22:58:29 +000011101 if( nArg<2 ){
drh5df84282019-08-17 19:45:25 +000011102 raw_printf(stderr, "Usage: .unmodule [--allexcept] NAME ...\n");
drhcc5979d2019-08-16 22:58:29 +000011103 rc = 1;
11104 goto meta_command_exit;
11105 }
11106 open_db(p, 0);
drh5df84282019-08-17 19:45:25 +000011107 zOpt = azArg[1];
11108 if( zOpt[0]=='-' && zOpt[1]=='-' && zOpt[2]!=0 ) zOpt++;
drh8c754a32019-08-19 20:35:30 +000011109 lenOpt = (int)strlen(zOpt);
11110 if( lenOpt>=3 && strncmp(zOpt, "-allexcept",lenOpt)==0 ){
drh5df84282019-08-17 19:45:25 +000011111 assert( azArg[nArg]==0 );
drh8c754a32019-08-19 20:35:30 +000011112 sqlite3_drop_modules(p->db, nArg>2 ? (const char**)(azArg+2) : 0);
drh5df84282019-08-17 19:45:25 +000011113 }else{
11114 for(ii=1; ii<nArg; ii++){
11115 sqlite3_create_module(p->db, azArg[ii], 0, 0);
11116 }
drhcc5979d2019-08-16 22:58:29 +000011117 }
11118 }else
11119#endif
11120
drh2ce15c32017-07-11 13:34:40 +000011121#if SQLITE_USER_AUTHENTICATION
11122 if( c=='u' && strncmp(azArg[0], "user", n)==0 ){
11123 if( nArg<2 ){
11124 raw_printf(stderr, "Usage: .user SUBCOMMAND ...\n");
11125 rc = 1;
11126 goto meta_command_exit;
11127 }
11128 open_db(p, 0);
11129 if( strcmp(azArg[1],"login")==0 ){
11130 if( nArg!=4 ){
11131 raw_printf(stderr, "Usage: .user login USER PASSWORD\n");
11132 rc = 1;
11133 goto meta_command_exit;
11134 }
drhe2754c12019-08-26 12:50:01 +000011135 rc = sqlite3_user_authenticate(p->db, azArg[2], azArg[3],
11136 strlen30(azArg[3]));
drh2ce15c32017-07-11 13:34:40 +000011137 if( rc ){
11138 utf8_printf(stderr, "Authentication failed for user %s\n", azArg[2]);
11139 rc = 1;
11140 }
11141 }else if( strcmp(azArg[1],"add")==0 ){
11142 if( nArg!=5 ){
11143 raw_printf(stderr, "Usage: .user add USER PASSWORD ISADMIN\n");
11144 rc = 1;
11145 goto meta_command_exit;
11146 }
drhaf2770f2018-01-05 14:55:43 +000011147 rc = sqlite3_user_add(p->db, azArg[2], azArg[3], strlen30(azArg[3]),
drh2ce15c32017-07-11 13:34:40 +000011148 booleanValue(azArg[4]));
11149 if( rc ){
11150 raw_printf(stderr, "User-Add failed: %d\n", rc);
11151 rc = 1;
11152 }
11153 }else if( strcmp(azArg[1],"edit")==0 ){
11154 if( nArg!=5 ){
11155 raw_printf(stderr, "Usage: .user edit USER PASSWORD ISADMIN\n");
11156 rc = 1;
11157 goto meta_command_exit;
11158 }
drhaf2770f2018-01-05 14:55:43 +000011159 rc = sqlite3_user_change(p->db, azArg[2], azArg[3], strlen30(azArg[3]),
drh2ce15c32017-07-11 13:34:40 +000011160 booleanValue(azArg[4]));
11161 if( rc ){
11162 raw_printf(stderr, "User-Edit failed: %d\n", rc);
11163 rc = 1;
11164 }
11165 }else if( strcmp(azArg[1],"delete")==0 ){
11166 if( nArg!=3 ){
11167 raw_printf(stderr, "Usage: .user delete USER\n");
11168 rc = 1;
11169 goto meta_command_exit;
11170 }
11171 rc = sqlite3_user_delete(p->db, azArg[2]);
11172 if( rc ){
11173 raw_printf(stderr, "User-Delete failed: %d\n", rc);
11174 rc = 1;
11175 }
11176 }else{
11177 raw_printf(stderr, "Usage: .user login|add|edit|delete ...\n");
11178 rc = 1;
11179 goto meta_command_exit;
11180 }
11181 }else
11182#endif /* SQLITE_USER_AUTHENTICATION */
11183
11184 if( c=='v' && strncmp(azArg[0], "version", n)==0 ){
11185 utf8_printf(p->out, "SQLite %s %s\n" /*extra-version-info*/,
11186 sqlite3_libversion(), sqlite3_sourceid());
drh0ed2fd82018-01-16 20:05:27 +000011187#if SQLITE_HAVE_ZLIB
11188 utf8_printf(p->out, "zlib version %s\n", zlibVersion());
11189#endif
11190#define CTIMEOPT_VAL_(opt) #opt
11191#define CTIMEOPT_VAL(opt) CTIMEOPT_VAL_(opt)
11192#if defined(__clang__) && defined(__clang_major__)
11193 utf8_printf(p->out, "clang-" CTIMEOPT_VAL(__clang_major__) "."
11194 CTIMEOPT_VAL(__clang_minor__) "."
11195 CTIMEOPT_VAL(__clang_patchlevel__) "\n");
11196#elif defined(_MSC_VER)
11197 utf8_printf(p->out, "msvc-" CTIMEOPT_VAL(_MSC_VER) "\n");
11198#elif defined(__GNUC__) && defined(__VERSION__)
11199 utf8_printf(p->out, "gcc-" __VERSION__ "\n");
11200#endif
drh2ce15c32017-07-11 13:34:40 +000011201 }else
11202
11203 if( c=='v' && strncmp(azArg[0], "vfsinfo", n)==0 ){
11204 const char *zDbName = nArg==2 ? azArg[1] : "main";
11205 sqlite3_vfs *pVfs = 0;
11206 if( p->db ){
11207 sqlite3_file_control(p->db, zDbName, SQLITE_FCNTL_VFS_POINTER, &pVfs);
11208 if( pVfs ){
11209 utf8_printf(p->out, "vfs.zName = \"%s\"\n", pVfs->zName);
11210 raw_printf(p->out, "vfs.iVersion = %d\n", pVfs->iVersion);
11211 raw_printf(p->out, "vfs.szOsFile = %d\n", pVfs->szOsFile);
11212 raw_printf(p->out, "vfs.mxPathname = %d\n", pVfs->mxPathname);
11213 }
11214 }
11215 }else
11216
11217 if( c=='v' && strncmp(azArg[0], "vfslist", n)==0 ){
11218 sqlite3_vfs *pVfs;
11219 sqlite3_vfs *pCurrent = 0;
11220 if( p->db ){
11221 sqlite3_file_control(p->db, "main", SQLITE_FCNTL_VFS_POINTER, &pCurrent);
11222 }
11223 for(pVfs=sqlite3_vfs_find(0); pVfs; pVfs=pVfs->pNext){
11224 utf8_printf(p->out, "vfs.zName = \"%s\"%s\n", pVfs->zName,
11225 pVfs==pCurrent ? " <--- CURRENT" : "");
11226 raw_printf(p->out, "vfs.iVersion = %d\n", pVfs->iVersion);
11227 raw_printf(p->out, "vfs.szOsFile = %d\n", pVfs->szOsFile);
11228 raw_printf(p->out, "vfs.mxPathname = %d\n", pVfs->mxPathname);
11229 if( pVfs->pNext ){
11230 raw_printf(p->out, "-----------------------------------\n");
11231 }
11232 }
11233 }else
11234
11235 if( c=='v' && strncmp(azArg[0], "vfsname", n)==0 ){
11236 const char *zDbName = nArg==2 ? azArg[1] : "main";
11237 char *zVfsName = 0;
11238 if( p->db ){
11239 sqlite3_file_control(p->db, zDbName, SQLITE_FCNTL_VFSNAME, &zVfsName);
11240 if( zVfsName ){
11241 utf8_printf(p->out, "%s\n", zVfsName);
11242 sqlite3_free(zVfsName);
11243 }
11244 }
11245 }else
11246
drh2ce15c32017-07-11 13:34:40 +000011247 if( c=='w' && strncmp(azArg[0], "wheretrace", n)==0 ){
drhc0622a42020-12-04 01:17:57 +000011248 unsigned int x = nArg>=2 ? (unsigned int)integerValue(azArg[1]) : 0xffffffff;
11249 sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 3, &x);
drh2ce15c32017-07-11 13:34:40 +000011250 }else
drh2ce15c32017-07-11 13:34:40 +000011251
11252 if( c=='w' && strncmp(azArg[0], "width", n)==0 ){
11253 int j;
11254 assert( nArg<=ArraySize(azArg) );
drh0285d982020-05-29 14:38:43 +000011255 p->nWidth = nArg-1;
drh76fc88f2021-10-02 16:39:16 +000011256 p->colWidth = realloc(p->colWidth, (p->nWidth+1)*sizeof(int)*2);
drh0285d982020-05-29 14:38:43 +000011257 if( p->colWidth==0 && p->nWidth>0 ) shell_out_of_memory();
11258 if( p->nWidth ) p->actualWidth = &p->colWidth[p->nWidth];
11259 for(j=1; j<nArg; j++){
drh2ce15c32017-07-11 13:34:40 +000011260 p->colWidth[j-1] = (int)integerValue(azArg[j]);
11261 }
11262 }else
11263
11264 {
11265 utf8_printf(stderr, "Error: unknown command or invalid arguments: "
11266 " \"%s\". Enter \".help\" for help\n", azArg[0]);
11267 rc = 1;
11268 }
11269
11270meta_command_exit:
11271 if( p->outCount ){
11272 p->outCount--;
11273 if( p->outCount==0 ) output_reset(p);
11274 }
drhb97e2ad2021-08-26 18:31:39 +000011275 p->bSafeMode = p->bSafeModePersist;
drh2ce15c32017-07-11 13:34:40 +000011276 return rc;
11277}
11278
larrybr8bc4cbc2021-09-10 00:58:46 +000011279/* Line scan result and intermediate states (supporting scan resumption)
drh2ce15c32017-07-11 13:34:40 +000011280*/
drh68911c22021-09-22 14:26:22 +000011281#ifndef CHAR_BIT
11282# define CHAR_BIT 8
11283#endif
larrybr8bc4cbc2021-09-10 00:58:46 +000011284typedef enum {
larrybr7e009842021-09-18 21:35:22 +000011285 QSS_HasDark = 1<<CHAR_BIT, QSS_EndingSemi = 2<<CHAR_BIT,
11286 QSS_CharMask = (1<<CHAR_BIT)-1, QSS_ScanMask = 3<<CHAR_BIT,
larrybra96bbe92021-09-10 19:45:22 +000011287 QSS_Start = 0
larrybr8bc4cbc2021-09-10 00:58:46 +000011288} QuickScanState;
larrybr7e009842021-09-18 21:35:22 +000011289#define QSS_SETV(qss, newst) ((newst) | ((qss) & QSS_ScanMask))
11290#define QSS_INPLAIN(qss) (((qss)&QSS_CharMask)==QSS_Start)
11291#define QSS_PLAINWHITE(qss) (((qss)&~QSS_EndingSemi)==QSS_Start)
larrybra96bbe92021-09-10 19:45:22 +000011292#define QSS_PLAINDARK(qss) (((qss)&~QSS_EndingSemi)==QSS_HasDark)
larrybr7e009842021-09-18 21:35:22 +000011293#define QSS_SEMITERM(qss) (((qss)&~QSS_HasDark)==QSS_EndingSemi)
drh2ce15c32017-07-11 13:34:40 +000011294
11295/*
larrybr8bc4cbc2021-09-10 00:58:46 +000011296** Scan line for classification to guide shell's handling.
11297** The scan is resumable for subsequent lines when prior
11298** return values are passed as the 2nd argument.
drh2ce15c32017-07-11 13:34:40 +000011299*/
larrybr8bc4cbc2021-09-10 00:58:46 +000011300static QuickScanState quickscan(char *zLine, QuickScanState qss){
11301 char cin;
larrybr7e009842021-09-18 21:35:22 +000011302 char cWait = (char)qss; /* intentional narrowing loss */
11303 if( cWait==0 ){
11304 PlainScan:
drhe85e1da2021-10-01 21:01:07 +000011305 assert( cWait==0 );
drhfd7abcd2021-09-22 13:43:16 +000011306 while( (cin = *zLine++)!=0 ){
larrybr8bc4cbc2021-09-10 00:58:46 +000011307 if( IsSpace(cin) )
11308 continue;
11309 switch (cin){
11310 case '-':
larrybr7e009842021-09-18 21:35:22 +000011311 if( *zLine!='-' )
11312 break;
11313 while((cin = *++zLine)!=0 )
11314 if( cin=='\n')
11315 goto PlainScan;
11316 return qss;
larrybr8bc4cbc2021-09-10 00:58:46 +000011317 case ';':
larrybra96bbe92021-09-10 19:45:22 +000011318 qss |= QSS_EndingSemi;
11319 continue;
larrybr8bc4cbc2021-09-10 00:58:46 +000011320 case '/':
11321 if( *zLine=='*' ){
11322 ++zLine;
larrybr7e009842021-09-18 21:35:22 +000011323 cWait = '*';
11324 qss = QSS_SETV(qss, cWait);
11325 goto TermScan;
larrybr8bc4cbc2021-09-10 00:58:46 +000011326 }
11327 break;
larrybra96bbe92021-09-10 19:45:22 +000011328 case '[':
11329 cin = ']';
11330 /* fall thru */
11331 case '`': case '\'': case '"':
larrybr7e009842021-09-18 21:35:22 +000011332 cWait = cin;
11333 qss = QSS_HasDark | cWait;
11334 goto TermScan;
larrybr8bc4cbc2021-09-10 00:58:46 +000011335 default:
11336 break;
11337 }
larrybr7e009842021-09-18 21:35:22 +000011338 qss = (qss & ~QSS_EndingSemi) | QSS_HasDark;
drh2ce15c32017-07-11 13:34:40 +000011339 }
larrybr7e009842021-09-18 21:35:22 +000011340 }else{
11341 TermScan:
drhfd7abcd2021-09-22 13:43:16 +000011342 while( (cin = *zLine++)!=0 ){
larrybr7e009842021-09-18 21:35:22 +000011343 if( cin==cWait ){
11344 switch( cWait ){
11345 case '*':
11346 if( *zLine != '/' )
11347 continue;
11348 ++zLine;
11349 cWait = 0;
11350 qss = QSS_SETV(qss, 0);
11351 goto PlainScan;
11352 case '`': case '\'': case '"':
11353 if(*zLine==cWait){
larrybr8d463ce2021-09-11 02:42:04 +000011354 ++zLine;
larrybr7e009842021-09-18 21:35:22 +000011355 continue;
11356 }
11357 /* fall thru */
11358 case ']':
11359 cWait = 0;
11360 qss = QSS_SETV(qss, 0);
11361 goto PlainScan;
11362 default: assert(0);
larrybr8bc4cbc2021-09-10 00:58:46 +000011363 }
11364 }
11365 }
drh2ce15c32017-07-11 13:34:40 +000011366 }
larrybr8bc4cbc2021-09-10 00:58:46 +000011367 return qss;
drh2ce15c32017-07-11 13:34:40 +000011368}
11369
11370/*
11371** Return TRUE if the line typed in is an SQL command terminator other
11372** than a semi-colon. The SQL Server style "go" command is understood
11373** as is the Oracle "/".
11374*/
larrybr8bc4cbc2021-09-10 00:58:46 +000011375static int line_is_command_terminator(char *zLine){
drh2ce15c32017-07-11 13:34:40 +000011376 while( IsSpace(zLine[0]) ){ zLine++; };
larrybr8bc4cbc2021-09-10 00:58:46 +000011377 if( zLine[0]=='/' )
11378 zLine += 1; /* Oracle */
11379 else if ( ToLower(zLine[0])=='g' && ToLower(zLine[1])=='o' )
11380 zLine += 2; /* SQL Server */
11381 else
11382 return 0;
larrybra96bbe92021-09-10 19:45:22 +000011383 return quickscan(zLine,QSS_Start)==QSS_Start;
drh2ce15c32017-07-11 13:34:40 +000011384}
11385
11386/*
drh56f17742018-01-24 01:58:49 +000011387** We need a default sqlite3_complete() implementation to use in case
11388** the shell is compiled with SQLITE_OMIT_COMPLETE. The default assumes
11389** any arbitrary text is a complete SQL statement. This is not very
11390** user-friendly, but it does seem to work.
11391*/
11392#ifdef SQLITE_OMIT_COMPLETE
danc86b23b2018-11-16 14:36:42 +000011393#define sqlite3_complete(x) 1
drh56f17742018-01-24 01:58:49 +000011394#endif
11395
11396/*
drh2ce15c32017-07-11 13:34:40 +000011397** Return true if zSql is a complete SQL statement. Return false if it
11398** ends in the middle of a string literal or C-style comment.
11399*/
11400static int line_is_complete(char *zSql, int nSql){
11401 int rc;
11402 if( zSql==0 ) return 1;
11403 zSql[nSql] = ';';
11404 zSql[nSql+1] = 0;
11405 rc = sqlite3_complete(zSql);
11406 zSql[nSql] = 0;
11407 return rc;
11408}
11409
11410/*
drhfc29a862018-05-11 19:11:18 +000011411** Run a single line of SQL. Return the number of errors.
drh2ce15c32017-07-11 13:34:40 +000011412*/
11413static int runOneSqlLine(ShellState *p, char *zSql, FILE *in, int startline){
11414 int rc;
11415 char *zErrMsg = 0;
11416
11417 open_db(p, 0);
11418 if( ShellHasFlag(p,SHFLG_Backslash) ) resolve_backslashes(zSql);
drhfc4eeef2019-02-05 19:48:46 +000011419 if( p->flgProgress & SHELL_PROGRESS_RESET ) p->nProgress = 0;
drh2ce15c32017-07-11 13:34:40 +000011420 BEGIN_TIMER;
drha10b9992018-03-09 15:24:33 +000011421 rc = shell_exec(p, zSql, &zErrMsg);
drh2ce15c32017-07-11 13:34:40 +000011422 END_TIMER;
11423 if( rc || zErrMsg ){
11424 char zPrefix[100];
drh3e46db22022-02-08 11:52:45 +000011425 const char *zErrorTail;
11426 const char *zErrorType;
11427 if( zErrMsg==0 ){
11428 zErrorType = "Error";
11429 zErrorTail = sqlite3_errmsg(p->db);
11430 }else if( strncmp(zErrMsg, "in prepare, ",12)==0 ){
11431 zErrorType = "Parse error";
11432 zErrorTail = &zErrMsg[12];
11433 }else if( strncmp(zErrMsg, "stepping, ", 10)==0 ){
11434 zErrorType = "Runtime error";
11435 zErrorTail = &zErrMsg[10];
11436 }else{
11437 zErrorType = "Error";
11438 zErrorTail = zErrMsg;
11439 }
drh2ce15c32017-07-11 13:34:40 +000011440 if( in!=0 || !stdin_is_interactive ){
11441 sqlite3_snprintf(sizeof(zPrefix), zPrefix,
drh3e46db22022-02-08 11:52:45 +000011442 "%s near line %d:", zErrorType, startline);
drh2ce15c32017-07-11 13:34:40 +000011443 }else{
drh3e46db22022-02-08 11:52:45 +000011444 sqlite3_snprintf(sizeof(zPrefix), zPrefix, "%s:", zErrorType);
drh2ce15c32017-07-11 13:34:40 +000011445 }
drh3e46db22022-02-08 11:52:45 +000011446 utf8_printf(stderr, "%s %s\n", zPrefix, zErrorTail);
11447 sqlite3_free(zErrMsg);
11448 zErrMsg = 0;
drh2ce15c32017-07-11 13:34:40 +000011449 return 1;
11450 }else if( ShellHasFlag(p, SHFLG_CountChanges) ){
drh6d9f0342021-09-22 10:28:50 +000011451 char zLineBuf[2000];
11452 sqlite3_snprintf(sizeof(zLineBuf), zLineBuf,
11453 "changes: %lld total_changes: %lld",
larrybr10496f72021-06-23 16:07:20 +000011454 sqlite3_changes64(p->db), sqlite3_total_changes64(p->db));
drh6d9f0342021-09-22 10:28:50 +000011455 raw_printf(p->out, "%s\n", zLineBuf);
drh2ce15c32017-07-11 13:34:40 +000011456 }
11457 return 0;
11458}
11459
11460
11461/*
11462** Read input from *in and process it. If *in==0 then input
11463** is interactive - the user is typing it it. Otherwise, input
11464** is coming from a file or device. A prompt is issued and history
11465** is saved only if input is interactive. An interrupt signal will
11466** cause this routine to exit immediately, unless input is interactive.
11467**
11468** Return the number of errors.
11469*/
drh60379d42018-12-13 18:30:01 +000011470static int process_input(ShellState *p){
drh2ce15c32017-07-11 13:34:40 +000011471 char *zLine = 0; /* A single input line */
11472 char *zSql = 0; /* Accumulated SQL text */
11473 int nLine; /* Length of current line */
11474 int nSql = 0; /* Bytes of zSql[] used */
11475 int nAlloc = 0; /* Allocated zSql[] space */
drh2ce15c32017-07-11 13:34:40 +000011476 int rc; /* Error code */
11477 int errCnt = 0; /* Number of errors seen */
drh2ce15c32017-07-11 13:34:40 +000011478 int startline = 0; /* Line number for start of current input */
larrybr7e009842021-09-18 21:35:22 +000011479 QuickScanState qss = QSS_Start; /* Accumulated line status (so far) */
drh2ce15c32017-07-11 13:34:40 +000011480
larrybrd48e88e2022-01-24 06:36:16 +000011481 if( p->inputNesting==MAX_INPUT_NESTING ){
11482 /* This will be more informative in a later version. */
11483 utf8_printf(stderr,"Input nesting limit (%d) reached at line %d."
11484 " Check recursion.\n", MAX_INPUT_NESTING, p->lineno);
11485 return 1;
11486 }
11487 ++p->inputNesting;
drh2c8ee022018-12-13 18:59:30 +000011488 p->lineno = 0;
drh60379d42018-12-13 18:30:01 +000011489 while( errCnt==0 || !bail_on_error || (p->in==0 && stdin_is_interactive) ){
drh2ce15c32017-07-11 13:34:40 +000011490 fflush(p->out);
drh60379d42018-12-13 18:30:01 +000011491 zLine = one_input_line(p->in, zLine, nSql>0);
drh2ce15c32017-07-11 13:34:40 +000011492 if( zLine==0 ){
11493 /* End of input */
drh60379d42018-12-13 18:30:01 +000011494 if( p->in==0 && stdin_is_interactive ) printf("\n");
drh2ce15c32017-07-11 13:34:40 +000011495 break;
11496 }
11497 if( seenInterrupt ){
drh60379d42018-12-13 18:30:01 +000011498 if( p->in!=0 ) break;
drh2ce15c32017-07-11 13:34:40 +000011499 seenInterrupt = 0;
11500 }
drh2c8ee022018-12-13 18:59:30 +000011501 p->lineno++;
larrybr7e009842021-09-18 21:35:22 +000011502 if( QSS_INPLAIN(qss)
larrybr8bc4cbc2021-09-10 00:58:46 +000011503 && line_is_command_terminator(zLine)
11504 && line_is_complete(zSql, nSql) ){
11505 memcpy(zLine,";",2);
11506 }
11507 qss = quickscan(zLine, qss);
11508 if( QSS_PLAINWHITE(qss) && nSql==0 ){
11509 if( ShellHasFlag(p, SHFLG_Echo) )
11510 printf("%s\n", zLine);
larrybrd797d6b2021-10-03 22:03:59 +000011511 /* Just swallow single-line whitespace */
11512 qss = QSS_Start;
larrybr8bc4cbc2021-09-10 00:58:46 +000011513 continue;
drh2ce15c32017-07-11 13:34:40 +000011514 }
drh1615c372018-05-12 23:56:22 +000011515 if( zLine && (zLine[0]=='.' || zLine[0]=='#') && nSql==0 ){
drh2ce15c32017-07-11 13:34:40 +000011516 if( ShellHasFlag(p, SHFLG_Echo) ) printf("%s\n", zLine);
drh1615c372018-05-12 23:56:22 +000011517 if( zLine[0]=='.' ){
11518 rc = do_meta_command(zLine, p);
11519 if( rc==2 ){ /* exit requested */
11520 break;
11521 }else if( rc ){
11522 errCnt++;
11523 }
drh2ce15c32017-07-11 13:34:40 +000011524 }
larrybr81012162021-10-02 15:34:52 +000011525 qss = QSS_Start;
drh2ce15c32017-07-11 13:34:40 +000011526 continue;
11527 }
larrybrd797d6b2021-10-03 22:03:59 +000011528 /* No single-line dispositions remain; accumulate line(s). */
drh2ce15c32017-07-11 13:34:40 +000011529 nLine = strlen30(zLine);
11530 if( nSql+nLine+2>=nAlloc ){
larrybr31bffb42021-09-08 21:49:03 +000011531 /* Grow buffer by half-again increments when big. */
11532 nAlloc = nSql+(nSql>>1)+nLine+100;
drh2ce15c32017-07-11 13:34:40 +000011533 zSql = realloc(zSql, nAlloc);
drhe3e25652021-12-16 13:29:28 +000011534 shell_check_oom(zSql);
drh2ce15c32017-07-11 13:34:40 +000011535 }
drh2ce15c32017-07-11 13:34:40 +000011536 if( nSql==0 ){
11537 int i;
11538 for(i=0; zLine[i] && IsSpace(zLine[i]); i++){}
11539 assert( nAlloc>0 && zSql!=0 );
11540 memcpy(zSql, zLine+i, nLine+1-i);
drh2c8ee022018-12-13 18:59:30 +000011541 startline = p->lineno;
drh2ce15c32017-07-11 13:34:40 +000011542 nSql = nLine-i;
11543 }else{
11544 zSql[nSql++] = '\n';
11545 memcpy(zSql+nSql, zLine, nLine+1);
11546 nSql += nLine;
11547 }
larrybra96bbe92021-09-10 19:45:22 +000011548 if( nSql && QSS_SEMITERM(qss) && sqlite3_complete(zSql) ){
drh60379d42018-12-13 18:30:01 +000011549 errCnt += runOneSqlLine(p, zSql, p->in, startline);
drh2ce15c32017-07-11 13:34:40 +000011550 nSql = 0;
11551 if( p->outCount ){
11552 output_reset(p);
11553 p->outCount = 0;
drh13c20932018-01-10 21:41:55 +000011554 }else{
11555 clearTempFile(p);
drh2ce15c32017-07-11 13:34:40 +000011556 }
drhb97e2ad2021-08-26 18:31:39 +000011557 p->bSafeMode = p->bSafeModePersist;
larrybrd797d6b2021-10-03 22:03:59 +000011558 qss = QSS_Start;
larrybr8bc4cbc2021-09-10 00:58:46 +000011559 }else if( nSql && QSS_PLAINWHITE(qss) ){
drh2ce15c32017-07-11 13:34:40 +000011560 if( ShellHasFlag(p, SHFLG_Echo) ) printf("%s\n", zSql);
11561 nSql = 0;
larrybrd797d6b2021-10-03 22:03:59 +000011562 qss = QSS_Start;
drh2ce15c32017-07-11 13:34:40 +000011563 }
11564 }
larrybrc6e2f2e2022-03-15 17:57:42 +000011565 if( nSql ){
11566 /* This may be incomplete. Let the SQL parser deal with that. */
drh60379d42018-12-13 18:30:01 +000011567 errCnt += runOneSqlLine(p, zSql, p->in, startline);
drh2ce15c32017-07-11 13:34:40 +000011568 }
11569 free(zSql);
11570 free(zLine);
larrybrd48e88e2022-01-24 06:36:16 +000011571 --p->inputNesting;
drh2ce15c32017-07-11 13:34:40 +000011572 return errCnt>0;
11573}
11574
11575/*
11576** Return a pathname which is the user's home directory. A
11577** 0 return indicates an error of some kind.
11578*/
11579static char *find_home_dir(int clearFlag){
11580 static char *home_dir = NULL;
11581 if( clearFlag ){
11582 free(home_dir);
11583 home_dir = 0;
11584 return 0;
11585 }
11586 if( home_dir ) return home_dir;
11587
11588#if !defined(_WIN32) && !defined(WIN32) && !defined(_WIN32_WCE) \
11589 && !defined(__RTP__) && !defined(_WRS_KERNEL)
11590 {
11591 struct passwd *pwent;
11592 uid_t uid = getuid();
11593 if( (pwent=getpwuid(uid)) != NULL) {
11594 home_dir = pwent->pw_dir;
11595 }
11596 }
11597#endif
11598
11599#if defined(_WIN32_WCE)
11600 /* Windows CE (arm-wince-mingw32ce-gcc) does not provide getenv()
11601 */
11602 home_dir = "/";
11603#else
11604
11605#if defined(_WIN32) || defined(WIN32)
11606 if (!home_dir) {
11607 home_dir = getenv("USERPROFILE");
11608 }
11609#endif
11610
11611 if (!home_dir) {
11612 home_dir = getenv("HOME");
11613 }
11614
11615#if defined(_WIN32) || defined(WIN32)
11616 if (!home_dir) {
11617 char *zDrive, *zPath;
11618 int n;
11619 zDrive = getenv("HOMEDRIVE");
11620 zPath = getenv("HOMEPATH");
11621 if( zDrive && zPath ){
11622 n = strlen30(zDrive) + strlen30(zPath) + 1;
11623 home_dir = malloc( n );
11624 if( home_dir==0 ) return 0;
11625 sqlite3_snprintf(n, home_dir, "%s%s", zDrive, zPath);
11626 return home_dir;
11627 }
11628 home_dir = "c:\\";
11629 }
11630#endif
11631
11632#endif /* !_WIN32_WCE */
11633
11634 if( home_dir ){
11635 int n = strlen30(home_dir) + 1;
11636 char *z = malloc( n );
11637 if( z ) memcpy(z, home_dir, n);
11638 home_dir = z;
11639 }
11640
11641 return home_dir;
11642}
11643
11644/*
11645** Read input from the file given by sqliterc_override. Or if that
11646** parameter is NULL, take input from ~/.sqliterc
11647**
11648** Returns the number of errors.
11649*/
11650static void process_sqliterc(
11651 ShellState *p, /* Configuration data */
11652 const char *sqliterc_override /* Name of config file. NULL to use default */
11653){
11654 char *home_dir = NULL;
11655 const char *sqliterc = sqliterc_override;
11656 char *zBuf = 0;
drh60379d42018-12-13 18:30:01 +000011657 FILE *inSaved = p->in;
drh2c8ee022018-12-13 18:59:30 +000011658 int savedLineno = p->lineno;
drh2ce15c32017-07-11 13:34:40 +000011659
11660 if (sqliterc == NULL) {
11661 home_dir = find_home_dir(0);
11662 if( home_dir==0 ){
11663 raw_printf(stderr, "-- warning: cannot find home directory;"
11664 " cannot read ~/.sqliterc\n");
11665 return;
11666 }
drh2ce15c32017-07-11 13:34:40 +000011667 zBuf = sqlite3_mprintf("%s/.sqliterc",home_dir);
drhe3e25652021-12-16 13:29:28 +000011668 shell_check_oom(zBuf);
drh2ce15c32017-07-11 13:34:40 +000011669 sqliterc = zBuf;
11670 }
drh60379d42018-12-13 18:30:01 +000011671 p->in = fopen(sqliterc,"rb");
11672 if( p->in ){
drh2ce15c32017-07-11 13:34:40 +000011673 if( stdin_is_interactive ){
11674 utf8_printf(stderr,"-- Loading resources from %s\n",sqliterc);
11675 }
drhb7c46aa2020-11-25 13:59:47 +000011676 if( process_input(p) && bail_on_error ) exit(1);
drh60379d42018-12-13 18:30:01 +000011677 fclose(p->in);
drhb7c46aa2020-11-25 13:59:47 +000011678 }else if( sqliterc_override!=0 ){
11679 utf8_printf(stderr,"cannot open: \"%s\"\n", sqliterc);
11680 if( bail_on_error ) exit(1);
drh2ce15c32017-07-11 13:34:40 +000011681 }
drh60379d42018-12-13 18:30:01 +000011682 p->in = inSaved;
drh2c8ee022018-12-13 18:59:30 +000011683 p->lineno = savedLineno;
drh2ce15c32017-07-11 13:34:40 +000011684 sqlite3_free(zBuf);
11685}
11686
11687/*
11688** Show available command line options
11689*/
11690static const char zOptions[] =
drhda57d962018-03-05 19:34:05 +000011691#if defined(SQLITE_HAVE_ZLIB) && !defined(SQLITE_OMIT_VIRTUALTABLE)
drhad7fd5d2018-03-05 20:21:50 +000011692 " -A ARGS... run \".archive ARGS\" and exit\n"
drhda57d962018-03-05 19:34:05 +000011693#endif
drh3baed312018-03-08 18:14:41 +000011694 " -append append the database to the end of the file\n"
drh2ce15c32017-07-11 13:34:40 +000011695 " -ascii set output mode to 'ascii'\n"
11696 " -bail stop after hitting an error\n"
11697 " -batch force batch I/O\n"
drh0908e382020-06-04 18:05:39 +000011698 " -box set output mode to 'box'\n"
drh2ce15c32017-07-11 13:34:40 +000011699 " -column set output mode to 'column'\n"
11700 " -cmd COMMAND run \"COMMAND\" before reading stdin\n"
11701 " -csv set output mode to 'csv'\n"
drh8d889af2021-05-08 17:18:23 +000011702#if !defined(SQLITE_OMIT_DESERIALIZE)
drh6ca64482019-01-22 16:06:20 +000011703 " -deserialize open the database using sqlite3_deserialize()\n"
11704#endif
drh2ce15c32017-07-11 13:34:40 +000011705 " -echo print commands before execution\n"
11706 " -init FILENAME read/process named file\n"
11707 " -[no]header turn headers on or off\n"
11708#if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5)
11709 " -heap SIZE Size of heap for memsys3 or memsys5\n"
11710#endif
11711 " -help show this message\n"
11712 " -html set output mode to HTML\n"
11713 " -interactive force interactive I/O\n"
drh30c54a02020-05-28 23:49:50 +000011714 " -json set output mode to 'json'\n"
drh2ce15c32017-07-11 13:34:40 +000011715 " -line set output mode to 'line'\n"
11716 " -list set output mode to 'list'\n"
11717 " -lookaside SIZE N use N entries of SZ bytes for lookaside memory\n"
drh30c54a02020-05-28 23:49:50 +000011718 " -markdown set output mode to 'markdown'\n"
drh8d889af2021-05-08 17:18:23 +000011719#if !defined(SQLITE_OMIT_DESERIALIZE)
drh6ca64482019-01-22 16:06:20 +000011720 " -maxsize N maximum size for a --deserialize database\n"
11721#endif
drhaf482572019-02-04 19:52:39 +000011722 " -memtrace trace all memory allocations and deallocations\n"
drh2ce15c32017-07-11 13:34:40 +000011723 " -mmap N default mmap size set to N\n"
11724#ifdef SQLITE_ENABLE_MULTIPLEX
11725 " -multiplex enable the multiplexor VFS\n"
11726#endif
11727 " -newline SEP set output row separator. Default: '\\n'\n"
drh0933aad2019-11-18 17:46:38 +000011728 " -nofollow refuse to open symbolic links to database files\n"
drhb97e2ad2021-08-26 18:31:39 +000011729 " -nonce STRING set the safe-mode escape nonce\n"
drh2ce15c32017-07-11 13:34:40 +000011730 " -nullvalue TEXT set text string for NULL values. Default ''\n"
11731 " -pagecache SIZE N use N slots of SZ bytes each for page cache memory\n"
11732 " -quote set output mode to 'quote'\n"
drhee269a62018-02-14 23:27:43 +000011733 " -readonly open the database read-only\n"
drhb97e2ad2021-08-26 18:31:39 +000011734 " -safe enable safe-mode\n"
drh2ce15c32017-07-11 13:34:40 +000011735 " -separator SEP set output column separator. Default: '|'\n"
drha90d84f2018-04-18 15:21:13 +000011736#ifdef SQLITE_ENABLE_SORTER_REFERENCES
11737 " -sorterref SIZE sorter references threshold size\n"
11738#endif
drh2ce15c32017-07-11 13:34:40 +000011739 " -stats print memory stats before each finalize\n"
drh30c54a02020-05-28 23:49:50 +000011740 " -table set output mode to 'table'\n"
drh2fa78182020-10-31 18:58:37 +000011741 " -tabs set output mode to 'tabs'\n"
drh2ce15c32017-07-11 13:34:40 +000011742 " -version show SQLite version\n"
11743 " -vfs NAME use NAME as the default VFS\n"
11744#ifdef SQLITE_ENABLE_VFSTRACE
11745 " -vfstrace enable tracing of all VFS calls\n"
11746#endif
drh3baed312018-03-08 18:14:41 +000011747#ifdef SQLITE_HAVE_ZLIB
11748 " -zip open the file as a ZIP Archive\n"
11749#endif
drh2ce15c32017-07-11 13:34:40 +000011750;
11751static void usage(int showDetail){
11752 utf8_printf(stderr,
11753 "Usage: %s [OPTIONS] FILENAME [SQL]\n"
11754 "FILENAME is the name of an SQLite database. A new database is created\n"
11755 "if the file does not previously exist.\n", Argv0);
11756 if( showDetail ){
11757 utf8_printf(stderr, "OPTIONS include:\n%s", zOptions);
11758 }else{
11759 raw_printf(stderr, "Use the -help option for additional information\n");
11760 }
11761 exit(1);
11762}
11763
11764/*
drhe7df8922018-04-18 10:44:58 +000011765** Internal check: Verify that the SQLite is uninitialized. Print a
11766** error message if it is initialized.
11767*/
11768static void verify_uninitialized(void){
11769 if( sqlite3_config(-1)==SQLITE_MISUSE ){
drh8e02a182018-05-30 07:24:41 +000011770 utf8_printf(stdout, "WARNING: attempt to configure SQLite after"
drhe7df8922018-04-18 10:44:58 +000011771 " initialization.\n");
11772 }
11773}
11774
11775/*
drh2ce15c32017-07-11 13:34:40 +000011776** Initialize the state information in data
11777*/
11778static void main_init(ShellState *data) {
11779 memset(data, 0, sizeof(*data));
11780 data->normalMode = data->cMode = data->mode = MODE_List;
11781 data->autoExplain = 1;
drh37407122021-07-23 18:43:58 +000011782 data->pAuxDb = &data->aAuxDb[0];
drh2ce15c32017-07-11 13:34:40 +000011783 memcpy(data->colSeparator,SEP_Column, 2);
11784 memcpy(data->rowSeparator,SEP_Row, 2);
11785 data->showHeader = 0;
11786 data->shellFlgs = SHFLG_Lookaside;
drhe7df8922018-04-18 10:44:58 +000011787 verify_uninitialized();
drh2ce15c32017-07-11 13:34:40 +000011788 sqlite3_config(SQLITE_CONFIG_URI, 1);
11789 sqlite3_config(SQLITE_CONFIG_LOG, shellLog, data);
11790 sqlite3_config(SQLITE_CONFIG_MULTITHREAD);
11791 sqlite3_snprintf(sizeof(mainPrompt), mainPrompt,"sqlite> ");
11792 sqlite3_snprintf(sizeof(continuePrompt), continuePrompt," ...> ");
11793}
11794
11795/*
11796** Output text to the console in a font that attracts extra attention.
11797*/
11798#ifdef _WIN32
11799static void printBold(const char *zText){
mistachkin43e86272020-04-09 15:31:22 +000011800#if !SQLITE_OS_WINRT
drh2ce15c32017-07-11 13:34:40 +000011801 HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE);
11802 CONSOLE_SCREEN_BUFFER_INFO defaultScreenInfo;
11803 GetConsoleScreenBufferInfo(out, &defaultScreenInfo);
11804 SetConsoleTextAttribute(out,
11805 FOREGROUND_RED|FOREGROUND_INTENSITY
11806 );
mistachkin43e86272020-04-09 15:31:22 +000011807#endif
drh2ce15c32017-07-11 13:34:40 +000011808 printf("%s", zText);
mistachkin43e86272020-04-09 15:31:22 +000011809#if !SQLITE_OS_WINRT
drh2ce15c32017-07-11 13:34:40 +000011810 SetConsoleTextAttribute(out, defaultScreenInfo.wAttributes);
mistachkin43e86272020-04-09 15:31:22 +000011811#endif
drh2ce15c32017-07-11 13:34:40 +000011812}
11813#else
11814static void printBold(const char *zText){
11815 printf("\033[1m%s\033[0m", zText);
11816}
11817#endif
11818
11819/*
11820** Get the argument to an --option. Throw an error and die if no argument
11821** is available.
11822*/
11823static char *cmdline_option_value(int argc, char **argv, int i){
11824 if( i==argc ){
11825 utf8_printf(stderr, "%s: Error: missing argument to %s\n",
11826 argv[0], argv[argc-1]);
11827 exit(1);
11828 }
11829 return argv[i];
11830}
11831
11832#ifndef SQLITE_SHELL_IS_UTF8
dan39b6bd52021-03-04 18:31:07 +000011833# if (defined(_WIN32) || defined(WIN32)) \
11834 && (defined(_MSC_VER) || (defined(UNICODE) && defined(__GNUC__)))
drh2ce15c32017-07-11 13:34:40 +000011835# define SQLITE_SHELL_IS_UTF8 (0)
11836# else
11837# define SQLITE_SHELL_IS_UTF8 (1)
11838# endif
11839#endif
11840
11841#if SQLITE_SHELL_IS_UTF8
11842int SQLITE_CDECL main(int argc, char **argv){
11843#else
11844int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
11845 char **argv;
11846#endif
11847 char *zErrMsg = 0;
11848 ShellState data;
11849 const char *zInitFile = 0;
11850 int i;
11851 int rc = 0;
11852 int warnInmemoryDb = 0;
11853 int readStdin = 1;
11854 int nCmd = 0;
11855 char **azCmd = 0;
dan16a47422018-04-18 09:16:11 +000011856 const char *zVfs = 0; /* Value of -vfs command-line option */
drh1f22f622018-05-17 13:29:14 +000011857#if !SQLITE_SHELL_IS_UTF8
11858 char **argvToFree = 0;
11859 int argcToFree = 0;
11860#endif
drh2ce15c32017-07-11 13:34:40 +000011861
11862 setBinaryMode(stdin, 0);
11863 setvbuf(stderr, 0, _IONBF, 0); /* Make sure stderr is unbuffered */
11864 stdin_is_interactive = isatty(0);
11865 stdout_is_console = isatty(1);
11866
mistachkin1e8487d2018-07-22 06:25:35 +000011867#if !defined(_WIN32_WCE)
11868 if( getenv("SQLITE_DEBUG_BREAK") ){
11869 if( isatty(0) && isatty(2) ){
11870 fprintf(stderr,
11871 "attach debugger to process %d and press any key to continue.\n",
11872 GETPID());
11873 fgetc(stdin);
11874 }else{
11875#if defined(_WIN32) || defined(WIN32)
mistachkin43e86272020-04-09 15:31:22 +000011876#if SQLITE_OS_WINRT
11877 __debugbreak();
11878#else
mistachkin1e8487d2018-07-22 06:25:35 +000011879 DebugBreak();
mistachkin43e86272020-04-09 15:31:22 +000011880#endif
mistachkin1e8487d2018-07-22 06:25:35 +000011881#elif defined(SIGTRAP)
11882 raise(SIGTRAP);
11883#endif
11884 }
11885 }
11886#endif
11887
drh2ce15c32017-07-11 13:34:40 +000011888#if USE_SYSTEM_SQLITE+0!=1
drhb3c45232017-08-28 14:33:27 +000011889 if( strncmp(sqlite3_sourceid(),SQLITE_SOURCE_ID,60)!=0 ){
drh2ce15c32017-07-11 13:34:40 +000011890 utf8_printf(stderr, "SQLite header and source version mismatch\n%s\n%s\n",
11891 sqlite3_sourceid(), SQLITE_SOURCE_ID);
11892 exit(1);
11893 }
11894#endif
11895 main_init(&data);
drh501ea052018-02-15 01:03:37 +000011896
11897 /* On Windows, we must translate command-line arguments into UTF-8.
11898 ** The SQLite memory allocator subsystem has to be enabled in order to
11899 ** do this. But we want to run an sqlite3_shutdown() afterwards so that
11900 ** subsequent sqlite3_config() calls will work. So copy all results into
11901 ** memory that does not come from the SQLite memory allocator.
11902 */
drh4b18c1d2018-02-04 20:33:13 +000011903#if !SQLITE_SHELL_IS_UTF8
drh501ea052018-02-15 01:03:37 +000011904 sqlite3_initialize();
drh1f22f622018-05-17 13:29:14 +000011905 argvToFree = malloc(sizeof(argv[0])*argc*2);
drhe3e25652021-12-16 13:29:28 +000011906 shell_check_oom(argvToFree);
drh1f22f622018-05-17 13:29:14 +000011907 argcToFree = argc;
11908 argv = argvToFree + argc;
drh2ce15c32017-07-11 13:34:40 +000011909 for(i=0; i<argc; i++){
drh501ea052018-02-15 01:03:37 +000011910 char *z = sqlite3_win32_unicode_to_utf8(wargv[i]);
11911 int n;
drhe3e25652021-12-16 13:29:28 +000011912 shell_check_oom(z);
drh501ea052018-02-15 01:03:37 +000011913 n = (int)strlen(z);
11914 argv[i] = malloc( n+1 );
drhe3e25652021-12-16 13:29:28 +000011915 shell_check_oom(argv[i]);
drh501ea052018-02-15 01:03:37 +000011916 memcpy(argv[i], z, n+1);
drh1f22f622018-05-17 13:29:14 +000011917 argvToFree[i] = argv[i];
drh501ea052018-02-15 01:03:37 +000011918 sqlite3_free(z);
drh2ce15c32017-07-11 13:34:40 +000011919 }
drh501ea052018-02-15 01:03:37 +000011920 sqlite3_shutdown();
drh2ce15c32017-07-11 13:34:40 +000011921#endif
drh501ea052018-02-15 01:03:37 +000011922
drh2ce15c32017-07-11 13:34:40 +000011923 assert( argc>=1 && argv && argv[0] );
11924 Argv0 = argv[0];
11925
11926 /* Make sure we have a valid signal handler early, before anything
11927 ** else is done.
11928 */
11929#ifdef SIGINT
11930 signal(SIGINT, interrupt_handler);
mistachkinb4bab902017-10-27 17:09:44 +000011931#elif (defined(_WIN32) || defined(WIN32)) && !defined(_WIN32_WCE)
11932 SetConsoleCtrlHandler(ConsoleCtrlHandler, TRUE);
drh2ce15c32017-07-11 13:34:40 +000011933#endif
11934
11935#ifdef SQLITE_SHELL_DBNAME_PROC
11936 {
11937 /* If the SQLITE_SHELL_DBNAME_PROC macro is defined, then it is the name
11938 ** of a C-function that will provide the name of the database file. Use
11939 ** this compile-time option to embed this shell program in larger
11940 ** applications. */
11941 extern void SQLITE_SHELL_DBNAME_PROC(const char**);
drh37407122021-07-23 18:43:58 +000011942 SQLITE_SHELL_DBNAME_PROC(&data.pAuxDb->zDbFilename);
drh2ce15c32017-07-11 13:34:40 +000011943 warnInmemoryDb = 0;
11944 }
11945#endif
11946
11947 /* Do an initial pass through the command-line argument to locate
11948 ** the name of the database file, the name of the initialization file,
11949 ** the size of the alternative malloc heap,
11950 ** and the first command to execute.
11951 */
drhe7df8922018-04-18 10:44:58 +000011952 verify_uninitialized();
drh2ce15c32017-07-11 13:34:40 +000011953 for(i=1; i<argc; i++){
11954 char *z;
11955 z = argv[i];
11956 if( z[0]!='-' ){
drh37407122021-07-23 18:43:58 +000011957 if( data.aAuxDb->zDbFilename==0 ){
11958 data.aAuxDb->zDbFilename = z;
drh2ce15c32017-07-11 13:34:40 +000011959 }else{
11960 /* Excesss arguments are interpreted as SQL (or dot-commands) and
11961 ** mean that nothing is read from stdin */
11962 readStdin = 0;
11963 nCmd++;
11964 azCmd = realloc(azCmd, sizeof(azCmd[0])*nCmd);
drhe3e25652021-12-16 13:29:28 +000011965 shell_check_oom(azCmd);
drh2ce15c32017-07-11 13:34:40 +000011966 azCmd[nCmd-1] = z;
11967 }
11968 }
11969 if( z[1]=='-' ) z++;
11970 if( strcmp(z,"-separator")==0
11971 || strcmp(z,"-nullvalue")==0
11972 || strcmp(z,"-newline")==0
11973 || strcmp(z,"-cmd")==0
11974 ){
11975 (void)cmdline_option_value(argc, argv, ++i);
11976 }else if( strcmp(z,"-init")==0 ){
11977 zInitFile = cmdline_option_value(argc, argv, ++i);
11978 }else if( strcmp(z,"-batch")==0 ){
11979 /* Need to check for batch mode here to so we can avoid printing
11980 ** informational messages (like from process_sqliterc) before
11981 ** we do the actual processing of arguments later in a second pass.
11982 */
11983 stdin_is_interactive = 0;
11984 }else if( strcmp(z,"-heap")==0 ){
11985#if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5)
11986 const char *zSize;
11987 sqlite3_int64 szHeap;
11988
11989 zSize = cmdline_option_value(argc, argv, ++i);
11990 szHeap = integerValue(zSize);
11991 if( szHeap>0x7fff0000 ) szHeap = 0x7fff0000;
11992 sqlite3_config(SQLITE_CONFIG_HEAP, malloc((int)szHeap), (int)szHeap, 64);
11993#else
11994 (void)cmdline_option_value(argc, argv, ++i);
11995#endif
drh2ce15c32017-07-11 13:34:40 +000011996 }else if( strcmp(z,"-pagecache")==0 ){
drhf573b4f2020-09-28 13:34:05 +000011997 sqlite3_int64 n, sz;
11998 sz = integerValue(cmdline_option_value(argc,argv,++i));
drh2ce15c32017-07-11 13:34:40 +000011999 if( sz>70000 ) sz = 70000;
12000 if( sz<0 ) sz = 0;
drhf573b4f2020-09-28 13:34:05 +000012001 n = integerValue(cmdline_option_value(argc,argv,++i));
12002 if( sz>0 && n>0 && 0xffffffffffffLL/sz<n ){
12003 n = 0xffffffffffffLL/sz;
12004 }
drh2ce15c32017-07-11 13:34:40 +000012005 sqlite3_config(SQLITE_CONFIG_PAGECACHE,
12006 (n>0 && sz>0) ? malloc(n*sz) : 0, sz, n);
12007 data.shellFlgs |= SHFLG_Pagecache;
12008 }else if( strcmp(z,"-lookaside")==0 ){
12009 int n, sz;
12010 sz = (int)integerValue(cmdline_option_value(argc,argv,++i));
12011 if( sz<0 ) sz = 0;
12012 n = (int)integerValue(cmdline_option_value(argc,argv,++i));
12013 if( n<0 ) n = 0;
12014 sqlite3_config(SQLITE_CONFIG_LOOKASIDE, sz, n);
12015 if( sz*n==0 ) data.shellFlgs &= ~SHFLG_Lookaside;
drhaf6d1af2021-08-09 17:37:58 +000012016 }else if( strcmp(z,"-threadsafe")==0 ){
drh9d16fb12021-08-09 17:45:00 +000012017 int n;
12018 n = (int)integerValue(cmdline_option_value(argc,argv,++i));
12019 switch( n ){
drhaf6d1af2021-08-09 17:37:58 +000012020 case 0: sqlite3_config(SQLITE_CONFIG_SINGLETHREAD); break;
12021 case 2: sqlite3_config(SQLITE_CONFIG_MULTITHREAD); break;
12022 default: sqlite3_config(SQLITE_CONFIG_SERIALIZED); break;
12023 }
drh2ce15c32017-07-11 13:34:40 +000012024#ifdef SQLITE_ENABLE_VFSTRACE
12025 }else if( strcmp(z,"-vfstrace")==0 ){
12026 extern int vfstrace_register(
12027 const char *zTraceName,
12028 const char *zOldVfsName,
12029 int (*xOut)(const char*,void*),
12030 void *pOutArg,
12031 int makeDefault
12032 );
12033 vfstrace_register("trace",0,(int(*)(const char*,void*))fputs,stderr,1);
12034#endif
12035#ifdef SQLITE_ENABLE_MULTIPLEX
12036 }else if( strcmp(z,"-multiplex")==0 ){
12037 extern int sqlite3_multiple_initialize(const char*,int);
12038 sqlite3_multiplex_initialize(0, 1);
12039#endif
12040 }else if( strcmp(z,"-mmap")==0 ){
12041 sqlite3_int64 sz = integerValue(cmdline_option_value(argc,argv,++i));
12042 sqlite3_config(SQLITE_CONFIG_MMAP_SIZE, sz, sz);
drha90d84f2018-04-18 15:21:13 +000012043#ifdef SQLITE_ENABLE_SORTER_REFERENCES
12044 }else if( strcmp(z,"-sorterref")==0 ){
12045 sqlite3_int64 sz = integerValue(cmdline_option_value(argc,argv,++i));
12046 sqlite3_config(SQLITE_CONFIG_SORTERREF_SIZE, (int)sz);
12047#endif
drh2ce15c32017-07-11 13:34:40 +000012048 }else if( strcmp(z,"-vfs")==0 ){
dan16a47422018-04-18 09:16:11 +000012049 zVfs = cmdline_option_value(argc, argv, ++i);
drh3baed312018-03-08 18:14:41 +000012050#ifdef SQLITE_HAVE_ZLIB
drh8682e122018-01-07 20:38:10 +000012051 }else if( strcmp(z,"-zip")==0 ){
12052 data.openMode = SHELL_OPEN_ZIPFILE;
12053#endif
12054 }else if( strcmp(z,"-append")==0 ){
12055 data.openMode = SHELL_OPEN_APPENDVFS;
drh8d889af2021-05-08 17:18:23 +000012056#ifndef SQLITE_OMIT_DESERIALIZE
drh60f34ae2018-10-30 13:19:49 +000012057 }else if( strcmp(z,"-deserialize")==0 ){
12058 data.openMode = SHELL_OPEN_DESERIALIZE;
drh6ca64482019-01-22 16:06:20 +000012059 }else if( strcmp(z,"-maxsize")==0 && i+1<argc ){
12060 data.szMax = integerValue(argv[++i]);
drha751f392018-10-30 15:31:22 +000012061#endif
drhee269a62018-02-14 23:27:43 +000012062 }else if( strcmp(z,"-readonly")==0 ){
12063 data.openMode = SHELL_OPEN_READONLY;
drh0933aad2019-11-18 17:46:38 +000012064 }else if( strcmp(z,"-nofollow")==0 ){
12065 data.openFlags = SQLITE_OPEN_NOFOLLOW;
drhda57d962018-03-05 19:34:05 +000012066#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
drh93b77312018-03-05 20:20:22 +000012067 }else if( strncmp(z, "-A",2)==0 ){
drhda57d962018-03-05 19:34:05 +000012068 /* All remaining command-line arguments are passed to the ".archive"
12069 ** command, so ignore them */
12070 break;
12071#endif
drh50b910a2019-01-21 14:55:03 +000012072 }else if( strcmp(z, "-memtrace")==0 ){
12073 sqlite3MemTraceActivate(stderr);
drhb7c46aa2020-11-25 13:59:47 +000012074 }else if( strcmp(z,"-bail")==0 ){
12075 bail_on_error = 1;
drhb97e2ad2021-08-26 18:31:39 +000012076 }else if( strcmp(z,"-nonce")==0 ){
12077 free(data.zNonce);
12078 data.zNonce = strdup(argv[++i]);
12079 }else if( strcmp(z,"-safe")==0 ){
12080 /* no-op - catch this on the second pass */
drh2ce15c32017-07-11 13:34:40 +000012081 }
12082 }
drhe7df8922018-04-18 10:44:58 +000012083 verify_uninitialized();
12084
dan16a47422018-04-18 09:16:11 +000012085
drhd11b8f62018-04-25 13:27:07 +000012086#ifdef SQLITE_SHELL_INIT_PROC
12087 {
12088 /* If the SQLITE_SHELL_INIT_PROC macro is defined, then it is the name
12089 ** of a C-function that will perform initialization actions on SQLite that
12090 ** occur just before or after sqlite3_initialize(). Use this compile-time
12091 ** option to embed this shell program in larger applications. */
12092 extern void SQLITE_SHELL_INIT_PROC(void);
12093 SQLITE_SHELL_INIT_PROC();
12094 }
12095#else
dan16a47422018-04-18 09:16:11 +000012096 /* All the sqlite3_config() calls have now been made. So it is safe
12097 ** to call sqlite3_initialize() and process any command line -vfs option. */
12098 sqlite3_initialize();
drhd11b8f62018-04-25 13:27:07 +000012099#endif
12100
dan16a47422018-04-18 09:16:11 +000012101 if( zVfs ){
12102 sqlite3_vfs *pVfs = sqlite3_vfs_find(zVfs);
12103 if( pVfs ){
12104 sqlite3_vfs_register(pVfs, 1);
12105 }else{
12106 utf8_printf(stderr, "no such VFS: \"%s\"\n", argv[i]);
12107 exit(1);
12108 }
12109 }
12110
drh37407122021-07-23 18:43:58 +000012111 if( data.pAuxDb->zDbFilename==0 ){
drh2ce15c32017-07-11 13:34:40 +000012112#ifndef SQLITE_OMIT_MEMORYDB
drh37407122021-07-23 18:43:58 +000012113 data.pAuxDb->zDbFilename = ":memory:";
drh2ce15c32017-07-11 13:34:40 +000012114 warnInmemoryDb = argc==1;
12115#else
12116 utf8_printf(stderr,"%s: Error: no database filename specified\n", Argv0);
12117 return 1;
12118#endif
12119 }
12120 data.out = stdout;
drh8682e122018-01-07 20:38:10 +000012121 sqlite3_appendvfs_init(0,0,0);
drh2ce15c32017-07-11 13:34:40 +000012122
12123 /* Go ahead and open the database file if it already exists. If the
12124 ** file does not exist, delay opening it. This prevents empty database
12125 ** files from being created if a user mistypes the database name argument
12126 ** to the sqlite command-line tool.
12127 */
drh37407122021-07-23 18:43:58 +000012128 if( access(data.pAuxDb->zDbFilename, 0)==0 ){
drh2ce15c32017-07-11 13:34:40 +000012129 open_db(&data, 0);
12130 }
12131
12132 /* Process the initialization file if there is one. If no -init option
12133 ** is given on the command line, look for a file named ~/.sqliterc and
12134 ** try to process it.
12135 */
12136 process_sqliterc(&data,zInitFile);
12137
12138 /* Make a second pass through the command-line argument and set
12139 ** options. This second pass is delayed until after the initialization
12140 ** file is processed so that the command-line arguments will override
12141 ** settings in the initialization file.
12142 */
12143 for(i=1; i<argc; i++){
12144 char *z = argv[i];
12145 if( z[0]!='-' ) continue;
12146 if( z[1]=='-' ){ z++; }
12147 if( strcmp(z,"-init")==0 ){
12148 i++;
12149 }else if( strcmp(z,"-html")==0 ){
12150 data.mode = MODE_Html;
12151 }else if( strcmp(z,"-list")==0 ){
12152 data.mode = MODE_List;
12153 }else if( strcmp(z,"-quote")==0 ){
12154 data.mode = MODE_Quote;
drh9191c702020-08-17 09:11:21 +000012155 sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator, SEP_Comma);
12156 sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator, SEP_Row);
drh2ce15c32017-07-11 13:34:40 +000012157 }else if( strcmp(z,"-line")==0 ){
12158 data.mode = MODE_Line;
12159 }else if( strcmp(z,"-column")==0 ){
12160 data.mode = MODE_Column;
drh30c54a02020-05-28 23:49:50 +000012161 }else if( strcmp(z,"-json")==0 ){
12162 data.mode = MODE_Json;
12163 }else if( strcmp(z,"-markdown")==0 ){
12164 data.mode = MODE_Markdown;
12165 }else if( strcmp(z,"-table")==0 ){
12166 data.mode = MODE_Table;
drh0908e382020-06-04 18:05:39 +000012167 }else if( strcmp(z,"-box")==0 ){
12168 data.mode = MODE_Box;
drh2ce15c32017-07-11 13:34:40 +000012169 }else if( strcmp(z,"-csv")==0 ){
12170 data.mode = MODE_Csv;
12171 memcpy(data.colSeparator,",",2);
drh3baed312018-03-08 18:14:41 +000012172#ifdef SQLITE_HAVE_ZLIB
drh1fa6d9f2018-01-06 21:46:01 +000012173 }else if( strcmp(z,"-zip")==0 ){
12174 data.openMode = SHELL_OPEN_ZIPFILE;
12175#endif
12176 }else if( strcmp(z,"-append")==0 ){
12177 data.openMode = SHELL_OPEN_APPENDVFS;
drh8d889af2021-05-08 17:18:23 +000012178#ifndef SQLITE_OMIT_DESERIALIZE
drh60f34ae2018-10-30 13:19:49 +000012179 }else if( strcmp(z,"-deserialize")==0 ){
12180 data.openMode = SHELL_OPEN_DESERIALIZE;
drh6ca64482019-01-22 16:06:20 +000012181 }else if( strcmp(z,"-maxsize")==0 && i+1<argc ){
12182 data.szMax = integerValue(argv[++i]);
drha751f392018-10-30 15:31:22 +000012183#endif
drh4aafe592018-03-23 16:08:30 +000012184 }else if( strcmp(z,"-readonly")==0 ){
12185 data.openMode = SHELL_OPEN_READONLY;
drh0933aad2019-11-18 17:46:38 +000012186 }else if( strcmp(z,"-nofollow")==0 ){
12187 data.openFlags |= SQLITE_OPEN_NOFOLLOW;
drh2ce15c32017-07-11 13:34:40 +000012188 }else if( strcmp(z,"-ascii")==0 ){
12189 data.mode = MODE_Ascii;
drh2fa78182020-10-31 18:58:37 +000012190 sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator, SEP_Unit);
12191 sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator, SEP_Record);
12192 }else if( strcmp(z,"-tabs")==0 ){
12193 data.mode = MODE_List;
12194 sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator, SEP_Tab);
12195 sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator, SEP_Row);
drh2ce15c32017-07-11 13:34:40 +000012196 }else if( strcmp(z,"-separator")==0 ){
12197 sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator,
12198 "%s",cmdline_option_value(argc,argv,++i));
12199 }else if( strcmp(z,"-newline")==0 ){
12200 sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator,
12201 "%s",cmdline_option_value(argc,argv,++i));
12202 }else if( strcmp(z,"-nullvalue")==0 ){
12203 sqlite3_snprintf(sizeof(data.nullValue), data.nullValue,
12204 "%s",cmdline_option_value(argc,argv,++i));
12205 }else if( strcmp(z,"-header")==0 ){
12206 data.showHeader = 1;
larrybrae509122021-09-10 01:45:20 +000012207 ShellSetFlag(&data, SHFLG_HeaderSet);
12208 }else if( strcmp(z,"-noheader")==0 ){
drh2ce15c32017-07-11 13:34:40 +000012209 data.showHeader = 0;
larrybrae509122021-09-10 01:45:20 +000012210 ShellSetFlag(&data, SHFLG_HeaderSet);
drh2ce15c32017-07-11 13:34:40 +000012211 }else if( strcmp(z,"-echo")==0 ){
12212 ShellSetFlag(&data, SHFLG_Echo);
12213 }else if( strcmp(z,"-eqp")==0 ){
drhada70452017-12-21 21:02:27 +000012214 data.autoEQP = AUTOEQP_on;
drh2ce15c32017-07-11 13:34:40 +000012215 }else if( strcmp(z,"-eqpfull")==0 ){
drhada70452017-12-21 21:02:27 +000012216 data.autoEQP = AUTOEQP_full;
drh2ce15c32017-07-11 13:34:40 +000012217 }else if( strcmp(z,"-stats")==0 ){
12218 data.statsOn = 1;
12219 }else if( strcmp(z,"-scanstats")==0 ){
12220 data.scanstatsOn = 1;
12221 }else if( strcmp(z,"-backslash")==0 ){
12222 /* Undocumented command-line option: -backslash
12223 ** Causes C-style backslash escapes to be evaluated in SQL statements
12224 ** prior to sending the SQL into SQLite. Useful for injecting
12225 ** crazy bytes in the middle of SQL statements for testing and debugging.
12226 */
12227 ShellSetFlag(&data, SHFLG_Backslash);
12228 }else if( strcmp(z,"-bail")==0 ){
drhb7c46aa2020-11-25 13:59:47 +000012229 /* No-op. The bail_on_error flag should already be set. */
drh2ce15c32017-07-11 13:34:40 +000012230 }else if( strcmp(z,"-version")==0 ){
12231 printf("%s %s\n", sqlite3_libversion(), sqlite3_sourceid());
12232 return 0;
12233 }else if( strcmp(z,"-interactive")==0 ){
12234 stdin_is_interactive = 1;
12235 }else if( strcmp(z,"-batch")==0 ){
12236 stdin_is_interactive = 0;
12237 }else if( strcmp(z,"-heap")==0 ){
12238 i++;
drh2ce15c32017-07-11 13:34:40 +000012239 }else if( strcmp(z,"-pagecache")==0 ){
12240 i+=2;
12241 }else if( strcmp(z,"-lookaside")==0 ){
12242 i+=2;
drhaf6d1af2021-08-09 17:37:58 +000012243 }else if( strcmp(z,"-threadsafe")==0 ){
12244 i+=2;
drhb97e2ad2021-08-26 18:31:39 +000012245 }else if( strcmp(z,"-nonce")==0 ){
12246 i += 2;
drh2ce15c32017-07-11 13:34:40 +000012247 }else if( strcmp(z,"-mmap")==0 ){
12248 i++;
drh50b910a2019-01-21 14:55:03 +000012249 }else if( strcmp(z,"-memtrace")==0 ){
12250 i++;
drha90d84f2018-04-18 15:21:13 +000012251#ifdef SQLITE_ENABLE_SORTER_REFERENCES
12252 }else if( strcmp(z,"-sorterref")==0 ){
12253 i++;
12254#endif
drh2ce15c32017-07-11 13:34:40 +000012255 }else if( strcmp(z,"-vfs")==0 ){
12256 i++;
12257#ifdef SQLITE_ENABLE_VFSTRACE
12258 }else if( strcmp(z,"-vfstrace")==0 ){
12259 i++;
12260#endif
12261#ifdef SQLITE_ENABLE_MULTIPLEX
12262 }else if( strcmp(z,"-multiplex")==0 ){
12263 i++;
12264#endif
12265 }else if( strcmp(z,"-help")==0 ){
12266 usage(1);
12267 }else if( strcmp(z,"-cmd")==0 ){
12268 /* Run commands that follow -cmd first and separately from commands
12269 ** that simply appear on the command-line. This seems goofy. It would
12270 ** be better if all commands ran in the order that they appear. But
12271 ** we retain the goofy behavior for historical compatibility. */
12272 if( i==argc-1 ) break;
12273 z = cmdline_option_value(argc,argv,++i);
12274 if( z[0]=='.' ){
12275 rc = do_meta_command(z, &data);
12276 if( rc && bail_on_error ) return rc==2 ? 0 : rc;
12277 }else{
12278 open_db(&data, 0);
drha10b9992018-03-09 15:24:33 +000012279 rc = shell_exec(&data, z, &zErrMsg);
drh2ce15c32017-07-11 13:34:40 +000012280 if( zErrMsg!=0 ){
12281 utf8_printf(stderr,"Error: %s\n", zErrMsg);
12282 if( bail_on_error ) return rc!=0 ? rc : 1;
12283 }else if( rc!=0 ){
12284 utf8_printf(stderr,"Error: unable to process SQL \"%s\"\n", z);
12285 if( bail_on_error ) return rc;
12286 }
12287 }
drhda57d962018-03-05 19:34:05 +000012288#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
drh93b77312018-03-05 20:20:22 +000012289 }else if( strncmp(z, "-A", 2)==0 ){
drhda57d962018-03-05 19:34:05 +000012290 if( nCmd>0 ){
12291 utf8_printf(stderr, "Error: cannot mix regular SQL or dot-commands"
12292 " with \"%s\"\n", z);
12293 return 1;
12294 }
drhbe4ccb22018-05-17 20:04:24 +000012295 open_db(&data, OPEN_DB_ZIPFILE);
drh93b77312018-03-05 20:20:22 +000012296 if( z[2] ){
12297 argv[i] = &z[2];
drhd0f9cdc2018-05-17 14:09:06 +000012298 arDotCommand(&data, 1, argv+(i-1), argc-(i-1));
drh93b77312018-03-05 20:20:22 +000012299 }else{
drhd0f9cdc2018-05-17 14:09:06 +000012300 arDotCommand(&data, 1, argv+i, argc-i);
drh93b77312018-03-05 20:20:22 +000012301 }
drhda57d962018-03-05 19:34:05 +000012302 readStdin = 0;
12303 break;
12304#endif
drhb97e2ad2021-08-26 18:31:39 +000012305 }else if( strcmp(z,"-safe")==0 ){
12306 data.bSafeMode = data.bSafeModePersist = 1;
drh2ce15c32017-07-11 13:34:40 +000012307 }else{
12308 utf8_printf(stderr,"%s: Error: unknown option: %s\n", Argv0, z);
12309 raw_printf(stderr,"Use -help for a list of options.\n");
12310 return 1;
12311 }
12312 data.cMode = data.mode;
12313 }
12314
12315 if( !readStdin ){
12316 /* Run all arguments that do not begin with '-' as if they were separate
12317 ** command-line inputs, except for the argToSkip argument which contains
12318 ** the database filename.
12319 */
12320 for(i=0; i<nCmd; i++){
12321 if( azCmd[i][0]=='.' ){
12322 rc = do_meta_command(azCmd[i], &data);
danaff1a572020-11-17 21:09:56 +000012323 if( rc ){
12324 free(azCmd);
12325 return rc==2 ? 0 : rc;
12326 }
drh2ce15c32017-07-11 13:34:40 +000012327 }else{
12328 open_db(&data, 0);
drha10b9992018-03-09 15:24:33 +000012329 rc = shell_exec(&data, azCmd[i], &zErrMsg);
danaff1a572020-11-17 21:09:56 +000012330 if( zErrMsg || rc ){
12331 if( zErrMsg!=0 ){
12332 utf8_printf(stderr,"Error: %s\n", zErrMsg);
12333 }else{
12334 utf8_printf(stderr,"Error: unable to process SQL: %s\n", azCmd[i]);
12335 }
12336 sqlite3_free(zErrMsg);
12337 free(azCmd);
drh2ce15c32017-07-11 13:34:40 +000012338 return rc!=0 ? rc : 1;
drh2ce15c32017-07-11 13:34:40 +000012339 }
12340 }
12341 }
drh2ce15c32017-07-11 13:34:40 +000012342 }else{
12343 /* Run commands received from standard input
12344 */
12345 if( stdin_is_interactive ){
12346 char *zHome;
drha9e4be32018-10-10 18:56:40 +000012347 char *zHistory;
drh2ce15c32017-07-11 13:34:40 +000012348 int nHistory;
12349 printf(
12350 "SQLite version %s %.19s\n" /*extra-version-info*/
12351 "Enter \".help\" for usage hints.\n",
12352 sqlite3_libversion(), sqlite3_sourceid()
12353 );
12354 if( warnInmemoryDb ){
12355 printf("Connected to a ");
12356 printBold("transient in-memory database");
12357 printf(".\nUse \".open FILENAME\" to reopen on a "
12358 "persistent database.\n");
12359 }
drha9e4be32018-10-10 18:56:40 +000012360 zHistory = getenv("SQLITE_HISTORY");
12361 if( zHistory ){
12362 zHistory = strdup(zHistory);
12363 }else if( (zHome = find_home_dir(0))!=0 ){
drh2ce15c32017-07-11 13:34:40 +000012364 nHistory = strlen30(zHome) + 20;
12365 if( (zHistory = malloc(nHistory))!=0 ){
12366 sqlite3_snprintf(nHistory, zHistory,"%s/.sqlite_history", zHome);
12367 }
12368 }
12369 if( zHistory ){ shell_read_history(zHistory); }
drh56eb09b2017-07-11 13:59:07 +000012370#if HAVE_READLINE || HAVE_EDITLINE
12371 rl_attempted_completion_function = readline_completion;
12372#elif HAVE_LINENOISE
12373 linenoiseSetCompletionCallback(linenoise_completion);
12374#endif
drh60379d42018-12-13 18:30:01 +000012375 data.in = 0;
12376 rc = process_input(&data);
drh2ce15c32017-07-11 13:34:40 +000012377 if( zHistory ){
drh5a75dd82017-07-18 20:59:40 +000012378 shell_stifle_history(2000);
drh2ce15c32017-07-11 13:34:40 +000012379 shell_write_history(zHistory);
12380 free(zHistory);
12381 }
12382 }else{
drh60379d42018-12-13 18:30:01 +000012383 data.in = stdin;
12384 rc = process_input(&data);
drh2ce15c32017-07-11 13:34:40 +000012385 }
12386 }
danaff1a572020-11-17 21:09:56 +000012387 free(azCmd);
drh2ce15c32017-07-11 13:34:40 +000012388 set_table_name(&data, 0);
12389 if( data.db ){
drh37407122021-07-23 18:43:58 +000012390 session_close_all(&data, -1);
drh9e804032018-05-18 17:11:50 +000012391 close_db(data.db);
drh2ce15c32017-07-11 13:34:40 +000012392 }
drh37407122021-07-23 18:43:58 +000012393 for(i=0; i<ArraySize(data.aAuxDb); i++){
12394 sqlite3_free(data.aAuxDb[i].zFreeOnClose);
12395 if( data.aAuxDb[i].db ){
12396 session_close_all(&data, i);
12397 close_db(data.aAuxDb[i].db);
12398 }
12399 }
drh2ce15c32017-07-11 13:34:40 +000012400 find_home_dir(1);
drh536c3452018-01-11 00:38:39 +000012401 output_reset(&data);
12402 data.doXdgOpen = 0;
drh13c20932018-01-10 21:41:55 +000012403 clearTempFile(&data);
drh2ce15c32017-07-11 13:34:40 +000012404#if !SQLITE_SHELL_IS_UTF8
drh1f22f622018-05-17 13:29:14 +000012405 for(i=0; i<argcToFree; i++) free(argvToFree[i]);
12406 free(argvToFree);
drh2ce15c32017-07-11 13:34:40 +000012407#endif
drh0285d982020-05-29 14:38:43 +000012408 free(data.colWidth);
drhb97e2ad2021-08-26 18:31:39 +000012409 free(data.zNonce);
drh9e804032018-05-18 17:11:50 +000012410 /* Clear the global data structure so that valgrind will detect memory
12411 ** leaks */
12412 memset(&data, 0, sizeof(data));
drh2ce15c32017-07-11 13:34:40 +000012413 return rc;
12414}