blob: 29e61c7b16a0f2f3a86740b79da2a6d0d6732397 [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
drh80fafc22022-11-07 19:40:20 +000019typedef unsigned int u32;
20typedef unsigned short int u16;
drh2ce15c32017-07-11 13:34:40 +000021
22/*
larrybra13c0c72021-07-09 00:12:05 +000023** Optionally #include a user-defined header, whereby compilation options
24** may be set prior to where they take effect, but after platform setup.
25** If SQLITE_CUSTOM_INCLUDE=? is defined, its value names the #include
26** file. Note that this macro has a like effect on sqlite3.c compilation.
27*/
larrybr78138392022-02-12 02:15:37 +000028# define SHELL_STRINGIFY_(f) #f
29# define SHELL_STRINGIFY(f) SHELL_STRINGIFY_(f)
larrybra13c0c72021-07-09 00:12:05 +000030#ifdef SQLITE_CUSTOM_INCLUDE
larrybr78138392022-02-12 02:15:37 +000031# include SHELL_STRINGIFY(SQLITE_CUSTOM_INCLUDE)
larrybra13c0c72021-07-09 00:12:05 +000032#endif
33
34/*
mistachkin43e86272020-04-09 15:31:22 +000035** Determine if we are dealing with WinRT, which provides only a subset of
36** the full Win32 API.
37*/
38#if !defined(SQLITE_OS_WINRT)
39# define SQLITE_OS_WINRT 0
40#endif
41
42/*
stephan4413ec72022-07-12 15:53:02 +000043** If SQLITE_SHELL_FIDDLE is defined then the shell is modified
44** somewhat for use as a WASM module in a web browser. This flag
45** should only be used when building the "fiddle" web application, as
46** the browser-mode build has much different user input requirements
47** and this build mode rewires the user input subsystem to account for
48** that.
stephanea1e3b42022-07-12 09:40:27 +000049*/
50
51/*
drh2ce15c32017-07-11 13:34:40 +000052** Warning pragmas copied from msvc.h in the core.
53*/
54#if defined(_MSC_VER)
55#pragma warning(disable : 4054)
56#pragma warning(disable : 4055)
57#pragma warning(disable : 4100)
58#pragma warning(disable : 4127)
59#pragma warning(disable : 4130)
60#pragma warning(disable : 4152)
61#pragma warning(disable : 4189)
62#pragma warning(disable : 4206)
63#pragma warning(disable : 4210)
64#pragma warning(disable : 4232)
65#pragma warning(disable : 4244)
66#pragma warning(disable : 4305)
67#pragma warning(disable : 4306)
68#pragma warning(disable : 4702)
69#pragma warning(disable : 4706)
70#endif /* defined(_MSC_VER) */
71
72/*
73** No support for loadable extensions in VxWorks.
74*/
75#if (defined(__RTP__) || defined(_WRS_KERNEL)) && !SQLITE_OMIT_LOAD_EXTENSION
76# define SQLITE_OMIT_LOAD_EXTENSION 1
77#endif
78
79/*
80** Enable large-file support for fopen() and friends on unix.
81*/
82#ifndef SQLITE_DISABLE_LFS
83# define _LARGE_FILE 1
84# ifndef _FILE_OFFSET_BITS
85# define _FILE_OFFSET_BITS 64
86# endif
87# define _LARGEFILE_SOURCE 1
88#endif
89
stephan65022712022-09-21 16:21:21 +000090#if defined(SQLITE_SHELL_FIDDLE) && !defined(_POSIX_SOURCE)
91/*
92** emcc requires _POSIX_SOURCE (or one of several similar defines)
93** to expose strdup().
94*/
95# define _POSIX_SOURCE
96#endif
97
drh2ce15c32017-07-11 13:34:40 +000098#include <stdlib.h>
99#include <string.h>
100#include <stdio.h>
101#include <assert.h>
102#include "sqlite3.h"
drh1e506b52018-01-05 21:01:37 +0000103typedef sqlite3_int64 i64;
104typedef sqlite3_uint64 u64;
drh1fa6d9f2018-01-06 21:46:01 +0000105typedef unsigned char u8;
drh2ce15c32017-07-11 13:34:40 +0000106#if SQLITE_USER_AUTHENTICATION
107# include "sqlite3userauth.h"
108#endif
109#include <ctype.h>
110#include <stdarg.h>
111
112#if !defined(_WIN32) && !defined(WIN32)
113# include <signal.h>
114# if !defined(__RTP__) && !defined(_WRS_KERNEL)
115# include <pwd.h>
116# endif
mistachkinacae8c32018-01-05 20:08:46 +0000117#endif
mistachkin562f0c82018-01-09 00:28:24 +0000118#if (!defined(_WIN32) && !defined(WIN32)) || defined(__MINGW32__)
drh2ce15c32017-07-11 13:34:40 +0000119# include <unistd.h>
mistachkinacae8c32018-01-05 20:08:46 +0000120# include <dirent.h>
mistachkin1e8487d2018-07-22 06:25:35 +0000121# define GETPID getpid
mistachkin562f0c82018-01-09 00:28:24 +0000122# if defined(__MINGW32__)
mistachkinacae8c32018-01-05 20:08:46 +0000123# define DIRENT dirent
mistachkin2f74b3c2018-01-05 20:26:06 +0000124# ifndef S_ISLNK
125# define S_ISLNK(mode) (0)
126# endif
mistachkinacae8c32018-01-05 20:08:46 +0000127# endif
mistachkin1e8487d2018-07-22 06:25:35 +0000128#else
129# define GETPID (int)GetCurrentProcessId
drh2ce15c32017-07-11 13:34:40 +0000130#endif
mistachkindfdfd8c2018-01-04 22:46:08 +0000131#include <sys/types.h>
132#include <sys/stat.h>
drh2ce15c32017-07-11 13:34:40 +0000133
134#if HAVE_READLINE
135# include <readline/readline.h>
136# include <readline/history.h>
137#endif
138
139#if HAVE_EDITLINE
140# include <editline/readline.h>
141#endif
142
143#if HAVE_EDITLINE || HAVE_READLINE
144
145# define shell_add_history(X) add_history(X)
146# define shell_read_history(X) read_history(X)
147# define shell_write_history(X) write_history(X)
148# define shell_stifle_history(X) stifle_history(X)
149# define shell_readline(X) readline(X)
150
151#elif HAVE_LINENOISE
152
153# include "linenoise.h"
154# define shell_add_history(X) linenoiseHistoryAdd(X)
155# define shell_read_history(X) linenoiseHistoryLoad(X)
156# define shell_write_history(X) linenoiseHistorySave(X)
157# define shell_stifle_history(X) linenoiseHistorySetMaxLen(X)
158# define shell_readline(X) linenoise(X)
159
160#else
161
162# define shell_read_history(X)
163# define shell_write_history(X)
164# define shell_stifle_history(X)
165
166# define SHELL_USE_LOCAL_GETLINE 1
167#endif
168
169
170#if defined(_WIN32) || defined(WIN32)
mistachkin43e86272020-04-09 15:31:22 +0000171# if SQLITE_OS_WINRT
172# define SQLITE_OMIT_POPEN 1
173# else
174# include <io.h>
175# include <fcntl.h>
176# define isatty(h) _isatty(h)
177# ifndef access
178# define access(f,m) _access((f),(m))
179# endif
180# ifndef unlink
181# define unlink _unlink
182# endif
183# ifndef strdup
184# define strdup _strdup
185# endif
186# undef popen
187# define popen _popen
188# undef pclose
189# define pclose _pclose
drh2ce15c32017-07-11 13:34:40 +0000190# endif
drh2ce15c32017-07-11 13:34:40 +0000191#else
192 /* Make sure isatty() has a prototype. */
193 extern int isatty(int);
194
195# if !defined(__RTP__) && !defined(_WRS_KERNEL)
196 /* popen and pclose are not C89 functions and so are
197 ** sometimes omitted from the <stdio.h> header */
198 extern FILE *popen(const char*,const char*);
199 extern int pclose(FILE*);
200# else
201# define SQLITE_OMIT_POPEN 1
202# endif
203#endif
204
205#if defined(_WIN32_WCE)
206/* Windows CE (arm-wince-mingw32ce-gcc) does not provide isatty()
207 * thus we always assume that we have a console. That can be
208 * overridden with the -batch command line option.
209 */
210#define isatty(x) 1
211#endif
212
213/* ctype macros that work with signed characters */
214#define IsSpace(X) isspace((unsigned char)X)
215#define IsDigit(X) isdigit((unsigned char)X)
216#define ToLower(X) (char)tolower((unsigned char)X)
217
218#if defined(_WIN32) || defined(WIN32)
mistachkin43e86272020-04-09 15:31:22 +0000219#if SQLITE_OS_WINRT
220#include <intrin.h>
221#endif
drh2ce15c32017-07-11 13:34:40 +0000222#include <windows.h>
223
224/* string conversion routines only needed on Win32 */
225extern char *sqlite3_win32_unicode_to_utf8(LPCWSTR);
226extern char *sqlite3_win32_mbcs_to_utf8_v2(const char *, int);
227extern char *sqlite3_win32_utf8_to_mbcs_v2(const char *, int);
228extern LPWSTR sqlite3_win32_utf8_to_unicode(const char *zText);
229#endif
230
231/* On Windows, we normally run with output mode of TEXT so that \n characters
232** are automatically translated into \r\n. However, this behavior needs
233** to be disabled in some cases (ex: when generating CSV output and when
234** rendering quoted strings that contain \n characters). The following
235** routines take care of that.
236*/
mistachkin43e86272020-04-09 15:31:22 +0000237#if (defined(_WIN32) || defined(WIN32)) && !SQLITE_OS_WINRT
drh2ce15c32017-07-11 13:34:40 +0000238static void setBinaryMode(FILE *file, int isOutput){
239 if( isOutput ) fflush(file);
240 _setmode(_fileno(file), _O_BINARY);
241}
242static void setTextMode(FILE *file, int isOutput){
243 if( isOutput ) fflush(file);
244 _setmode(_fileno(file), _O_TEXT);
245}
246#else
247# define setBinaryMode(X,Y)
248# define setTextMode(X,Y)
249#endif
250
drh2ce15c32017-07-11 13:34:40 +0000251/* True if the timer is enabled */
252static int enableTimer = 0;
253
drhbf70f1b2022-10-19 18:04:42 +0000254/* A version of strcmp() that works with NULL values */
255static int cli_strcmp(const char *a, const char *b){
256 if( a==0 ) a = "";
257 if( b==0 ) b = "";
258 return strcmp(a,b);
259}
260static int cli_strncmp(const char *a, const char *b, size_t n){
261 if( a==0 ) a = "";
262 if( b==0 ) b = "";
263 return strncmp(a,b,n);
264}
265
drh2ce15c32017-07-11 13:34:40 +0000266/* Return the current wall-clock time */
267static sqlite3_int64 timeOfDay(void){
268 static sqlite3_vfs *clockVfs = 0;
269 sqlite3_int64 t;
270 if( clockVfs==0 ) clockVfs = sqlite3_vfs_find(0);
drha959bf52021-06-15 15:15:40 +0000271 if( clockVfs==0 ) return 0; /* Never actually happens */
drh2ce15c32017-07-11 13:34:40 +0000272 if( clockVfs->iVersion>=2 && clockVfs->xCurrentTimeInt64!=0 ){
273 clockVfs->xCurrentTimeInt64(clockVfs, &t);
274 }else{
275 double r;
276 clockVfs->xCurrentTime(clockVfs, &r);
277 t = (sqlite3_int64)(r*86400000.0);
278 }
279 return t;
280}
281
282#if !defined(_WIN32) && !defined(WIN32) && !defined(__minux)
283#include <sys/time.h>
284#include <sys/resource.h>
285
286/* VxWorks does not support getrusage() as far as we can determine */
287#if defined(_WRS_KERNEL) || defined(__RTP__)
288struct rusage {
289 struct timeval ru_utime; /* user CPU time used */
290 struct timeval ru_stime; /* system CPU time used */
291};
292#define getrusage(A,B) memset(B,0,sizeof(*B))
293#endif
294
295/* Saved resource information for the beginning of an operation */
296static struct rusage sBegin; /* CPU time at start */
297static sqlite3_int64 iBegin; /* Wall-clock time at start */
298
299/*
300** Begin timing an operation
301*/
302static void beginTimer(void){
303 if( enableTimer ){
304 getrusage(RUSAGE_SELF, &sBegin);
305 iBegin = timeOfDay();
306 }
307}
308
309/* Return the difference of two time_structs in seconds */
310static double timeDiff(struct timeval *pStart, struct timeval *pEnd){
311 return (pEnd->tv_usec - pStart->tv_usec)*0.000001 +
312 (double)(pEnd->tv_sec - pStart->tv_sec);
313}
314
315/*
316** Print the timing results.
317*/
318static void endTimer(void){
319 if( enableTimer ){
320 sqlite3_int64 iEnd = timeOfDay();
321 struct rusage sEnd;
322 getrusage(RUSAGE_SELF, &sEnd);
323 printf("Run Time: real %.3f user %f sys %f\n",
324 (iEnd - iBegin)*0.001,
325 timeDiff(&sBegin.ru_utime, &sEnd.ru_utime),
326 timeDiff(&sBegin.ru_stime, &sEnd.ru_stime));
327 }
328}
329
330#define BEGIN_TIMER beginTimer()
331#define END_TIMER endTimer()
332#define HAS_TIMER 1
333
334#elif (defined(_WIN32) || defined(WIN32))
335
336/* Saved resource information for the beginning of an operation */
337static HANDLE hProcess;
338static FILETIME ftKernelBegin;
339static FILETIME ftUserBegin;
340static sqlite3_int64 ftWallBegin;
341typedef BOOL (WINAPI *GETPROCTIMES)(HANDLE, LPFILETIME, LPFILETIME,
342 LPFILETIME, LPFILETIME);
343static GETPROCTIMES getProcessTimesAddr = NULL;
344
345/*
346** Check to see if we have timer support. Return 1 if necessary
347** support found (or found previously).
348*/
349static int hasTimer(void){
350 if( getProcessTimesAddr ){
351 return 1;
352 } else {
mistachkin43e86272020-04-09 15:31:22 +0000353#if !SQLITE_OS_WINRT
drh2ce15c32017-07-11 13:34:40 +0000354 /* GetProcessTimes() isn't supported in WIN95 and some other Windows
355 ** versions. See if the version we are running on has it, and if it
356 ** does, save off a pointer to it and the current process handle.
357 */
358 hProcess = GetCurrentProcess();
359 if( hProcess ){
360 HINSTANCE hinstLib = LoadLibrary(TEXT("Kernel32.dll"));
361 if( NULL != hinstLib ){
362 getProcessTimesAddr =
363 (GETPROCTIMES) GetProcAddress(hinstLib, "GetProcessTimes");
364 if( NULL != getProcessTimesAddr ){
365 return 1;
366 }
367 FreeLibrary(hinstLib);
368 }
369 }
mistachkin43e86272020-04-09 15:31:22 +0000370#endif
drh2ce15c32017-07-11 13:34:40 +0000371 }
372 return 0;
373}
374
375/*
376** Begin timing an operation
377*/
378static void beginTimer(void){
379 if( enableTimer && getProcessTimesAddr ){
380 FILETIME ftCreation, ftExit;
381 getProcessTimesAddr(hProcess,&ftCreation,&ftExit,
382 &ftKernelBegin,&ftUserBegin);
383 ftWallBegin = timeOfDay();
384 }
385}
386
387/* Return the difference of two FILETIME structs in seconds */
388static double timeDiff(FILETIME *pStart, FILETIME *pEnd){
389 sqlite_int64 i64Start = *((sqlite_int64 *) pStart);
390 sqlite_int64 i64End = *((sqlite_int64 *) pEnd);
391 return (double) ((i64End - i64Start) / 10000000.0);
392}
393
394/*
395** Print the timing results.
396*/
397static void endTimer(void){
398 if( enableTimer && getProcessTimesAddr){
399 FILETIME ftCreation, ftExit, ftKernelEnd, ftUserEnd;
400 sqlite3_int64 ftWallEnd = timeOfDay();
401 getProcessTimesAddr(hProcess,&ftCreation,&ftExit,&ftKernelEnd,&ftUserEnd);
402 printf("Run Time: real %.3f user %f sys %f\n",
403 (ftWallEnd - ftWallBegin)*0.001,
404 timeDiff(&ftUserBegin, &ftUserEnd),
405 timeDiff(&ftKernelBegin, &ftKernelEnd));
406 }
407}
408
409#define BEGIN_TIMER beginTimer()
410#define END_TIMER endTimer()
411#define HAS_TIMER hasTimer()
412
413#else
414#define BEGIN_TIMER
415#define END_TIMER
416#define HAS_TIMER 0
417#endif
418
419/*
420** Used to prevent warnings about unused parameters
421*/
422#define UNUSED_PARAMETER(x) (void)(x)
423
424/*
drh5af06982018-01-10 00:53:55 +0000425** Number of elements in an array
426*/
427#define ArraySize(X) (int)(sizeof(X)/sizeof(X[0]))
428
429/*
drh2ce15c32017-07-11 13:34:40 +0000430** If the following flag is set, then command execution stops
431** at an error if we are not interactive.
432*/
433static int bail_on_error = 0;
434
435/*
436** Threat stdin as an interactive input if the following variable
437** is true. Otherwise, assume stdin is connected to a file or pipe.
438*/
439static int stdin_is_interactive = 1;
440
441/*
442** On Windows systems we have to know if standard output is a console
443** in order to translate UTF-8 into MBCS. The following variable is
444** true if translation is required.
445*/
446static int stdout_is_console = 1;
447
448/*
449** The following is the open SQLite database. We make a pointer
450** to this database a static variable so that it can be accessed
451** by the SIGINT handler to interrupt database processing.
452*/
453static sqlite3 *globalDb = 0;
454
455/*
456** True if an interrupt (Control-C) has been received.
457*/
458static volatile int seenInterrupt = 0;
459
460/*
461** This is the name of our program. It is set in main(), used
462** in a number of other places, mostly for error messages.
463*/
464static char *Argv0;
465
466/*
467** Prompt strings. Initialized in main. Settable with
468** .prompt main continue
469*/
470static char mainPrompt[20]; /* First line prompt. default: "sqlite> "*/
471static char continuePrompt[20]; /* Continuation prompt. default: " ...> " */
472
473/*
474** Render output like fprintf(). Except, if the output is going to the
475** console and if this is running on a Windows machine, translate the
476** output from UTF-8 into MBCS.
477*/
478#if defined(_WIN32) || defined(WIN32)
479void utf8_printf(FILE *out, const char *zFormat, ...){
480 va_list ap;
481 va_start(ap, zFormat);
482 if( stdout_is_console && (out==stdout || out==stderr) ){
483 char *z1 = sqlite3_vmprintf(zFormat, ap);
484 char *z2 = sqlite3_win32_utf8_to_mbcs_v2(z1, 0);
485 sqlite3_free(z1);
486 fputs(z2, out);
487 sqlite3_free(z2);
488 }else{
489 vfprintf(out, zFormat, ap);
490 }
491 va_end(ap);
492}
493#elif !defined(utf8_printf)
494# define utf8_printf fprintf
495#endif
496
497/*
498** Render output like fprintf(). This should not be used on anything that
499** includes string formatting (e.g. "%s").
500*/
501#if !defined(raw_printf)
502# define raw_printf fprintf
503#endif
504
drh4b5345c2018-04-24 13:07:40 +0000505/* Indicate out-of-memory and exit. */
506static void shell_out_of_memory(void){
507 raw_printf(stderr,"Error: out of memory\n");
508 exit(1);
509}
510
drhe3e25652021-12-16 13:29:28 +0000511/* Check a pointer to see if it is NULL. If it is NULL, exit with an
512** out-of-memory error.
513*/
514static void shell_check_oom(void *p){
515 if( p==0 ) shell_out_of_memory();
516}
517
drh2ce15c32017-07-11 13:34:40 +0000518/*
519** Write I/O traces to the following stream.
520*/
521#ifdef SQLITE_ENABLE_IOTRACE
522static FILE *iotrace = 0;
523#endif
524
525/*
526** This routine works like printf in that its first argument is a
527** format string and subsequent arguments are values to be substituted
528** in place of % fields. The result of formatting this string
529** is written to iotrace.
530*/
531#ifdef SQLITE_ENABLE_IOTRACE
532static void SQLITE_CDECL iotracePrintf(const char *zFormat, ...){
533 va_list ap;
534 char *z;
535 if( iotrace==0 ) return;
536 va_start(ap, zFormat);
537 z = sqlite3_vmprintf(zFormat, ap);
538 va_end(ap);
539 utf8_printf(iotrace, "%s", z);
540 sqlite3_free(z);
541}
542#endif
543
544/*
545** Output string zUtf to stream pOut as w characters. If w is negative,
546** then right-justify the text. W is the width in UTF-8 characters, not
547** in bytes. This is different from the %*.*s specification in printf
548** since with %*.*s the width is measured in bytes, not characters.
549*/
550static void utf8_width_print(FILE *pOut, int w, const char *zUtf){
551 int i;
552 int n;
553 int aw = w<0 ? -w : w;
drh4853aa12022-10-27 18:20:08 +0000554 if( zUtf==0 ) zUtf = "";
drh2ce15c32017-07-11 13:34:40 +0000555 for(i=n=0; zUtf[i]; i++){
556 if( (zUtf[i]&0xc0)!=0x80 ){
557 n++;
558 if( n==aw ){
559 do{ i++; }while( (zUtf[i]&0xc0)==0x80 );
560 break;
561 }
562 }
563 }
564 if( n>=aw ){
565 utf8_printf(pOut, "%.*s", i, zUtf);
566 }else if( w<0 ){
567 utf8_printf(pOut, "%*s%s", aw-n, "", zUtf);
568 }else{
569 utf8_printf(pOut, "%s%*s", zUtf, aw-n, "");
570 }
571}
572
573
574/*
575** Determines if a string is a number of not.
576*/
577static int isNumber(const char *z, int *realnum){
578 if( *z=='-' || *z=='+' ) z++;
579 if( !IsDigit(*z) ){
580 return 0;
581 }
582 z++;
583 if( realnum ) *realnum = 0;
584 while( IsDigit(*z) ){ z++; }
585 if( *z=='.' ){
586 z++;
587 if( !IsDigit(*z) ) return 0;
588 while( IsDigit(*z) ){ z++; }
589 if( realnum ) *realnum = 1;
590 }
591 if( *z=='e' || *z=='E' ){
592 z++;
593 if( *z=='+' || *z=='-' ) z++;
594 if( !IsDigit(*z) ) return 0;
595 while( IsDigit(*z) ){ z++; }
596 if( realnum ) *realnum = 1;
597 }
598 return *z==0;
599}
600
601/*
602** Compute a string length that is limited to what can be stored in
603** lower 30 bits of a 32-bit signed integer.
604*/
605static int strlen30(const char *z){
606 const char *z2 = z;
607 while( *z2 ){ z2++; }
608 return 0x3fffffff & (int)(z2 - z);
609}
610
611/*
612** Return the length of a string in characters. Multibyte UTF8 characters
613** count as a single character.
614*/
615static int strlenChar(const char *z){
616 int n = 0;
617 while( *z ){
618 if( (0xc0&*(z++))!=0x80 ) n++;
619 }
620 return n;
621}
622
623/*
larrybrd96bcc72021-09-17 21:12:47 +0000624** Return open FILE * if zFile exists, can be opened for read
625** and is an ordinary file or a character stream source.
626** Otherwise return 0.
drhbbd620e2020-07-20 23:33:11 +0000627*/
larrybrd96bcc72021-09-17 21:12:47 +0000628static FILE * openChrSource(const char *zFile){
drhbbd620e2020-07-20 23:33:11 +0000629#ifdef _WIN32
larrybrd0007852021-09-13 23:11:46 +0000630 struct _stat x = {0};
larrybrd0007852021-09-13 23:11:46 +0000631# define STAT_CHR_SRC(mode) ((mode & (_S_IFCHR|_S_IFIFO|_S_IFREG))!=0)
larrybrd96bcc72021-09-17 21:12:47 +0000632 /* On Windows, open first, then check the stream nature. This order
633 ** is necessary because _stat() and sibs, when checking a named pipe,
634 ** effectively break the pipe as its supplier sees it. */
635 FILE *rv = fopen(zFile, "rb");
636 if( rv==0 ) return 0;
637 if( _fstat(_fileno(rv), &x) != 0
638 || !STAT_CHR_SRC(x.st_mode)){
639 fclose(rv);
640 rv = 0;
641 }
642 return rv;
drhbbd620e2020-07-20 23:33:11 +0000643#else
larrybrd0007852021-09-13 23:11:46 +0000644 struct stat x = {0};
645 int rc = stat(zFile, &x);
646# define STAT_CHR_SRC(mode) (S_ISREG(mode)||S_ISFIFO(mode)||S_ISCHR(mode))
larrybrd96bcc72021-09-17 21:12:47 +0000647 if( rc!=0 ) return 0;
648 if( STAT_CHR_SRC(x.st_mode) ){
649 return fopen(zFile, "rb");
650 }else{
651 return 0;
652 }
drhbbd620e2020-07-20 23:33:11 +0000653#endif
larrybrd0007852021-09-13 23:11:46 +0000654#undef STAT_CHR_SRC
655}
drhbbd620e2020-07-20 23:33:11 +0000656
657/*
drh2ce15c32017-07-11 13:34:40 +0000658** This routine reads a line of text from FILE in, stores
659** the text in memory obtained from malloc() and returns a pointer
660** to the text. NULL is returned at end of file, or if malloc()
661** fails.
662**
663** If zLine is not NULL then it is a malloced buffer returned from
664** a previous call to this routine that may be reused.
665*/
666static char *local_getline(char *zLine, FILE *in){
667 int nLine = zLine==0 ? 0 : 100;
668 int n = 0;
669
670 while( 1 ){
671 if( n+100>nLine ){
672 nLine = nLine*2 + 100;
673 zLine = realloc(zLine, nLine);
drhe3e25652021-12-16 13:29:28 +0000674 shell_check_oom(zLine);
drh2ce15c32017-07-11 13:34:40 +0000675 }
676 if( fgets(&zLine[n], nLine - n, in)==0 ){
677 if( n==0 ){
678 free(zLine);
679 return 0;
680 }
681 zLine[n] = 0;
682 break;
683 }
684 while( zLine[n] ) n++;
685 if( n>0 && zLine[n-1]=='\n' ){
686 n--;
687 if( n>0 && zLine[n-1]=='\r' ) n--;
688 zLine[n] = 0;
689 break;
690 }
691 }
692#if defined(_WIN32) || defined(WIN32)
693 /* For interactive input on Windows systems, translate the
694 ** multi-byte characterset characters into UTF-8. */
695 if( stdin_is_interactive && in==stdin ){
696 char *zTrans = sqlite3_win32_mbcs_to_utf8_v2(zLine, 0);
697 if( zTrans ){
drh7d23d152022-10-11 12:02:42 +0000698 i64 nTrans = strlen(zTrans)+1;
drh2ce15c32017-07-11 13:34:40 +0000699 if( nTrans>nLine ){
700 zLine = realloc(zLine, nTrans);
drhe3e25652021-12-16 13:29:28 +0000701 shell_check_oom(zLine);
drh2ce15c32017-07-11 13:34:40 +0000702 }
703 memcpy(zLine, zTrans, nTrans);
704 sqlite3_free(zTrans);
705 }
706 }
707#endif /* defined(_WIN32) || defined(WIN32) */
708 return zLine;
709}
710
711/*
712** Retrieve a single line of input text.
713**
714** If in==0 then read from standard input and prompt before each line.
715** If isContinuation is true, then a continuation prompt is appropriate.
716** If isContinuation is zero, then the main prompt should be used.
717**
718** If zPrior is not NULL then it is a buffer from a prior call to this
719** routine that can be reused.
720**
721** The result is stored in space obtained from malloc() and must either
722** be freed by the caller or else passed back into this routine via the
723** zPrior argument for reuse.
724*/
stephan4413ec72022-07-12 15:53:02 +0000725#ifndef SQLITE_SHELL_FIDDLE
drh2ce15c32017-07-11 13:34:40 +0000726static char *one_input_line(FILE *in, char *zPrior, int isContinuation){
727 char *zPrompt;
728 char *zResult;
729 if( in!=0 ){
730 zResult = local_getline(zPrior, in);
731 }else{
732 zPrompt = isContinuation ? continuePrompt : mainPrompt;
733#if SHELL_USE_LOCAL_GETLINE
734 printf("%s", zPrompt);
735 fflush(stdout);
736 zResult = local_getline(zPrior, stdin);
737#else
738 free(zPrior);
739 zResult = shell_readline(zPrompt);
740 if( zResult && *zResult ) shell_add_history(zResult);
741#endif
742 }
743 return zResult;
744}
stephan4413ec72022-07-12 15:53:02 +0000745#endif /* !SQLITE_SHELL_FIDDLE */
drh5af06982018-01-10 00:53:55 +0000746
747/*
748** Return the value of a hexadecimal digit. Return -1 if the input
749** is not a hex digit.
750*/
751static int hexDigitValue(char c){
752 if( c>='0' && c<='9' ) return c - '0';
753 if( c>='a' && c<='f' ) return c - 'a' + 10;
754 if( c>='A' && c<='F' ) return c - 'A' + 10;
755 return -1;
756}
757
758/*
759** Interpret zArg as an integer value, possibly with suffixes.
760*/
761static sqlite3_int64 integerValue(const char *zArg){
762 sqlite3_int64 v = 0;
763 static const struct { char *zSuffix; int iMult; } aMult[] = {
764 { "KiB", 1024 },
765 { "MiB", 1024*1024 },
766 { "GiB", 1024*1024*1024 },
767 { "KB", 1000 },
768 { "MB", 1000000 },
769 { "GB", 1000000000 },
770 { "K", 1000 },
771 { "M", 1000000 },
772 { "G", 1000000000 },
773 };
774 int i;
775 int isNeg = 0;
776 if( zArg[0]=='-' ){
777 isNeg = 1;
778 zArg++;
779 }else if( zArg[0]=='+' ){
780 zArg++;
781 }
782 if( zArg[0]=='0' && zArg[1]=='x' ){
783 int x;
784 zArg += 2;
785 while( (x = hexDigitValue(zArg[0]))>=0 ){
786 v = (v<<4) + x;
787 zArg++;
788 }
789 }else{
790 while( IsDigit(zArg[0]) ){
791 v = v*10 + zArg[0] - '0';
792 zArg++;
793 }
794 }
795 for(i=0; i<ArraySize(aMult); i++){
796 if( sqlite3_stricmp(aMult[i].zSuffix, zArg)==0 ){
797 v *= aMult[i].iMult;
798 break;
799 }
800 }
801 return isNeg? -v : v;
802}
803
drh2ce15c32017-07-11 13:34:40 +0000804/*
805** A variable length string to which one can append text.
806*/
807typedef struct ShellText ShellText;
808struct ShellText {
809 char *z;
810 int n;
811 int nAlloc;
812};
813
814/*
815** Initialize and destroy a ShellText object
816*/
817static void initText(ShellText *p){
818 memset(p, 0, sizeof(*p));
819}
820static void freeText(ShellText *p){
821 free(p->z);
822 initText(p);
823}
824
825/* zIn is either a pointer to a NULL-terminated string in memory obtained
826** from malloc(), or a NULL pointer. The string pointed to by zAppend is
827** added to zIn, and the result returned in memory obtained from malloc().
828** zIn, if it was not NULL, is freed.
829**
830** If the third argument, quote, is not '\0', then it is used as a
831** quote character for zAppend.
832*/
stephan0076e492022-05-18 18:10:17 +0000833static void appendText(ShellText *p, const char *zAppend, char quote){
drh7d23d152022-10-11 12:02:42 +0000834 i64 len;
835 i64 i;
836 i64 nAppend = strlen30(zAppend);
drh2ce15c32017-07-11 13:34:40 +0000837
838 len = nAppend+p->n+1;
839 if( quote ){
840 len += 2;
841 for(i=0; i<nAppend; i++){
842 if( zAppend[i]==quote ) len++;
843 }
844 }
845
drh11a9ad52021-10-04 18:21:14 +0000846 if( p->z==0 || p->n+len>=p->nAlloc ){
drh2ce15c32017-07-11 13:34:40 +0000847 p->nAlloc = p->nAlloc*2 + len + 20;
848 p->z = realloc(p->z, p->nAlloc);
drhe3e25652021-12-16 13:29:28 +0000849 shell_check_oom(p->z);
drh2ce15c32017-07-11 13:34:40 +0000850 }
851
852 if( quote ){
853 char *zCsr = p->z+p->n;
854 *zCsr++ = quote;
855 for(i=0; i<nAppend; i++){
856 *zCsr++ = zAppend[i];
857 if( zAppend[i]==quote ) *zCsr++ = quote;
858 }
859 *zCsr++ = quote;
860 p->n = (int)(zCsr - p->z);
861 *zCsr = '\0';
862 }else{
863 memcpy(p->z+p->n, zAppend, nAppend);
864 p->n += nAppend;
865 p->z[p->n] = '\0';
866 }
867}
868
869/*
870** Attempt to determine if identifier zName needs to be quoted, either
871** because it contains non-alphanumeric characters, or because it is an
872** SQLite keyword. Be conservative in this estimate: When in doubt assume
873** that quoting is required.
874**
875** Return '"' if quoting is required. Return 0 if no quoting is required.
876*/
877static char quoteChar(const char *zName){
drhfc0ec3e2018-04-25 19:02:48 +0000878 int i;
drh2ce15c32017-07-11 13:34:40 +0000879 if( !isalpha((unsigned char)zName[0]) && zName[0]!='_' ) return '"';
880 for(i=0; zName[i]; i++){
881 if( !isalnum((unsigned char)zName[i]) && zName[i]!='_' ) return '"';
882 }
drhfc0ec3e2018-04-25 19:02:48 +0000883 return sqlite3_keyword_check(zName, i) ? '"' : 0;
drh2ce15c32017-07-11 13:34:40 +0000884}
885
886/*
drh667a2a22018-01-02 00:04:37 +0000887** Construct a fake object name and column list to describe the structure
888** of the view, virtual table, or table valued function zSchema.zName.
drhceba7922018-01-01 21:28:25 +0000889*/
drh667a2a22018-01-02 00:04:37 +0000890static char *shellFakeSchema(
drhceba7922018-01-01 21:28:25 +0000891 sqlite3 *db, /* The database connection containing the vtab */
892 const char *zSchema, /* Schema of the database holding the vtab */
893 const char *zName /* The name of the virtual table */
894){
895 sqlite3_stmt *pStmt = 0;
896 char *zSql;
drh1d315cf2018-01-01 21:49:43 +0000897 ShellText s;
898 char cQuote;
899 char *zDiv = "(";
drh667a2a22018-01-02 00:04:37 +0000900 int nRow = 0;
drhceba7922018-01-01 21:28:25 +0000901
drh1d315cf2018-01-01 21:49:43 +0000902 zSql = sqlite3_mprintf("PRAGMA \"%w\".table_info=%Q;",
903 zSchema ? zSchema : "main", zName);
drhe3e25652021-12-16 13:29:28 +0000904 shell_check_oom(zSql);
drhceba7922018-01-01 21:28:25 +0000905 sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
906 sqlite3_free(zSql);
drh1d315cf2018-01-01 21:49:43 +0000907 initText(&s);
908 if( zSchema ){
909 cQuote = quoteChar(zSchema);
910 if( cQuote && sqlite3_stricmp(zSchema,"temp")==0 ) cQuote = 0;
911 appendText(&s, zSchema, cQuote);
912 appendText(&s, ".", 0);
drhceba7922018-01-01 21:28:25 +0000913 }
drh1d315cf2018-01-01 21:49:43 +0000914 cQuote = quoteChar(zName);
915 appendText(&s, zName, cQuote);
916 while( sqlite3_step(pStmt)==SQLITE_ROW ){
917 const char *zCol = (const char*)sqlite3_column_text(pStmt, 1);
drh667a2a22018-01-02 00:04:37 +0000918 nRow++;
drh1d315cf2018-01-01 21:49:43 +0000919 appendText(&s, zDiv, 0);
920 zDiv = ",";
drh621a5e02021-12-16 17:35:27 +0000921 if( zCol==0 ) zCol = "";
drh1d315cf2018-01-01 21:49:43 +0000922 cQuote = quoteChar(zCol);
923 appendText(&s, zCol, cQuote);
924 }
925 appendText(&s, ")", 0);
drhceba7922018-01-01 21:28:25 +0000926 sqlite3_finalize(pStmt);
drh667a2a22018-01-02 00:04:37 +0000927 if( nRow==0 ){
928 freeText(&s);
929 s.z = 0;
930 }
drh1d315cf2018-01-01 21:49:43 +0000931 return s.z;
drhceba7922018-01-01 21:28:25 +0000932}
933
934/*
drh667a2a22018-01-02 00:04:37 +0000935** SQL function: shell_module_schema(X)
936**
937** Return a fake schema for the table-valued function or eponymous virtual
938** table X.
939*/
940static void shellModuleSchema(
941 sqlite3_context *pCtx,
942 int nVal,
943 sqlite3_value **apVal
944){
drh511b1182021-12-16 13:56:04 +0000945 const char *zName;
946 char *zFake;
drhb9685182018-01-17 13:15:23 +0000947 UNUSED_PARAMETER(nVal);
drh511b1182021-12-16 13:56:04 +0000948 zName = (const char*)sqlite3_value_text(apVal[0]);
949 zFake = zName ? shellFakeSchema(sqlite3_context_db_handle(pCtx), 0, zName) : 0;
drh667a2a22018-01-02 00:04:37 +0000950 if( zFake ){
dandcfbff92018-01-08 17:05:32 +0000951 sqlite3_result_text(pCtx, sqlite3_mprintf("/* %s */", zFake),
drh667a2a22018-01-02 00:04:37 +0000952 -1, sqlite3_free);
dandcfbff92018-01-08 17:05:32 +0000953 free(zFake);
drh667a2a22018-01-02 00:04:37 +0000954 }
955}
956
957/*
drh2ce15c32017-07-11 13:34:40 +0000958** SQL function: shell_add_schema(S,X)
959**
960** Add the schema name X to the CREATE statement in S and return the result.
961** Examples:
962**
963** CREATE TABLE t1(x) -> CREATE TABLE xyz.t1(x);
964**
965** Also works on
966**
967** CREATE INDEX
968** CREATE UNIQUE INDEX
969** CREATE VIEW
970** CREATE TRIGGER
971** CREATE VIRTUAL TABLE
972**
973** This UDF is used by the .schema command to insert the schema name of
drh067b92b2020-06-19 15:24:12 +0000974** attached databases into the middle of the sqlite_schema.sql field.
drh2ce15c32017-07-11 13:34:40 +0000975*/
976static void shellAddSchemaName(
977 sqlite3_context *pCtx,
978 int nVal,
979 sqlite3_value **apVal
980){
981 static const char *aPrefix[] = {
982 "TABLE",
983 "INDEX",
984 "UNIQUE INDEX",
985 "VIEW",
986 "TRIGGER",
987 "VIRTUAL TABLE"
988 };
989 int i = 0;
990 const char *zIn = (const char*)sqlite3_value_text(apVal[0]);
991 const char *zSchema = (const char*)sqlite3_value_text(apVal[1]);
drh667a2a22018-01-02 00:04:37 +0000992 const char *zName = (const char*)sqlite3_value_text(apVal[2]);
drhceba7922018-01-01 21:28:25 +0000993 sqlite3 *db = sqlite3_context_db_handle(pCtx);
drhb9685182018-01-17 13:15:23 +0000994 UNUSED_PARAMETER(nVal);
drhbf70f1b2022-10-19 18:04:42 +0000995 if( zIn!=0 && cli_strncmp(zIn, "CREATE ", 7)==0 ){
drh37407122021-07-23 18:43:58 +0000996 for(i=0; i<ArraySize(aPrefix); i++){
drh2ce15c32017-07-11 13:34:40 +0000997 int n = strlen30(aPrefix[i]);
drhbf70f1b2022-10-19 18:04:42 +0000998 if( cli_strncmp(zIn+7, aPrefix[i], n)==0 && zIn[n+7]==' ' ){
drhceba7922018-01-01 21:28:25 +0000999 char *z = 0;
drh667a2a22018-01-02 00:04:37 +00001000 char *zFake = 0;
drhceba7922018-01-01 21:28:25 +00001001 if( zSchema ){
1002 char cQuote = quoteChar(zSchema);
1003 if( cQuote && sqlite3_stricmp(zSchema,"temp")!=0 ){
1004 z = sqlite3_mprintf("%.*s \"%w\".%s", n+7, zIn, zSchema, zIn+n+8);
1005 }else{
1006 z = sqlite3_mprintf("%.*s %s.%s", n+7, zIn, zSchema, zIn+n+8);
1007 }
drh2ce15c32017-07-11 13:34:40 +00001008 }
drh667a2a22018-01-02 00:04:37 +00001009 if( zName
1010 && aPrefix[i][0]=='V'
1011 && (zFake = shellFakeSchema(db, zSchema, zName))!=0
1012 ){
1013 if( z==0 ){
dandcfbff92018-01-08 17:05:32 +00001014 z = sqlite3_mprintf("%s\n/* %s */", zIn, zFake);
drh667a2a22018-01-02 00:04:37 +00001015 }else{
dandcfbff92018-01-08 17:05:32 +00001016 z = sqlite3_mprintf("%z\n/* %s */", z, zFake);
drh667a2a22018-01-02 00:04:37 +00001017 }
dandcfbff92018-01-08 17:05:32 +00001018 free(zFake);
drhceba7922018-01-01 21:28:25 +00001019 }
1020 if( z ){
1021 sqlite3_result_text(pCtx, z, -1, sqlite3_free);
1022 return;
1023 }
drh2ce15c32017-07-11 13:34:40 +00001024 }
1025 }
1026 }
1027 sqlite3_result_value(pCtx, apVal[0]);
1028}
1029
1030/*
1031** The source code for several run-time loadable extensions is inserted
1032** below by the ../tool/mkshellc.tcl script. Before processing that included
1033** code, we need to override some macros to make the included program code
1034** work here in the middle of this regular program.
1035*/
1036#define SQLITE_EXTENSION_INIT1
drh89997982017-07-11 18:11:33 +00001037#define SQLITE_EXTENSION_INIT2(X) (void)(X)
drh2ce15c32017-07-11 13:34:40 +00001038
mistachkinacae8c32018-01-05 20:08:46 +00001039#if defined(_WIN32) && defined(_MSC_VER)
drh03491a12018-01-07 21:58:17 +00001040INCLUDE test_windirent.h
mistachkindfdfd8c2018-01-04 22:46:08 +00001041INCLUDE test_windirent.c
1042#define dirent DIRENT
mistachkindfdfd8c2018-01-04 22:46:08 +00001043#endif
drh50b910a2019-01-21 14:55:03 +00001044INCLUDE ../ext/misc/memtrace.c
stephanf8cd3d22022-05-18 17:14:24 +00001045INCLUDE ../ext/misc/shathree.c
drhf05dd032020-04-14 15:53:58 +00001046INCLUDE ../ext/misc/uint.c
drhbeb9def2020-06-22 19:12:23 +00001047INCLUDE ../ext/misc/decimal.c
drh8cda77d2020-06-24 15:06:29 +00001048INCLUDE ../ext/misc/ieee754.c
mistachkin72c38d82020-08-28 18:47:39 +00001049INCLUDE ../ext/misc/series.c
drh64689902021-06-03 13:51:31 +00001050INCLUDE ../ext/misc/regexp.c
stephan4413ec72022-07-12 15:53:02 +00001051#ifndef SQLITE_SHELL_FIDDLE
stephanf8cd3d22022-05-18 17:14:24 +00001052INCLUDE ../ext/misc/fileio.c
1053INCLUDE ../ext/misc/completion.c
1054INCLUDE ../ext/misc/appendvfs.c
1055#endif
dan72afc3c2017-12-05 18:32:40 +00001056#ifdef SQLITE_HAVE_ZLIB
dan9ebfaad2017-12-26 20:39:58 +00001057INCLUDE ../ext/misc/zipfile.c
dand1b51d42017-12-16 19:11:26 +00001058INCLUDE ../ext/misc/sqlar.c
dan72afc3c2017-12-05 18:32:40 +00001059#endif
dan43efc182017-12-19 17:42:13 +00001060INCLUDE ../ext/expert/sqlite3expert.h
1061INCLUDE ../ext/expert/sqlite3expert.c
drh2ce15c32017-07-11 13:34:40 +00001062
stephanbb5136e2022-10-27 11:32:20 +00001063#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
stephan3d420832022-10-27 03:56:01 +00001064#define SQLITE_SHELL_HAVE_RECOVER 1
1065#else
1066#define SQLITE_SHELL_HAVE_RECOVER 0
1067#endif
1068#if SQLITE_SHELL_HAVE_RECOVER
dan9a27d652022-09-08 19:22:29 +00001069INCLUDE ../ext/recover/sqlite3recover.h
dan63b74e02022-11-22 16:12:53 +00001070# ifndef SQLITE_HAVE_SQLITE3R
1071INCLUDE ../ext/recover/dbdata.c
dan9a27d652022-09-08 19:22:29 +00001072INCLUDE ../ext/recover/sqlite3recover.c
dan63b74e02022-11-22 16:12:53 +00001073# endif
dan1b162162019-04-27 20:15:15 +00001074#endif
dan68cb86e2019-04-20 20:57:28 +00001075
drh2ce15c32017-07-11 13:34:40 +00001076#if defined(SQLITE_ENABLE_SESSION)
1077/*
1078** State information for a single open session
1079*/
1080typedef struct OpenSession OpenSession;
1081struct OpenSession {
1082 char *zName; /* Symbolic name for this session */
1083 int nFilter; /* Number of xFilter rejection GLOB patterns */
1084 char **azFilter; /* Array of xFilter rejection GLOB patterns */
1085 sqlite3_session *p; /* The open session */
1086};
1087#endif
1088
dan43efc182017-12-19 17:42:13 +00001089typedef struct ExpertInfo ExpertInfo;
1090struct ExpertInfo {
1091 sqlite3expert *pExpert;
1092 int bVerbose;
1093};
1094
drh4b5345c2018-04-24 13:07:40 +00001095/* A single line in the EQP output */
1096typedef struct EQPGraphRow EQPGraphRow;
1097struct EQPGraphRow {
drhe2ca99c2018-05-02 00:33:43 +00001098 int iEqpId; /* ID for this row */
1099 int iParentId; /* ID of the parent row */
drh4b5345c2018-04-24 13:07:40 +00001100 EQPGraphRow *pNext; /* Next row in sequence */
1101 char zText[1]; /* Text to display for this row */
1102};
1103
1104/* All EQP output is collected into an instance of the following */
1105typedef struct EQPGraph EQPGraph;
1106struct EQPGraph {
1107 EQPGraphRow *pRow; /* Linked list of all rows of the EQP output */
1108 EQPGraphRow *pLast; /* Last element of the pRow list */
1109 char zPrefix[100]; /* Graph prefix */
1110};
1111
larrybrcc4d55c2022-02-01 02:50:45 +00001112/* Parameters affecting columnar mode result display (defaulting together) */
1113typedef struct ColModeOpts {
1114 int iWrap; /* In columnar modes, wrap lines reaching this limit */
1115 u8 bQuote; /* Quote results for .mode box and table */
1116 u8 bWordWrap; /* In columnar modes, wrap at word boundaries */
1117} ColModeOpts;
1118#define ColModeOpts_default { 60, 0, 0 }
1119#define ColModeOpts_default_qbox { 60, 1, 0 }
larrybrcc4d55c2022-02-01 02:50:45 +00001120
drh2ce15c32017-07-11 13:34:40 +00001121/*
1122** State information about the database connection is contained in an
1123** instance of the following structure.
1124*/
1125typedef struct ShellState ShellState;
1126struct ShellState {
1127 sqlite3 *db; /* The database */
drh1fa6d9f2018-01-06 21:46:01 +00001128 u8 autoExplain; /* Automatically turn on .explain mode */
1129 u8 autoEQP; /* Run EXPLAIN QUERY PLAN prior to seach SQL stmt */
drhe2ca99c2018-05-02 00:33:43 +00001130 u8 autoEQPtest; /* autoEQP is in test mode */
drhb4e50392019-01-26 15:40:04 +00001131 u8 autoEQPtrace; /* autoEQP is in trace mode */
drh1fa6d9f2018-01-06 21:46:01 +00001132 u8 scanstatsOn; /* True to display scan stats before each finalize */
1133 u8 openMode; /* SHELL_OPEN_NORMAL, _APPENDVFS, or _ZIPFILE */
drh13c20932018-01-10 21:41:55 +00001134 u8 doXdgOpen; /* Invoke start/open/xdg-open in output_reset() */
drh4b5345c2018-04-24 13:07:40 +00001135 u8 nEqpLevel; /* Depth of the EQP output graph */
drh707821f2018-12-05 13:39:06 +00001136 u8 eTraceType; /* SHELL_TRACE_* value for type of trace */
drhb97e2ad2021-08-26 18:31:39 +00001137 u8 bSafeMode; /* True to prohibit unsafe operations */
1138 u8 bSafeModePersist; /* The long-term value of bSafeMode */
larrybrcc4d55c2022-02-01 02:50:45 +00001139 ColModeOpts cmOpts; /* Option values affecting columnar mode output */
drha6e6cf22021-01-09 19:10:04 +00001140 unsigned statsOn; /* True to display memory stats before each finalize */
drh4b5345c2018-04-24 13:07:40 +00001141 unsigned mEqpLines; /* Mask of veritical lines in the EQP output graph */
larrybrd48e88e2022-01-24 06:36:16 +00001142 int inputNesting; /* Track nesting level of .read and other redirects */
drh2ce15c32017-07-11 13:34:40 +00001143 int outCount; /* Revert to stdout when reaching zero */
1144 int cnt; /* Number of records displayed so far */
drh2c8ee022018-12-13 18:59:30 +00001145 int lineno; /* Line number of last line read from in */
drh0933aad2019-11-18 17:46:38 +00001146 int openFlags; /* Additional flags to open. (SQLITE_OPEN_NOFOLLOW) */
drh60379d42018-12-13 18:30:01 +00001147 FILE *in; /* Read commands from this stream */
drh2ce15c32017-07-11 13:34:40 +00001148 FILE *out; /* Write results here */
1149 FILE *traceOut; /* Output for sqlite3_trace() */
1150 int nErr; /* Number of errors seen */
1151 int mode; /* An output mode setting */
drh3c484e82018-01-10 22:27:21 +00001152 int modePrior; /* Saved mode */
drh2ce15c32017-07-11 13:34:40 +00001153 int cMode; /* temporary output mode for the current query */
1154 int normalMode; /* Output mode before ".explain on" */
1155 int writableSchema; /* True if PRAGMA writable_schema=ON */
1156 int showHeader; /* True to show column names in List or Column mode */
1157 int nCheck; /* Number of ".check" commands run */
drh3f83f592019-02-04 14:53:18 +00001158 unsigned nProgress; /* Number of progress callbacks encountered */
1159 unsigned mxProgress; /* Maximum progress callbacks before failing */
1160 unsigned flgProgress; /* Flags for the progress callback */
drh2ce15c32017-07-11 13:34:40 +00001161 unsigned shellFlgs; /* Various flags */
drh7a431002020-04-18 14:12:00 +00001162 unsigned priorShFlgs; /* Saved copy of flags */
drh6ca64482019-01-22 16:06:20 +00001163 sqlite3_int64 szMax; /* --maxsize argument to .open */
drh2ce15c32017-07-11 13:34:40 +00001164 char *zDestTable; /* Name of destination table when MODE_Insert */
drh13c20932018-01-10 21:41:55 +00001165 char *zTempFile; /* Temporary file that might need deleting */
drh2ce15c32017-07-11 13:34:40 +00001166 char zTestcase[30]; /* Name of current test case */
1167 char colSeparator[20]; /* Column separator character for several modes */
1168 char rowSeparator[20]; /* Row separator character for MODE_Ascii */
drh3c484e82018-01-10 22:27:21 +00001169 char colSepPrior[20]; /* Saved column separator */
1170 char rowSepPrior[20]; /* Saved row separator */
drh0285d982020-05-29 14:38:43 +00001171 int *colWidth; /* Requested width of each column in columnar modes */
1172 int *actualWidth; /* Actual width of each column */
1173 int nWidth; /* Number of slots in colWidth[] and actualWidth[] */
drh2ce15c32017-07-11 13:34:40 +00001174 char nullValue[20]; /* The text to print when a NULL comes back from
1175 ** the database */
1176 char outfile[FILENAME_MAX]; /* Filename for *out */
drh2ce15c32017-07-11 13:34:40 +00001177 sqlite3_stmt *pStmt; /* Current statement if any. */
1178 FILE *pLog; /* Write log output here */
drh37407122021-07-23 18:43:58 +00001179 struct AuxDb { /* Storage space for auxiliary database connections */
1180 sqlite3 *db; /* Connection pointer */
1181 const char *zDbFilename; /* Filename used to open the connection */
1182 char *zFreeOnClose; /* Free this memory allocation on close */
1183#if defined(SQLITE_ENABLE_SESSION)
1184 int nSession; /* Number of active sessions */
1185 OpenSession aSession[4]; /* Array of sessions. [0] is in focus. */
1186#endif
1187 } aAuxDb[5], /* Array of all database connections */
1188 *pAuxDb; /* Currently active database connection */
drh2ce15c32017-07-11 13:34:40 +00001189 int *aiIndent; /* Array of indents used in MODE_Explain */
1190 int nIndent; /* Size of array aiIndent[] */
1191 int iIndent; /* Index of current op in aiIndent[] */
drhb97e2ad2021-08-26 18:31:39 +00001192 char *zNonce; /* Nonce for temporary safe-mode excapes */
drh4b5345c2018-04-24 13:07:40 +00001193 EQPGraph sGraph; /* Information for the graphical EXPLAIN QUERY PLAN */
drhb97e2ad2021-08-26 18:31:39 +00001194 ExpertInfo expert; /* Valid if previous command was ".expert OPT..." */
stephan4413ec72022-07-12 15:53:02 +00001195#ifdef SQLITE_SHELL_FIDDLE
stephanf8cd3d22022-05-18 17:14:24 +00001196 struct {
1197 const char * zInput; /* Input string from wasm/JS proxy */
stephan0076e492022-05-18 18:10:17 +00001198 const char * zPos; /* Cursor pos into zInput */
stephan60d9aa72022-09-24 07:36:45 +00001199 const char * zDefaultDbName; /* Default name for db file */
stephanf8cd3d22022-05-18 17:14:24 +00001200 } wasm;
1201#endif
drh2ce15c32017-07-11 13:34:40 +00001202};
1203
stephan4413ec72022-07-12 15:53:02 +00001204#ifdef SQLITE_SHELL_FIDDLE
stephanf8cd3d22022-05-18 17:14:24 +00001205static ShellState shellState;
1206#endif
1207
drh1fa6d9f2018-01-06 21:46:01 +00001208
drhada70452017-12-21 21:02:27 +00001209/* Allowed values for ShellState.autoEQP
1210*/
drhe2ca99c2018-05-02 00:33:43 +00001211#define AUTOEQP_off 0 /* Automatic EXPLAIN QUERY PLAN is off */
1212#define AUTOEQP_on 1 /* Automatic EQP is on */
1213#define AUTOEQP_trigger 2 /* On and also show plans for triggers */
1214#define AUTOEQP_full 3 /* Show full EXPLAIN */
drhada70452017-12-21 21:02:27 +00001215
drh1fa6d9f2018-01-06 21:46:01 +00001216/* Allowed values for ShellState.openMode
1217*/
drh60f34ae2018-10-30 13:19:49 +00001218#define SHELL_OPEN_UNSPEC 0 /* No open-mode specified */
1219#define SHELL_OPEN_NORMAL 1 /* Normal database file */
1220#define SHELL_OPEN_APPENDVFS 2 /* Use appendvfs */
1221#define SHELL_OPEN_ZIPFILE 3 /* Use the zipfile virtual table */
1222#define SHELL_OPEN_READONLY 4 /* Open a normal database read-only */
1223#define SHELL_OPEN_DESERIALIZE 5 /* Open using sqlite3_deserialize() */
drh33746482018-12-13 15:06:26 +00001224#define SHELL_OPEN_HEXDB 6 /* Use "dbtotxt" output as data source */
drh1fa6d9f2018-01-06 21:46:01 +00001225
drh707821f2018-12-05 13:39:06 +00001226/* Allowed values for ShellState.eTraceType
1227*/
1228#define SHELL_TRACE_PLAIN 0 /* Show input SQL text */
1229#define SHELL_TRACE_EXPANDED 1 /* Show expanded SQL text */
1230#define SHELL_TRACE_NORMALIZED 2 /* Show normalized SQL text */
1231
drh3f83f592019-02-04 14:53:18 +00001232/* Bits in the ShellState.flgProgress variable */
drhfc4eeef2019-02-05 19:48:46 +00001233#define SHELL_PROGRESS_QUIET 0x01 /* Omit announcing every progress callback */
1234#define SHELL_PROGRESS_RESET 0x02 /* Reset the count when the progres
1235 ** callback limit is reached, and for each
1236 ** top-level SQL statement */
1237#define SHELL_PROGRESS_ONCE 0x04 /* Cancel the --limit after firing once */
drh3f83f592019-02-04 14:53:18 +00001238
drh2ce15c32017-07-11 13:34:40 +00001239/*
1240** These are the allowed shellFlgs values
1241*/
drhb2a0f752017-08-28 15:51:35 +00001242#define SHFLG_Pagecache 0x00000001 /* The --pagecache option is used */
1243#define SHFLG_Lookaside 0x00000002 /* Lookaside memory is used */
1244#define SHFLG_Backslash 0x00000004 /* The --backslash option is used */
1245#define SHFLG_PreserveRowid 0x00000008 /* .dump preserves rowid values */
1246#define SHFLG_Newlines 0x00000010 /* .dump --newline flag */
1247#define SHFLG_CountChanges 0x00000020 /* .changes setting */
larrybr527c39d2022-05-10 14:55:45 +00001248#define SHFLG_Echo 0x00000040 /* .echo on/off, or --echo setting */
larrybrae509122021-09-10 01:45:20 +00001249#define SHFLG_HeaderSet 0x00000080 /* showHeader has been specified */
drhc1962192020-10-12 16:54:28 +00001250#define SHFLG_DumpDataOnly 0x00000100 /* .dump show data only */
1251#define SHFLG_DumpNoSys 0x00000200 /* .dump omits system tables */
drh2ce15c32017-07-11 13:34:40 +00001252
1253/*
1254** Macros for testing and setting shellFlgs
1255*/
1256#define ShellHasFlag(P,X) (((P)->shellFlgs & (X))!=0)
1257#define ShellSetFlag(P,X) ((P)->shellFlgs|=(X))
1258#define ShellClearFlag(P,X) ((P)->shellFlgs&=(~(X)))
1259
1260/*
1261** These are the allowed modes.
1262*/
1263#define MODE_Line 0 /* One column per line. Blank line between records */
1264#define MODE_Column 1 /* One record per line in neat columns */
1265#define MODE_List 2 /* One record per line with a separator */
1266#define MODE_Semi 3 /* Same as MODE_List but append ";" to each line */
1267#define MODE_Html 4 /* Generate an XHTML table */
1268#define MODE_Insert 5 /* Generate SQL "insert" statements */
1269#define MODE_Quote 6 /* Quote values as for SQL */
1270#define MODE_Tcl 7 /* Generate ANSI-C or TCL quoted elements */
1271#define MODE_Csv 8 /* Quote strings, numbers are plain */
1272#define MODE_Explain 9 /* Like MODE_Column, but do not truncate data */
1273#define MODE_Ascii 10 /* Use ASCII unit and record separators (0x1F/0x1E) */
1274#define MODE_Pretty 11 /* Pretty-print schemas */
drh4b5345c2018-04-24 13:07:40 +00001275#define MODE_EQP 12 /* Converts EXPLAIN QUERY PLAN output into a graph */
drh30c54a02020-05-28 23:49:50 +00001276#define MODE_Json 13 /* Output JSON */
1277#define MODE_Markdown 14 /* Markdown formatting */
1278#define MODE_Table 15 /* MySQL-style table formatting */
drh0908e382020-06-04 18:05:39 +00001279#define MODE_Box 16 /* Unicode box-drawing characters */
drh5d88be82021-12-09 16:17:43 +00001280#define MODE_Count 17 /* Output only a count of the rows of output */
1281#define MODE_Off 18 /* No query output shown */
drh2ce15c32017-07-11 13:34:40 +00001282
1283static const char *modeDescr[] = {
1284 "line",
1285 "column",
1286 "list",
1287 "semi",
1288 "html",
1289 "insert",
1290 "quote",
1291 "tcl",
1292 "csv",
1293 "explain",
1294 "ascii",
1295 "prettyprint",
drh30c54a02020-05-28 23:49:50 +00001296 "eqp",
1297 "json",
1298 "markdown",
drh0908e382020-06-04 18:05:39 +00001299 "table",
drh5d88be82021-12-09 16:17:43 +00001300 "box",
1301 "count",
1302 "off"
drh2ce15c32017-07-11 13:34:40 +00001303};
1304
1305/*
1306** These are the column/row/line separators used by the various
1307** import/export modes.
1308*/
1309#define SEP_Column "|"
1310#define SEP_Row "\n"
1311#define SEP_Tab "\t"
1312#define SEP_Space " "
1313#define SEP_Comma ","
1314#define SEP_CrLf "\r\n"
1315#define SEP_Unit "\x1F"
1316#define SEP_Record "\x1E"
1317
1318/*
larrybrd48e88e2022-01-24 06:36:16 +00001319** Limit input nesting via .read or any other input redirect.
1320** It's not too expensive, so a generous allowance can be made.
1321*/
1322#define MAX_INPUT_NESTING 25
1323
1324/*
drh2ce15c32017-07-11 13:34:40 +00001325** A callback for the sqlite3_log() interface.
1326*/
1327static void shellLog(void *pArg, int iErrCode, const char *zMsg){
1328 ShellState *p = (ShellState*)pArg;
1329 if( p->pLog==0 ) return;
1330 utf8_printf(p->pLog, "(%d) %s\n", iErrCode, zMsg);
1331 fflush(p->pLog);
1332}
1333
1334/*
drh634c70f2018-01-10 16:50:18 +00001335** SQL function: shell_putsnl(X)
1336**
1337** Write the text X to the screen (or whatever output is being directed)
1338** adding a newline at the end, and then return X.
1339*/
1340static void shellPutsFunc(
1341 sqlite3_context *pCtx,
1342 int nVal,
1343 sqlite3_value **apVal
1344){
1345 ShellState *p = (ShellState*)sqlite3_user_data(pCtx);
drhb9685182018-01-17 13:15:23 +00001346 (void)nVal;
drh634c70f2018-01-10 16:50:18 +00001347 utf8_printf(p->out, "%s\n", sqlite3_value_text(apVal[0]));
1348 sqlite3_result_value(pCtx, apVal[0]);
1349}
1350
1351/*
drhb97e2ad2021-08-26 18:31:39 +00001352** If in safe mode, print an error message described by the arguments
1353** and exit immediately.
1354*/
1355static void failIfSafeMode(
1356 ShellState *p,
1357 const char *zErrMsg,
1358 ...
1359){
1360 if( p->bSafeMode ){
1361 va_list ap;
1362 char *zMsg;
1363 va_start(ap, zErrMsg);
1364 zMsg = sqlite3_vmprintf(zErrMsg, ap);
1365 va_end(ap);
1366 raw_printf(stderr, "line %d: ", p->lineno);
1367 utf8_printf(stderr, "%s\n", zMsg);
1368 exit(1);
1369 }
1370}
1371
1372/*
drh97913132018-01-11 00:04:00 +00001373** SQL function: edit(VALUE)
1374** edit(VALUE,EDITOR)
1375**
1376** These steps:
1377**
1378** (1) Write VALUE into a temporary file.
1379** (2) Run program EDITOR on that temporary file.
1380** (3) Read the temporary file back and return its content as the result.
1381** (4) Delete the temporary file
1382**
1383** If the EDITOR argument is omitted, use the value in the VISUAL
1384** environment variable. If still there is no EDITOR, through an error.
1385**
1386** Also throw an error if the EDITOR program returns a non-zero exit code.
1387*/
drh04a28c32018-01-31 01:38:44 +00001388#ifndef SQLITE_NOHAVE_SYSTEM
drh97913132018-01-11 00:04:00 +00001389static void editFunc(
1390 sqlite3_context *context,
1391 int argc,
1392 sqlite3_value **argv
1393){
1394 const char *zEditor;
1395 char *zTempFile = 0;
1396 sqlite3 *db;
1397 char *zCmd = 0;
1398 int bBin;
1399 int rc;
drhf018fd52018-08-06 02:08:53 +00001400 int hasCRNL = 0;
drh97913132018-01-11 00:04:00 +00001401 FILE *f = 0;
1402 sqlite3_int64 sz;
1403 sqlite3_int64 x;
1404 unsigned char *p = 0;
1405
1406 if( argc==2 ){
1407 zEditor = (const char*)sqlite3_value_text(argv[1]);
1408 }else{
1409 zEditor = getenv("VISUAL");
1410 }
1411 if( zEditor==0 ){
1412 sqlite3_result_error(context, "no editor for edit()", -1);
1413 return;
1414 }
1415 if( sqlite3_value_type(argv[0])==SQLITE_NULL ){
1416 sqlite3_result_error(context, "NULL input to edit()", -1);
1417 return;
1418 }
1419 db = sqlite3_context_db_handle(context);
1420 zTempFile = 0;
1421 sqlite3_file_control(db, 0, SQLITE_FCNTL_TEMPFILENAME, &zTempFile);
1422 if( zTempFile==0 ){
1423 sqlite3_uint64 r = 0;
1424 sqlite3_randomness(sizeof(r), &r);
1425 zTempFile = sqlite3_mprintf("temp%llx", r);
1426 if( zTempFile==0 ){
1427 sqlite3_result_error_nomem(context);
1428 return;
1429 }
1430 }
1431 bBin = sqlite3_value_type(argv[0])==SQLITE_BLOB;
drhf018fd52018-08-06 02:08:53 +00001432 /* When writing the file to be edited, do \n to \r\n conversions on systems
1433 ** that want \r\n line endings */
drh97913132018-01-11 00:04:00 +00001434 f = fopen(zTempFile, bBin ? "wb" : "w");
1435 if( f==0 ){
1436 sqlite3_result_error(context, "edit() cannot open temp file", -1);
1437 goto edit_func_end;
1438 }
1439 sz = sqlite3_value_bytes(argv[0]);
1440 if( bBin ){
dan4d02b5f2019-07-17 07:23:06 +00001441 x = fwrite(sqlite3_value_blob(argv[0]), 1, (size_t)sz, f);
drh97913132018-01-11 00:04:00 +00001442 }else{
drhf018fd52018-08-06 02:08:53 +00001443 const char *z = (const char*)sqlite3_value_text(argv[0]);
1444 /* Remember whether or not the value originally contained \r\n */
1445 if( z && strstr(z,"\r\n")!=0 ) hasCRNL = 1;
dan4d02b5f2019-07-17 07:23:06 +00001446 x = fwrite(sqlite3_value_text(argv[0]), 1, (size_t)sz, f);
drh97913132018-01-11 00:04:00 +00001447 }
1448 fclose(f);
1449 f = 0;
1450 if( x!=sz ){
1451 sqlite3_result_error(context, "edit() could not write the whole file", -1);
1452 goto edit_func_end;
1453 }
1454 zCmd = sqlite3_mprintf("%s \"%s\"", zEditor, zTempFile);
1455 if( zCmd==0 ){
1456 sqlite3_result_error_nomem(context);
1457 goto edit_func_end;
1458 }
1459 rc = system(zCmd);
1460 sqlite3_free(zCmd);
1461 if( rc ){
1462 sqlite3_result_error(context, "EDITOR returned non-zero", -1);
1463 goto edit_func_end;
1464 }
drhf018fd52018-08-06 02:08:53 +00001465 f = fopen(zTempFile, "rb");
drh97913132018-01-11 00:04:00 +00001466 if( f==0 ){
1467 sqlite3_result_error(context,
1468 "edit() cannot reopen temp file after edit", -1);
1469 goto edit_func_end;
1470 }
1471 fseek(f, 0, SEEK_END);
1472 sz = ftell(f);
1473 rewind(f);
drhee37f8b2019-08-23 23:05:32 +00001474 p = sqlite3_malloc64( sz+1 );
drh97913132018-01-11 00:04:00 +00001475 if( p==0 ){
1476 sqlite3_result_error_nomem(context);
1477 goto edit_func_end;
1478 }
dan4d02b5f2019-07-17 07:23:06 +00001479 x = fread(p, 1, (size_t)sz, f);
drh97913132018-01-11 00:04:00 +00001480 fclose(f);
1481 f = 0;
1482 if( x!=sz ){
1483 sqlite3_result_error(context, "could not read back the whole file", -1);
1484 goto edit_func_end;
1485 }
1486 if( bBin ){
mistachkinb71aa092018-01-23 00:05:18 +00001487 sqlite3_result_blob64(context, p, sz, sqlite3_free);
drh97913132018-01-11 00:04:00 +00001488 }else{
dan60bdcf52018-10-03 11:13:30 +00001489 sqlite3_int64 i, j;
drhf018fd52018-08-06 02:08:53 +00001490 if( hasCRNL ){
1491 /* If the original contains \r\n then do no conversions back to \n */
drhf018fd52018-08-06 02:08:53 +00001492 }else{
1493 /* If the file did not originally contain \r\n then convert any new
1494 ** \r\n back into \n */
1495 for(i=j=0; i<sz; i++){
1496 if( p[i]=='\r' && p[i+1]=='\n' ) i++;
1497 p[j++] = p[i];
1498 }
1499 sz = j;
1500 p[sz] = 0;
1501 }
mistachkinb71aa092018-01-23 00:05:18 +00001502 sqlite3_result_text64(context, (const char*)p, sz,
1503 sqlite3_free, SQLITE_UTF8);
drh97913132018-01-11 00:04:00 +00001504 }
1505 p = 0;
1506
1507edit_func_end:
1508 if( f ) fclose(f);
1509 unlink(zTempFile);
1510 sqlite3_free(zTempFile);
1511 sqlite3_free(p);
1512}
drh04a28c32018-01-31 01:38:44 +00001513#endif /* SQLITE_NOHAVE_SYSTEM */
drh97913132018-01-11 00:04:00 +00001514
1515/*
drh3c484e82018-01-10 22:27:21 +00001516** Save or restore the current output mode
1517*/
1518static void outputModePush(ShellState *p){
1519 p->modePrior = p->mode;
drh7a431002020-04-18 14:12:00 +00001520 p->priorShFlgs = p->shellFlgs;
drh3c484e82018-01-10 22:27:21 +00001521 memcpy(p->colSepPrior, p->colSeparator, sizeof(p->colSeparator));
1522 memcpy(p->rowSepPrior, p->rowSeparator, sizeof(p->rowSeparator));
1523}
1524static void outputModePop(ShellState *p){
1525 p->mode = p->modePrior;
drh7a431002020-04-18 14:12:00 +00001526 p->shellFlgs = p->priorShFlgs;
drh3c484e82018-01-10 22:27:21 +00001527 memcpy(p->colSeparator, p->colSepPrior, sizeof(p->colSeparator));
1528 memcpy(p->rowSeparator, p->rowSepPrior, sizeof(p->rowSeparator));
1529}
1530
1531/*
drh2ce15c32017-07-11 13:34:40 +00001532** Output the given string as a hex-encoded blob (eg. X'1234' )
1533*/
1534static void output_hex_blob(FILE *out, const void *pBlob, int nBlob){
1535 int i;
dan2ce2b772022-08-24 11:51:31 +00001536 unsigned char *aBlob = (unsigned char*)pBlob;
1537
1538 char *zStr = sqlite3_malloc(nBlob*2 + 1);
1539 shell_check_oom(zStr);
1540
1541 for(i=0; i<nBlob; i++){
1542 static const char aHex[] = {
1543 '0', '1', '2', '3', '4', '5', '6', '7',
1544 '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
1545 };
1546 zStr[i*2] = aHex[ (aBlob[i] >> 4) ];
1547 zStr[i*2+1] = aHex[ (aBlob[i] & 0x0F) ];
1548 }
1549 zStr[i*2] = '\0';
1550
1551 raw_printf(out,"X'%s'", zStr);
1552 sqlite3_free(zStr);
drh2ce15c32017-07-11 13:34:40 +00001553}
1554
1555/*
1556** Find a string that is not found anywhere in z[]. Return a pointer
1557** to that string.
1558**
1559** Try to use zA and zB first. If both of those are already found in z[]
1560** then make up some string and store it in the buffer zBuf.
1561*/
1562static const char *unused_string(
1563 const char *z, /* Result must not appear anywhere in z */
1564 const char *zA, const char *zB, /* Try these first */
1565 char *zBuf /* Space to store a generated string */
1566){
1567 unsigned i = 0;
1568 if( strstr(z, zA)==0 ) return zA;
1569 if( strstr(z, zB)==0 ) return zB;
1570 do{
1571 sqlite3_snprintf(20,zBuf,"(%s%u)", zA, i++);
1572 }while( strstr(z,zBuf)!=0 );
1573 return zBuf;
1574}
1575
1576/*
1577** Output the given string as a quoted string using SQL quoting conventions.
1578**
1579** See also: output_quoted_escaped_string()
1580*/
1581static void output_quoted_string(FILE *out, const char *z){
1582 int i;
1583 char c;
1584 setBinaryMode(out, 1);
1585 for(i=0; (c = z[i])!=0 && c!='\''; i++){}
1586 if( c==0 ){
1587 utf8_printf(out,"'%s'",z);
1588 }else{
1589 raw_printf(out, "'");
1590 while( *z ){
1591 for(i=0; (c = z[i])!=0 && c!='\''; i++){}
1592 if( c=='\'' ) i++;
1593 if( i ){
1594 utf8_printf(out, "%.*s", i, z);
1595 z += i;
1596 }
1597 if( c=='\'' ){
1598 raw_printf(out, "'");
1599 continue;
1600 }
1601 if( c==0 ){
1602 break;
1603 }
1604 z++;
1605 }
1606 raw_printf(out, "'");
1607 }
1608 setTextMode(out, 1);
1609}
1610
1611/*
1612** Output the given string as a quoted string using SQL quoting conventions.
1613** Additionallly , escape the "\n" and "\r" characters so that they do not
1614** get corrupted by end-of-line translation facilities in some operating
1615** systems.
1616**
1617** This is like output_quoted_string() but with the addition of the \r\n
1618** escape mechanism.
1619*/
1620static void output_quoted_escaped_string(FILE *out, const char *z){
1621 int i;
1622 char c;
1623 setBinaryMode(out, 1);
1624 for(i=0; (c = z[i])!=0 && c!='\'' && c!='\n' && c!='\r'; i++){}
1625 if( c==0 ){
1626 utf8_printf(out,"'%s'",z);
1627 }else{
1628 const char *zNL = 0;
1629 const char *zCR = 0;
1630 int nNL = 0;
1631 int nCR = 0;
1632 char zBuf1[20], zBuf2[20];
1633 for(i=0; z[i]; i++){
1634 if( z[i]=='\n' ) nNL++;
1635 if( z[i]=='\r' ) nCR++;
1636 }
1637 if( nNL ){
1638 raw_printf(out, "replace(");
1639 zNL = unused_string(z, "\\n", "\\012", zBuf1);
1640 }
1641 if( nCR ){
1642 raw_printf(out, "replace(");
1643 zCR = unused_string(z, "\\r", "\\015", zBuf2);
1644 }
1645 raw_printf(out, "'");
1646 while( *z ){
1647 for(i=0; (c = z[i])!=0 && c!='\n' && c!='\r' && c!='\''; i++){}
1648 if( c=='\'' ) i++;
1649 if( i ){
1650 utf8_printf(out, "%.*s", i, z);
1651 z += i;
1652 }
1653 if( c=='\'' ){
1654 raw_printf(out, "'");
1655 continue;
1656 }
1657 if( c==0 ){
1658 break;
1659 }
1660 z++;
1661 if( c=='\n' ){
1662 raw_printf(out, "%s", zNL);
1663 continue;
1664 }
1665 raw_printf(out, "%s", zCR);
1666 }
1667 raw_printf(out, "'");
1668 if( nCR ){
1669 raw_printf(out, ",'%s',char(13))", zCR);
1670 }
1671 if( nNL ){
1672 raw_printf(out, ",'%s',char(10))", zNL);
1673 }
1674 }
1675 setTextMode(out, 1);
1676}
1677
1678/*
1679** Output the given string as a quoted according to C or TCL quoting rules.
1680*/
1681static void output_c_string(FILE *out, const char *z){
1682 unsigned int c;
1683 fputc('"', out);
1684 while( (c = *(z++))!=0 ){
1685 if( c=='\\' ){
1686 fputc(c, out);
1687 fputc(c, out);
1688 }else if( c=='"' ){
1689 fputc('\\', out);
1690 fputc('"', out);
1691 }else if( c=='\t' ){
1692 fputc('\\', out);
1693 fputc('t', out);
1694 }else if( c=='\n' ){
1695 fputc('\\', out);
1696 fputc('n', out);
1697 }else if( c=='\r' ){
1698 fputc('\\', out);
1699 fputc('r', out);
1700 }else if( !isprint(c&0xff) ){
1701 raw_printf(out, "\\%03o", c&0xff);
1702 }else{
1703 fputc(c, out);
1704 }
1705 }
1706 fputc('"', out);
1707}
1708
1709/*
drh69c093d2020-05-29 00:21:43 +00001710** Output the given string as a quoted according to JSON quoting rules.
1711*/
drh7d23d152022-10-11 12:02:42 +00001712static void output_json_string(FILE *out, const char *z, i64 n){
drh69c093d2020-05-29 00:21:43 +00001713 unsigned int c;
drh7d23d152022-10-11 12:02:42 +00001714 if( n<0 ) n = strlen(z);
drh69c093d2020-05-29 00:21:43 +00001715 fputc('"', out);
1716 while( n-- ){
1717 c = *(z++);
1718 if( c=='\\' || c=='"' ){
1719 fputc('\\', out);
1720 fputc(c, out);
1721 }else if( c<=0x1f ){
1722 fputc('\\', out);
1723 if( c=='\b' ){
1724 fputc('b', out);
1725 }else if( c=='\f' ){
1726 fputc('f', out);
1727 }else if( c=='\n' ){
1728 fputc('n', out);
1729 }else if( c=='\r' ){
1730 fputc('r', out);
1731 }else if( c=='\t' ){
1732 fputc('t', out);
1733 }else{
1734 raw_printf(out, "u%04x",c);
1735 }
1736 }else{
1737 fputc(c, out);
1738 }
1739 }
1740 fputc('"', out);
1741}
1742
1743/*
drh2ce15c32017-07-11 13:34:40 +00001744** Output the given string with characters that are special to
1745** HTML escaped.
1746*/
1747static void output_html_string(FILE *out, const char *z){
1748 int i;
1749 if( z==0 ) z = "";
1750 while( *z ){
1751 for(i=0; z[i]
1752 && z[i]!='<'
1753 && z[i]!='&'
1754 && z[i]!='>'
1755 && z[i]!='\"'
1756 && z[i]!='\'';
1757 i++){}
1758 if( i>0 ){
1759 utf8_printf(out,"%.*s",i,z);
1760 }
1761 if( z[i]=='<' ){
1762 raw_printf(out,"&lt;");
1763 }else if( z[i]=='&' ){
1764 raw_printf(out,"&amp;");
1765 }else if( z[i]=='>' ){
1766 raw_printf(out,"&gt;");
1767 }else if( z[i]=='\"' ){
1768 raw_printf(out,"&quot;");
1769 }else if( z[i]=='\'' ){
1770 raw_printf(out,"&#39;");
1771 }else{
1772 break;
1773 }
1774 z += i + 1;
1775 }
1776}
1777
1778/*
1779** If a field contains any character identified by a 1 in the following
1780** array, then the string must be quoted for CSV.
1781*/
1782static const char needCsvQuote[] = {
1783 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1784 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1785 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
1786 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1787 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1788 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1789 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1790 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
1791 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1792 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1793 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1794 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1795 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1796 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1797 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1798 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1799};
1800
1801/*
1802** Output a single term of CSV. Actually, p->colSeparator is used for
1803** the separator, which may or may not be a comma. p->nullValue is
1804** the null value. Strings are quoted if necessary. The separator
1805** is only issued if bSep is true.
1806*/
1807static void output_csv(ShellState *p, const char *z, int bSep){
1808 FILE *out = p->out;
1809 if( z==0 ){
1810 utf8_printf(out,"%s",p->nullValue);
1811 }else{
drh9cd0c3d2021-11-18 15:40:05 +00001812 unsigned i;
1813 for(i=0; z[i]; i++){
1814 if( needCsvQuote[((unsigned char*)z)[i]] ){
drh2ce15c32017-07-11 13:34:40 +00001815 i = 0;
1816 break;
1817 }
1818 }
drh9cd0c3d2021-11-18 15:40:05 +00001819 if( i==0 || strstr(z, p->colSeparator)!=0 ){
drh9b7affc2017-11-26 02:14:18 +00001820 char *zQuoted = sqlite3_mprintf("\"%w\"", z);
drhe3e25652021-12-16 13:29:28 +00001821 shell_check_oom(zQuoted);
drh9b7affc2017-11-26 02:14:18 +00001822 utf8_printf(out, "%s", zQuoted);
1823 sqlite3_free(zQuoted);
drh2ce15c32017-07-11 13:34:40 +00001824 }else{
1825 utf8_printf(out, "%s", z);
1826 }
1827 }
1828 if( bSep ){
1829 utf8_printf(p->out, "%s", p->colSeparator);
1830 }
1831}
1832
drh2ce15c32017-07-11 13:34:40 +00001833/*
1834** This routine runs when the user presses Ctrl-C
1835*/
1836static void interrupt_handler(int NotUsed){
1837 UNUSED_PARAMETER(NotUsed);
1838 seenInterrupt++;
1839 if( seenInterrupt>2 ) exit(1);
1840 if( globalDb ) sqlite3_interrupt(globalDb);
1841}
mistachkinb4bab902017-10-27 17:09:44 +00001842
1843#if (defined(_WIN32) || defined(WIN32)) && !defined(_WIN32_WCE)
1844/*
1845** This routine runs for console events (e.g. Ctrl-C) on Win32
1846*/
1847static BOOL WINAPI ConsoleCtrlHandler(
1848 DWORD dwCtrlType /* One of the CTRL_*_EVENT constants */
1849){
1850 if( dwCtrlType==CTRL_C_EVENT ){
1851 interrupt_handler(0);
1852 return TRUE;
1853 }
1854 return FALSE;
1855}
drh2ce15c32017-07-11 13:34:40 +00001856#endif
1857
1858#ifndef SQLITE_OMIT_AUTHORIZATION
1859/*
drhb97e2ad2021-08-26 18:31:39 +00001860** This authorizer runs in safe mode.
1861*/
1862static int safeModeAuth(
1863 void *pClientData,
1864 int op,
1865 const char *zA1,
1866 const char *zA2,
1867 const char *zA3,
1868 const char *zA4
1869){
1870 ShellState *p = (ShellState*)pClientData;
1871 static const char *azProhibitedFunctions[] = {
1872 "edit",
1873 "fts3_tokenizer",
1874 "load_extension",
1875 "readfile",
1876 "writefile",
1877 "zipfile",
1878 "zipfile_cds",
1879 };
1880 UNUSED_PARAMETER(zA2);
1881 UNUSED_PARAMETER(zA3);
1882 UNUSED_PARAMETER(zA4);
1883 switch( op ){
1884 case SQLITE_ATTACH: {
stephan4413ec72022-07-12 15:53:02 +00001885#ifndef SQLITE_SHELL_FIDDLE
stephan626aa482022-06-06 04:09:44 +00001886 /* In WASM builds the filesystem is a virtual sandbox, so
1887 ** there's no harm in using ATTACH. */
drhb97e2ad2021-08-26 18:31:39 +00001888 failIfSafeMode(p, "cannot run ATTACH in safe mode");
stephan626aa482022-06-06 04:09:44 +00001889#endif
drhb97e2ad2021-08-26 18:31:39 +00001890 break;
1891 }
1892 case SQLITE_FUNCTION: {
1893 int i;
1894 for(i=0; i<ArraySize(azProhibitedFunctions); i++){
1895 if( sqlite3_stricmp(zA1, azProhibitedFunctions[i])==0 ){
1896 failIfSafeMode(p, "cannot use the %s() function in safe mode",
1897 azProhibitedFunctions[i]);
1898 }
1899 }
1900 break;
1901 }
1902 }
1903 return SQLITE_OK;
1904}
1905
1906/*
drh2ce15c32017-07-11 13:34:40 +00001907** When the ".auth ON" is set, the following authorizer callback is
1908** invoked. It always returns SQLITE_OK.
1909*/
1910static int shellAuth(
1911 void *pClientData,
1912 int op,
1913 const char *zA1,
1914 const char *zA2,
1915 const char *zA3,
1916 const char *zA4
1917){
1918 ShellState *p = (ShellState*)pClientData;
1919 static const char *azAction[] = { 0,
1920 "CREATE_INDEX", "CREATE_TABLE", "CREATE_TEMP_INDEX",
1921 "CREATE_TEMP_TABLE", "CREATE_TEMP_TRIGGER", "CREATE_TEMP_VIEW",
1922 "CREATE_TRIGGER", "CREATE_VIEW", "DELETE",
1923 "DROP_INDEX", "DROP_TABLE", "DROP_TEMP_INDEX",
1924 "DROP_TEMP_TABLE", "DROP_TEMP_TRIGGER", "DROP_TEMP_VIEW",
1925 "DROP_TRIGGER", "DROP_VIEW", "INSERT",
1926 "PRAGMA", "READ", "SELECT",
1927 "TRANSACTION", "UPDATE", "ATTACH",
1928 "DETACH", "ALTER_TABLE", "REINDEX",
1929 "ANALYZE", "CREATE_VTABLE", "DROP_VTABLE",
1930 "FUNCTION", "SAVEPOINT", "RECURSIVE"
1931 };
1932 int i;
1933 const char *az[4];
1934 az[0] = zA1;
1935 az[1] = zA2;
1936 az[2] = zA3;
1937 az[3] = zA4;
1938 utf8_printf(p->out, "authorizer: %s", azAction[op]);
1939 for(i=0; i<4; i++){
1940 raw_printf(p->out, " ");
1941 if( az[i] ){
1942 output_c_string(p->out, az[i]);
1943 }else{
1944 raw_printf(p->out, "NULL");
1945 }
1946 }
1947 raw_printf(p->out, "\n");
drhb97e2ad2021-08-26 18:31:39 +00001948 if( p->bSafeMode ) (void)safeModeAuth(pClientData, op, zA1, zA2, zA3, zA4);
drh2ce15c32017-07-11 13:34:40 +00001949 return SQLITE_OK;
1950}
1951#endif
1952
1953/*
1954** Print a schema statement. Part of MODE_Semi and MODE_Pretty output.
1955**
1956** This routine converts some CREATE TABLE statements for shadow tables
1957** in FTS3/4/5 into CREATE TABLE IF NOT EXISTS statements.
drh78ed74e2022-08-17 20:18:34 +00001958**
1959** If the schema statement in z[] contains a start-of-comment and if
1960** sqlite3_complete() returns false, try to terminate the comment before
1961** printing the result. https://sqlite.org/forum/forumpost/d7be961c5c
drh2ce15c32017-07-11 13:34:40 +00001962*/
1963static void printSchemaLine(FILE *out, const char *z, const char *zTail){
drh78ed74e2022-08-17 20:18:34 +00001964 char *zToFree = 0;
drh0a0536a2019-05-09 18:13:30 +00001965 if( z==0 ) return;
1966 if( zTail==0 ) return;
drh78ed74e2022-08-17 20:18:34 +00001967 if( zTail[0]==';' && (strstr(z, "/*")!=0 || strstr(z,"--")!=0) ){
1968 const char *zOrig = z;
1969 static const char *azTerm[] = { "", "*/", "\n" };
1970 int i;
1971 for(i=0; i<ArraySize(azTerm); i++){
1972 char *zNew = sqlite3_mprintf("%s%s;", zOrig, azTerm[i]);
1973 if( sqlite3_complete(zNew) ){
1974 size_t n = strlen(zNew);
1975 zNew[n-1] = 0;
1976 zToFree = zNew;
1977 z = zNew;
1978 break;
1979 }
1980 sqlite3_free(zNew);
1981 }
1982 }
drh2ce15c32017-07-11 13:34:40 +00001983 if( sqlite3_strglob("CREATE TABLE ['\"]*", z)==0 ){
1984 utf8_printf(out, "CREATE TABLE IF NOT EXISTS %s%s", z+13, zTail);
1985 }else{
1986 utf8_printf(out, "%s%s", z, zTail);
1987 }
drh78ed74e2022-08-17 20:18:34 +00001988 sqlite3_free(zToFree);
drh2ce15c32017-07-11 13:34:40 +00001989}
1990static void printSchemaLineN(FILE *out, char *z, int n, const char *zTail){
1991 char c = z[n];
1992 z[n] = 0;
1993 printSchemaLine(out, z, zTail);
1994 z[n] = c;
1995}
1996
1997/*
drh11be81d2018-01-06 15:46:20 +00001998** Return true if string z[] has nothing but whitespace and comments to the
1999** end of the first line.
2000*/
2001static int wsToEol(const char *z){
2002 int i;
2003 for(i=0; z[i]; i++){
2004 if( z[i]=='\n' ) return 1;
2005 if( IsSpace(z[i]) ) continue;
2006 if( z[i]=='-' && z[i+1]=='-' ) return 1;
2007 return 0;
2008 }
2009 return 1;
2010}
drh4b5345c2018-04-24 13:07:40 +00002011
2012/*
2013** Add a new entry to the EXPLAIN QUERY PLAN data
2014*/
drhe2ca99c2018-05-02 00:33:43 +00002015static void eqp_append(ShellState *p, int iEqpId, int p2, const char *zText){
drh4b5345c2018-04-24 13:07:40 +00002016 EQPGraphRow *pNew;
drh8be89242022-10-17 16:09:33 +00002017 i64 nText;
2018 if( zText==0 ) return;
2019 nText = strlen(zText);
drhe2ca99c2018-05-02 00:33:43 +00002020 if( p->autoEQPtest ){
2021 utf8_printf(p->out, "%d,%d,%s\n", iEqpId, p2, zText);
2022 }
drh4b5345c2018-04-24 13:07:40 +00002023 pNew = sqlite3_malloc64( sizeof(*pNew) + nText );
drhe3e25652021-12-16 13:29:28 +00002024 shell_check_oom(pNew);
drhe2ca99c2018-05-02 00:33:43 +00002025 pNew->iEqpId = iEqpId;
2026 pNew->iParentId = p2;
drh4b5345c2018-04-24 13:07:40 +00002027 memcpy(pNew->zText, zText, nText+1);
2028 pNew->pNext = 0;
2029 if( p->sGraph.pLast ){
2030 p->sGraph.pLast->pNext = pNew;
2031 }else{
2032 p->sGraph.pRow = pNew;
2033 }
2034 p->sGraph.pLast = pNew;
2035}
2036
2037/*
2038** Free and reset the EXPLAIN QUERY PLAN data that has been collected
2039** in p->sGraph.
2040*/
2041static void eqp_reset(ShellState *p){
2042 EQPGraphRow *pRow, *pNext;
2043 for(pRow = p->sGraph.pRow; pRow; pRow = pNext){
2044 pNext = pRow->pNext;
2045 sqlite3_free(pRow);
2046 }
2047 memset(&p->sGraph, 0, sizeof(p->sGraph));
2048}
2049
drhe2ca99c2018-05-02 00:33:43 +00002050/* Return the next EXPLAIN QUERY PLAN line with iEqpId that occurs after
drh4b5345c2018-04-24 13:07:40 +00002051** pOld, or return the first such line if pOld is NULL
2052*/
drhe2ca99c2018-05-02 00:33:43 +00002053static EQPGraphRow *eqp_next_row(ShellState *p, int iEqpId, EQPGraphRow *pOld){
drh4b5345c2018-04-24 13:07:40 +00002054 EQPGraphRow *pRow = pOld ? pOld->pNext : p->sGraph.pRow;
drhe2ca99c2018-05-02 00:33:43 +00002055 while( pRow && pRow->iParentId!=iEqpId ) pRow = pRow->pNext;
drh4b5345c2018-04-24 13:07:40 +00002056 return pRow;
2057}
2058
drhe2ca99c2018-05-02 00:33:43 +00002059/* Render a single level of the graph that has iEqpId as its parent. Called
drh4b5345c2018-04-24 13:07:40 +00002060** recursively to render sublevels.
2061*/
drhe2ca99c2018-05-02 00:33:43 +00002062static void eqp_render_level(ShellState *p, int iEqpId){
drh4b5345c2018-04-24 13:07:40 +00002063 EQPGraphRow *pRow, *pNext;
drh7d23d152022-10-11 12:02:42 +00002064 i64 n = strlen(p->sGraph.zPrefix);
drh4b5345c2018-04-24 13:07:40 +00002065 char *z;
drhe2ca99c2018-05-02 00:33:43 +00002066 for(pRow = eqp_next_row(p, iEqpId, 0); pRow; pRow = pNext){
2067 pNext = eqp_next_row(p, iEqpId, pRow);
drh4b5345c2018-04-24 13:07:40 +00002068 z = pRow->zText;
drhe2754c12019-08-26 12:50:01 +00002069 utf8_printf(p->out, "%s%s%s\n", p->sGraph.zPrefix,
2070 pNext ? "|--" : "`--", z);
drh7d23d152022-10-11 12:02:42 +00002071 if( n<(i64)sizeof(p->sGraph.zPrefix)-7 ){
drh4b5345c2018-04-24 13:07:40 +00002072 memcpy(&p->sGraph.zPrefix[n], pNext ? "| " : " ", 4);
drhe2ca99c2018-05-02 00:33:43 +00002073 eqp_render_level(p, pRow->iEqpId);
drh4b5345c2018-04-24 13:07:40 +00002074 p->sGraph.zPrefix[n] = 0;
2075 }
2076 }
2077}
2078
2079/*
2080** Display and reset the EXPLAIN QUERY PLAN data
2081*/
2082static void eqp_render(ShellState *p){
2083 EQPGraphRow *pRow = p->sGraph.pRow;
2084 if( pRow ){
2085 if( pRow->zText[0]=='-' ){
2086 if( pRow->pNext==0 ){
2087 eqp_reset(p);
2088 return;
2089 }
2090 utf8_printf(p->out, "%s\n", pRow->zText+3);
2091 p->sGraph.pRow = pRow->pNext;
2092 sqlite3_free(pRow);
2093 }else{
2094 utf8_printf(p->out, "QUERY PLAN\n");
2095 }
2096 p->sGraph.zPrefix[0] = 0;
2097 eqp_render_level(p, 0);
2098 eqp_reset(p);
2099 }
2100}
drh11be81d2018-01-06 15:46:20 +00002101
drh569b1d92019-02-05 20:51:41 +00002102#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
drh11be81d2018-01-06 15:46:20 +00002103/*
drh3f83f592019-02-04 14:53:18 +00002104** Progress handler callback.
2105*/
2106static int progress_handler(void *pClientData) {
2107 ShellState *p = (ShellState*)pClientData;
2108 p->nProgress++;
2109 if( p->nProgress>=p->mxProgress && p->mxProgress>0 ){
2110 raw_printf(p->out, "Progress limit reached (%u)\n", p->nProgress);
drhfc4eeef2019-02-05 19:48:46 +00002111 if( p->flgProgress & SHELL_PROGRESS_RESET ) p->nProgress = 0;
2112 if( p->flgProgress & SHELL_PROGRESS_ONCE ) p->mxProgress = 0;
drh3f83f592019-02-04 14:53:18 +00002113 return 1;
2114 }
drhfc4eeef2019-02-05 19:48:46 +00002115 if( (p->flgProgress & SHELL_PROGRESS_QUIET)==0 ){
drh3f83f592019-02-04 14:53:18 +00002116 raw_printf(p->out, "Progress %u\n", p->nProgress);
2117 }
2118 return 0;
2119}
drh569b1d92019-02-05 20:51:41 +00002120#endif /* SQLITE_OMIT_PROGRESS_CALLBACK */
drh3f83f592019-02-04 14:53:18 +00002121
2122/*
drh30c54a02020-05-28 23:49:50 +00002123** Print N dashes
2124*/
2125static void print_dashes(FILE *out, int N){
2126 const char zDash[] = "--------------------------------------------------";
2127 const int nDash = sizeof(zDash) - 1;
2128 while( N>nDash ){
2129 fputs(zDash, out);
2130 N -= nDash;
2131 }
2132 raw_printf(out, "%.*s", N, zDash);
2133}
2134
2135/*
drh0908e382020-06-04 18:05:39 +00002136** Print a markdown or table-style row separator using ascii-art
drh30c54a02020-05-28 23:49:50 +00002137*/
2138static void print_row_separator(
2139 ShellState *p,
2140 int nArg,
2141 const char *zSep
2142){
2143 int i;
drh0908e382020-06-04 18:05:39 +00002144 if( nArg>0 ){
drh30c54a02020-05-28 23:49:50 +00002145 fputs(zSep, p->out);
drh0908e382020-06-04 18:05:39 +00002146 print_dashes(p->out, p->actualWidth[0]+2);
2147 for(i=1; i<nArg; i++){
2148 fputs(zSep, p->out);
2149 print_dashes(p->out, p->actualWidth[i]+2);
2150 }
2151 fputs(zSep, p->out);
drh30c54a02020-05-28 23:49:50 +00002152 }
drh30c54a02020-05-28 23:49:50 +00002153 fputs("\n", p->out);
2154}
2155
2156/*
drh2ce15c32017-07-11 13:34:40 +00002157** This is the callback routine that the shell
2158** invokes for each row of a query result.
2159*/
2160static int shell_callback(
2161 void *pArg,
2162 int nArg, /* Number of result columns */
2163 char **azArg, /* Text of each result column */
2164 char **azCol, /* Column names */
drhd6f25242020-05-29 12:31:53 +00002165 int *aiType /* Column types. Might be NULL */
drh2ce15c32017-07-11 13:34:40 +00002166){
2167 int i;
2168 ShellState *p = (ShellState*)pArg;
2169
drhb3c45232017-08-28 14:33:27 +00002170 if( azArg==0 ) return 0;
drh2ce15c32017-07-11 13:34:40 +00002171 switch( p->cMode ){
drh5d88be82021-12-09 16:17:43 +00002172 case MODE_Count:
2173 case MODE_Off: {
2174 break;
2175 }
drh2ce15c32017-07-11 13:34:40 +00002176 case MODE_Line: {
2177 int w = 5;
2178 if( azArg==0 ) break;
2179 for(i=0; i<nArg; i++){
2180 int len = strlen30(azCol[i] ? azCol[i] : "");
2181 if( len>w ) w = len;
2182 }
2183 if( p->cnt++>0 ) utf8_printf(p->out, "%s", p->rowSeparator);
2184 for(i=0; i<nArg; i++){
2185 utf8_printf(p->out,"%*s = %s%s", w, azCol[i],
2186 azArg[i] ? azArg[i] : p->nullValue, p->rowSeparator);
2187 }
2188 break;
2189 }
drh8c748632020-05-29 16:15:58 +00002190 case MODE_Explain: {
2191 static const int aExplainWidth[] = {4, 13, 4, 4, 4, 13, 2, 13};
2192 if( nArg>ArraySize(aExplainWidth) ){
2193 nArg = ArraySize(aExplainWidth);
drh2ce15c32017-07-11 13:34:40 +00002194 }
2195 if( p->cnt++==0 ){
2196 for(i=0; i<nArg; i++){
drh8c748632020-05-29 16:15:58 +00002197 int w = aExplainWidth[i];
2198 utf8_width_print(p->out, w, azCol[i]);
2199 fputs(i==nArg-1 ? "\n" : " ", p->out);
drh2ce15c32017-07-11 13:34:40 +00002200 }
drhe566ceb2020-05-30 15:34:49 +00002201 for(i=0; i<nArg; i++){
2202 int w = aExplainWidth[i];
2203 print_dashes(p->out, w);
2204 fputs(i==nArg-1 ? "\n" : " ", p->out);
2205 }
drh2ce15c32017-07-11 13:34:40 +00002206 }
2207 if( azArg==0 ) break;
2208 for(i=0; i<nArg; i++){
drh8c748632020-05-29 16:15:58 +00002209 int w = aExplainWidth[i];
drhaa556b02021-01-13 12:59:20 +00002210 if( i==nArg-1 ) w = 0;
drh8c748632020-05-29 16:15:58 +00002211 if( azArg[i] && strlenChar(azArg[i])>w ){
2212 w = strlenChar(azArg[i]);
drh2ce15c32017-07-11 13:34:40 +00002213 }
drh8c748632020-05-29 16:15:58 +00002214 if( i==1 && p->aiIndent && p->pStmt ){
2215 if( p->iIndent<p->nIndent ){
2216 utf8_printf(p->out, "%*.s", p->aiIndent[p->iIndent], "");
drh2ce15c32017-07-11 13:34:40 +00002217 }
drh8c748632020-05-29 16:15:58 +00002218 p->iIndent++;
drh2ce15c32017-07-11 13:34:40 +00002219 }
2220 utf8_width_print(p->out, w, azArg[i] ? azArg[i] : p->nullValue);
drh8c748632020-05-29 16:15:58 +00002221 fputs(i==nArg-1 ? "\n" : " ", p->out);
drh2ce15c32017-07-11 13:34:40 +00002222 }
2223 break;
2224 }
2225 case MODE_Semi: { /* .schema and .fullschema output */
2226 printSchemaLine(p->out, azArg[0], ";\n");
2227 break;
2228 }
2229 case MODE_Pretty: { /* .schema and .fullschema with --indent */
2230 char *z;
2231 int j;
2232 int nParen = 0;
2233 char cEnd = 0;
2234 char c;
2235 int nLine = 0;
2236 assert( nArg==1 );
2237 if( azArg[0]==0 ) break;
2238 if( sqlite3_strlike("CREATE VIEW%", azArg[0], 0)==0
2239 || sqlite3_strlike("CREATE TRIG%", azArg[0], 0)==0
2240 ){
2241 utf8_printf(p->out, "%s;\n", azArg[0]);
2242 break;
2243 }
2244 z = sqlite3_mprintf("%s", azArg[0]);
drhe3e25652021-12-16 13:29:28 +00002245 shell_check_oom(z);
drh2ce15c32017-07-11 13:34:40 +00002246 j = 0;
2247 for(i=0; IsSpace(z[i]); i++){}
2248 for(; (c = z[i])!=0; i++){
2249 if( IsSpace(c) ){
drhc3cbd672017-10-05 19:12:10 +00002250 if( z[j-1]=='\r' ) z[j-1] = '\n';
drh2ce15c32017-07-11 13:34:40 +00002251 if( IsSpace(z[j-1]) || z[j-1]=='(' ) continue;
2252 }else if( (c=='(' || c==')') && j>0 && IsSpace(z[j-1]) ){
2253 j--;
2254 }
2255 z[j++] = c;
2256 }
2257 while( j>0 && IsSpace(z[j-1]) ){ j--; }
2258 z[j] = 0;
2259 if( strlen30(z)>=79 ){
drhe2754c12019-08-26 12:50:01 +00002260 for(i=j=0; (c = z[i])!=0; i++){ /* Copy from z[i] back to z[j] */
drh2ce15c32017-07-11 13:34:40 +00002261 if( c==cEnd ){
2262 cEnd = 0;
2263 }else if( c=='"' || c=='\'' || c=='`' ){
2264 cEnd = c;
2265 }else if( c=='[' ){
2266 cEnd = ']';
drh11be81d2018-01-06 15:46:20 +00002267 }else if( c=='-' && z[i+1]=='-' ){
2268 cEnd = '\n';
drh2ce15c32017-07-11 13:34:40 +00002269 }else if( c=='(' ){
2270 nParen++;
2271 }else if( c==')' ){
2272 nParen--;
2273 if( nLine>0 && nParen==0 && j>0 ){
2274 printSchemaLineN(p->out, z, j, "\n");
2275 j = 0;
2276 }
2277 }
2278 z[j++] = c;
drh11be81d2018-01-06 15:46:20 +00002279 if( nParen==1 && cEnd==0
2280 && (c=='(' || c=='\n' || (c==',' && !wsToEol(z+i+1)))
2281 ){
drh2ce15c32017-07-11 13:34:40 +00002282 if( c=='\n' ) j--;
2283 printSchemaLineN(p->out, z, j, "\n ");
2284 j = 0;
2285 nLine++;
2286 while( IsSpace(z[i+1]) ){ i++; }
2287 }
2288 }
2289 z[j] = 0;
2290 }
2291 printSchemaLine(p->out, z, ";\n");
2292 sqlite3_free(z);
2293 break;
2294 }
2295 case MODE_List: {
2296 if( p->cnt++==0 && p->showHeader ){
2297 for(i=0; i<nArg; i++){
2298 utf8_printf(p->out,"%s%s",azCol[i],
2299 i==nArg-1 ? p->rowSeparator : p->colSeparator);
2300 }
2301 }
2302 if( azArg==0 ) break;
2303 for(i=0; i<nArg; i++){
2304 char *z = azArg[i];
2305 if( z==0 ) z = p->nullValue;
2306 utf8_printf(p->out, "%s", z);
2307 if( i<nArg-1 ){
2308 utf8_printf(p->out, "%s", p->colSeparator);
2309 }else{
2310 utf8_printf(p->out, "%s", p->rowSeparator);
2311 }
2312 }
2313 break;
2314 }
2315 case MODE_Html: {
2316 if( p->cnt++==0 && p->showHeader ){
2317 raw_printf(p->out,"<TR>");
2318 for(i=0; i<nArg; i++){
2319 raw_printf(p->out,"<TH>");
2320 output_html_string(p->out, azCol[i]);
2321 raw_printf(p->out,"</TH>\n");
2322 }
2323 raw_printf(p->out,"</TR>\n");
2324 }
2325 if( azArg==0 ) break;
2326 raw_printf(p->out,"<TR>");
2327 for(i=0; i<nArg; i++){
2328 raw_printf(p->out,"<TD>");
2329 output_html_string(p->out, azArg[i] ? azArg[i] : p->nullValue);
2330 raw_printf(p->out,"</TD>\n");
2331 }
2332 raw_printf(p->out,"</TR>\n");
2333 break;
2334 }
2335 case MODE_Tcl: {
2336 if( p->cnt++==0 && p->showHeader ){
2337 for(i=0; i<nArg; i++){
2338 output_c_string(p->out,azCol[i] ? azCol[i] : "");
2339 if(i<nArg-1) utf8_printf(p->out, "%s", p->colSeparator);
2340 }
2341 utf8_printf(p->out, "%s", p->rowSeparator);
2342 }
2343 if( azArg==0 ) break;
2344 for(i=0; i<nArg; i++){
2345 output_c_string(p->out, azArg[i] ? azArg[i] : p->nullValue);
2346 if(i<nArg-1) utf8_printf(p->out, "%s", p->colSeparator);
2347 }
2348 utf8_printf(p->out, "%s", p->rowSeparator);
2349 break;
2350 }
2351 case MODE_Csv: {
2352 setBinaryMode(p->out, 1);
2353 if( p->cnt++==0 && p->showHeader ){
2354 for(i=0; i<nArg; i++){
2355 output_csv(p, azCol[i] ? azCol[i] : "", i<nArg-1);
2356 }
2357 utf8_printf(p->out, "%s", p->rowSeparator);
2358 }
2359 if( nArg>0 ){
2360 for(i=0; i<nArg; i++){
2361 output_csv(p, azArg[i], i<nArg-1);
2362 }
2363 utf8_printf(p->out, "%s", p->rowSeparator);
2364 }
2365 setTextMode(p->out, 1);
2366 break;
2367 }
2368 case MODE_Insert: {
2369 if( azArg==0 ) break;
2370 utf8_printf(p->out,"INSERT INTO %s",p->zDestTable);
2371 if( p->showHeader ){
2372 raw_printf(p->out,"(");
2373 for(i=0; i<nArg; i++){
2374 if( i>0 ) raw_printf(p->out, ",");
2375 if( quoteChar(azCol[i]) ){
2376 char *z = sqlite3_mprintf("\"%w\"", azCol[i]);
drhe3e25652021-12-16 13:29:28 +00002377 shell_check_oom(z);
drh2ce15c32017-07-11 13:34:40 +00002378 utf8_printf(p->out, "%s", z);
2379 sqlite3_free(z);
2380 }else{
2381 raw_printf(p->out, "%s", azCol[i]);
2382 }
2383 }
2384 raw_printf(p->out,")");
2385 }
2386 p->cnt++;
2387 for(i=0; i<nArg; i++){
2388 raw_printf(p->out, i>0 ? "," : " VALUES(");
2389 if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){
2390 utf8_printf(p->out,"NULL");
2391 }else if( aiType && aiType[i]==SQLITE_TEXT ){
2392 if( ShellHasFlag(p, SHFLG_Newlines) ){
2393 output_quoted_string(p->out, azArg[i]);
2394 }else{
2395 output_quoted_escaped_string(p->out, azArg[i]);
2396 }
2397 }else if( aiType && aiType[i]==SQLITE_INTEGER ){
2398 utf8_printf(p->out,"%s", azArg[i]);
2399 }else if( aiType && aiType[i]==SQLITE_FLOAT ){
2400 char z[50];
2401 double r = sqlite3_column_double(p->pStmt, i);
drh2f1f8802018-06-13 17:19:20 +00002402 sqlite3_uint64 ur;
2403 memcpy(&ur,&r,sizeof(r));
2404 if( ur==0x7ff0000000000000LL ){
2405 raw_printf(p->out, "1e999");
2406 }else if( ur==0xfff0000000000000LL ){
2407 raw_printf(p->out, "-1e999");
2408 }else{
drh537a6bf2022-02-15 13:23:09 +00002409 sqlite3_int64 ir = (sqlite3_int64)r;
2410 if( r==(double)ir ){
2411 sqlite3_snprintf(50,z,"%lld.0", ir);
2412 }else{
2413 sqlite3_snprintf(50,z,"%!.20g", r);
2414 }
drh2f1f8802018-06-13 17:19:20 +00002415 raw_printf(p->out, "%s", z);
2416 }
drh2ce15c32017-07-11 13:34:40 +00002417 }else if( aiType && aiType[i]==SQLITE_BLOB && p->pStmt ){
2418 const void *pBlob = sqlite3_column_blob(p->pStmt, i);
2419 int nBlob = sqlite3_column_bytes(p->pStmt, i);
2420 output_hex_blob(p->out, pBlob, nBlob);
2421 }else if( isNumber(azArg[i], 0) ){
2422 utf8_printf(p->out,"%s", azArg[i]);
2423 }else if( ShellHasFlag(p, SHFLG_Newlines) ){
2424 output_quoted_string(p->out, azArg[i]);
2425 }else{
2426 output_quoted_escaped_string(p->out, azArg[i]);
2427 }
2428 }
2429 raw_printf(p->out,");\n");
2430 break;
2431 }
drh30c54a02020-05-28 23:49:50 +00002432 case MODE_Json: {
2433 if( azArg==0 ) break;
2434 if( p->cnt==0 ){
2435 fputs("[{", p->out);
2436 }else{
2437 fputs(",\n{", p->out);
2438 }
2439 p->cnt++;
2440 for(i=0; i<nArg; i++){
drh69c093d2020-05-29 00:21:43 +00002441 output_json_string(p->out, azCol[i], -1);
drh30c54a02020-05-28 23:49:50 +00002442 putc(':', p->out);
2443 if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){
2444 fputs("null",p->out);
2445 }else if( aiType && aiType[i]==SQLITE_FLOAT ){
2446 char z[50];
2447 double r = sqlite3_column_double(p->pStmt, i);
2448 sqlite3_uint64 ur;
2449 memcpy(&ur,&r,sizeof(r));
2450 if( ur==0x7ff0000000000000LL ){
2451 raw_printf(p->out, "1e999");
2452 }else if( ur==0xfff0000000000000LL ){
2453 raw_printf(p->out, "-1e999");
2454 }else{
2455 sqlite3_snprintf(50,z,"%!.20g", r);
2456 raw_printf(p->out, "%s", z);
2457 }
2458 }else if( aiType && aiType[i]==SQLITE_BLOB && p->pStmt ){
2459 const void *pBlob = sqlite3_column_blob(p->pStmt, i);
2460 int nBlob = sqlite3_column_bytes(p->pStmt, i);
drh69c093d2020-05-29 00:21:43 +00002461 output_json_string(p->out, pBlob, nBlob);
drh30c54a02020-05-28 23:49:50 +00002462 }else if( aiType && aiType[i]==SQLITE_TEXT ){
drh69c093d2020-05-29 00:21:43 +00002463 output_json_string(p->out, azArg[i], -1);
drh30c54a02020-05-28 23:49:50 +00002464 }else{
2465 utf8_printf(p->out,"%s", azArg[i]);
2466 }
2467 if( i<nArg-1 ){
2468 putc(',', p->out);
2469 }
2470 }
2471 putc('}', p->out);
2472 break;
2473 }
drh2ce15c32017-07-11 13:34:40 +00002474 case MODE_Quote: {
2475 if( azArg==0 ) break;
2476 if( p->cnt==0 && p->showHeader ){
2477 for(i=0; i<nArg; i++){
drhc6835732020-05-28 20:37:17 +00002478 if( i>0 ) fputs(p->colSeparator, p->out);
drh2ce15c32017-07-11 13:34:40 +00002479 output_quoted_string(p->out, azCol[i]);
2480 }
drhc6835732020-05-28 20:37:17 +00002481 fputs(p->rowSeparator, p->out);
drh2ce15c32017-07-11 13:34:40 +00002482 }
2483 p->cnt++;
2484 for(i=0; i<nArg; i++){
drhc6835732020-05-28 20:37:17 +00002485 if( i>0 ) fputs(p->colSeparator, p->out);
drh2ce15c32017-07-11 13:34:40 +00002486 if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){
2487 utf8_printf(p->out,"NULL");
2488 }else if( aiType && aiType[i]==SQLITE_TEXT ){
2489 output_quoted_string(p->out, azArg[i]);
2490 }else if( aiType && aiType[i]==SQLITE_INTEGER ){
2491 utf8_printf(p->out,"%s", azArg[i]);
2492 }else if( aiType && aiType[i]==SQLITE_FLOAT ){
2493 char z[50];
2494 double r = sqlite3_column_double(p->pStmt, i);
2495 sqlite3_snprintf(50,z,"%!.20g", r);
2496 raw_printf(p->out, "%s", z);
2497 }else if( aiType && aiType[i]==SQLITE_BLOB && p->pStmt ){
2498 const void *pBlob = sqlite3_column_blob(p->pStmt, i);
2499 int nBlob = sqlite3_column_bytes(p->pStmt, i);
2500 output_hex_blob(p->out, pBlob, nBlob);
2501 }else if( isNumber(azArg[i], 0) ){
2502 utf8_printf(p->out,"%s", azArg[i]);
2503 }else{
2504 output_quoted_string(p->out, azArg[i]);
2505 }
2506 }
drhc6835732020-05-28 20:37:17 +00002507 fputs(p->rowSeparator, p->out);
drh2ce15c32017-07-11 13:34:40 +00002508 break;
2509 }
2510 case MODE_Ascii: {
2511 if( p->cnt++==0 && p->showHeader ){
2512 for(i=0; i<nArg; i++){
2513 if( i>0 ) utf8_printf(p->out, "%s", p->colSeparator);
2514 utf8_printf(p->out,"%s",azCol[i] ? azCol[i] : "");
2515 }
2516 utf8_printf(p->out, "%s", p->rowSeparator);
2517 }
2518 if( azArg==0 ) break;
2519 for(i=0; i<nArg; i++){
2520 if( i>0 ) utf8_printf(p->out, "%s", p->colSeparator);
2521 utf8_printf(p->out,"%s",azArg[i] ? azArg[i] : p->nullValue);
2522 }
2523 utf8_printf(p->out, "%s", p->rowSeparator);
2524 break;
2525 }
drh4b5345c2018-04-24 13:07:40 +00002526 case MODE_EQP: {
drhe2ca99c2018-05-02 00:33:43 +00002527 eqp_append(p, atoi(azArg[0]), atoi(azArg[1]), azArg[3]);
drh4b5345c2018-04-24 13:07:40 +00002528 break;
2529 }
drh2ce15c32017-07-11 13:34:40 +00002530 }
2531 return 0;
2532}
2533
2534/*
2535** This is the callback routine that the SQLite library
2536** invokes for each row of a query result.
2537*/
2538static int callback(void *pArg, int nArg, char **azArg, char **azCol){
2539 /* since we don't have type info, call the shell_callback with a NULL value */
2540 return shell_callback(pArg, nArg, azArg, azCol, NULL);
2541}
2542
2543/*
2544** This is the callback routine from sqlite3_exec() that appends all
2545** output onto the end of a ShellText object.
2546*/
2547static int captureOutputCallback(void *pArg, int nArg, char **azArg, char **az){
2548 ShellText *p = (ShellText*)pArg;
2549 int i;
2550 UNUSED_PARAMETER(az);
drhb3c45232017-08-28 14:33:27 +00002551 if( azArg==0 ) return 0;
drh2ce15c32017-07-11 13:34:40 +00002552 if( p->n ) appendText(p, "|", 0);
2553 for(i=0; i<nArg; i++){
2554 if( i ) appendText(p, ",", 0);
2555 if( azArg[i] ) appendText(p, azArg[i], 0);
2556 }
2557 return 0;
2558}
2559
2560/*
2561** Generate an appropriate SELFTEST table in the main database.
2562*/
2563static void createSelftestTable(ShellState *p){
2564 char *zErrMsg = 0;
2565 sqlite3_exec(p->db,
2566 "SAVEPOINT selftest_init;\n"
2567 "CREATE TABLE IF NOT EXISTS selftest(\n"
2568 " tno INTEGER PRIMARY KEY,\n" /* Test number */
2569 " op TEXT,\n" /* Operator: memo run */
2570 " cmd TEXT,\n" /* Command text */
2571 " ans TEXT\n" /* Desired answer */
2572 ");"
2573 "CREATE TEMP TABLE [_shell$self](op,cmd,ans);\n"
2574 "INSERT INTO [_shell$self](rowid,op,cmd)\n"
2575 " VALUES(coalesce((SELECT (max(tno)+100)/10 FROM selftest),10),\n"
2576 " 'memo','Tests generated by --init');\n"
2577 "INSERT INTO [_shell$self]\n"
2578 " SELECT 'run',\n"
2579 " 'SELECT hex(sha3_query(''SELECT type,name,tbl_name,sql "
drh067b92b2020-06-19 15:24:12 +00002580 "FROM sqlite_schema ORDER BY 2'',224))',\n"
drh2ce15c32017-07-11 13:34:40 +00002581 " hex(sha3_query('SELECT type,name,tbl_name,sql "
drh067b92b2020-06-19 15:24:12 +00002582 "FROM sqlite_schema ORDER BY 2',224));\n"
drh2ce15c32017-07-11 13:34:40 +00002583 "INSERT INTO [_shell$self]\n"
2584 " SELECT 'run',"
2585 " 'SELECT hex(sha3_query(''SELECT * FROM \"' ||"
2586 " printf('%w',name) || '\" NOT INDEXED'',224))',\n"
2587 " hex(sha3_query(printf('SELECT * FROM \"%w\" NOT INDEXED',name),224))\n"
2588 " FROM (\n"
drh067b92b2020-06-19 15:24:12 +00002589 " SELECT name FROM sqlite_schema\n"
drh2ce15c32017-07-11 13:34:40 +00002590 " WHERE type='table'\n"
2591 " AND name<>'selftest'\n"
2592 " AND coalesce(rootpage,0)>0\n"
2593 " )\n"
2594 " ORDER BY name;\n"
2595 "INSERT INTO [_shell$self]\n"
2596 " VALUES('run','PRAGMA integrity_check','ok');\n"
2597 "INSERT INTO selftest(tno,op,cmd,ans)"
2598 " SELECT rowid*10,op,cmd,ans FROM [_shell$self];\n"
2599 "DROP TABLE [_shell$self];"
2600 ,0,0,&zErrMsg);
2601 if( zErrMsg ){
2602 utf8_printf(stderr, "SELFTEST initialization failure: %s\n", zErrMsg);
2603 sqlite3_free(zErrMsg);
2604 }
2605 sqlite3_exec(p->db, "RELEASE selftest_init",0,0,0);
2606}
2607
2608
2609/*
2610** Set the destination table field of the ShellState structure to
2611** the name of the table given. Escape any quote characters in the
2612** table name.
2613*/
2614static void set_table_name(ShellState *p, const char *zName){
2615 int i, n;
mistachkin2158a0c2017-09-09 00:51:36 +00002616 char cQuote;
drh2ce15c32017-07-11 13:34:40 +00002617 char *z;
2618
2619 if( p->zDestTable ){
2620 free(p->zDestTable);
2621 p->zDestTable = 0;
2622 }
2623 if( zName==0 ) return;
2624 cQuote = quoteChar(zName);
2625 n = strlen30(zName);
2626 if( cQuote ) n += n+2;
2627 z = p->zDestTable = malloc( n+1 );
drhe3e25652021-12-16 13:29:28 +00002628 shell_check_oom(z);
drh2ce15c32017-07-11 13:34:40 +00002629 n = 0;
2630 if( cQuote ) z[n++] = cQuote;
2631 for(i=0; zName[i]; i++){
2632 z[n++] = zName[i];
2633 if( zName[i]==cQuote ) z[n++] = cQuote;
2634 }
2635 if( cQuote ) z[n++] = cQuote;
2636 z[n] = 0;
2637}
2638
drhf62641e2021-12-24 20:22:13 +00002639/*
2640** Maybe construct two lines of text that point out the position of a
2641** syntax error. Return a pointer to the text, in memory obtained from
2642** sqlite3_malloc(). Or, if the most recent error does not involve a
2643** specific token that we can point to, return an empty string.
2644**
2645** In all cases, the memory returned is obtained from sqlite3_malloc64()
2646** and should be released by the caller invoking sqlite3_free().
2647*/
2648static char *shell_error_context(const char *zSql, sqlite3 *db){
2649 int iOffset;
2650 size_t len;
2651 char *zCode;
2652 char *zMsg;
2653 int i;
2654 if( db==0
2655 || zSql==0
2656 || (iOffset = sqlite3_error_offset(db))<0
2657 ){
2658 return sqlite3_mprintf("");
2659 }
2660 while( iOffset>50 ){
2661 iOffset--;
2662 zSql++;
2663 while( (zSql[0]&0xc0)==0x80 ){ zSql++; iOffset--; }
2664 }
2665 len = strlen(zSql);
2666 if( len>78 ){
2667 len = 78;
2668 while( (zSql[len]&0xc0)==0x80 ) len--;
2669 }
2670 zCode = sqlite3_mprintf("%.*s", len, zSql);
drh1e84e1e2022-10-31 01:22:38 +00002671 shell_check_oom(zCode);
drhf62641e2021-12-24 20:22:13 +00002672 for(i=0; zCode[i]; i++){ if( IsSpace(zSql[i]) ) zCode[i] = ' '; }
2673 if( iOffset<25 ){
2674 zMsg = sqlite3_mprintf("\n %z\n %*s^--- error here", zCode, iOffset, "");
2675 }else{
2676 zMsg = sqlite3_mprintf("\n %z\n %*serror here ---^", zCode, iOffset-14, "");
2677 }
2678 return zMsg;
2679}
2680
drh2ce15c32017-07-11 13:34:40 +00002681
2682/*
2683** Execute a query statement that will generate SQL output. Print
2684** the result columns, comma-separated, on a line and then add a
2685** semicolon terminator to the end of that line.
2686**
2687** If the number of columns is 1 and that column contains text "--"
2688** then write the semicolon on a separate line. That way, if a
2689** "--" comment occurs at the end of the statement, the comment
2690** won't consume the semicolon terminator.
2691*/
2692static int run_table_dump_query(
2693 ShellState *p, /* Query context */
drh8e9297f2020-03-25 12:50:13 +00002694 const char *zSelect /* SELECT statement to extract content */
drh2ce15c32017-07-11 13:34:40 +00002695){
2696 sqlite3_stmt *pSelect;
2697 int rc;
2698 int nResult;
2699 int i;
2700 const char *z;
2701 rc = sqlite3_prepare_v2(p->db, zSelect, -1, &pSelect, 0);
2702 if( rc!=SQLITE_OK || !pSelect ){
drhf62641e2021-12-24 20:22:13 +00002703 char *zContext = shell_error_context(zSelect, p->db);
2704 utf8_printf(p->out, "/**** ERROR: (%d) %s *****/\n%s", rc,
2705 sqlite3_errmsg(p->db), zContext);
2706 sqlite3_free(zContext);
drh2ce15c32017-07-11 13:34:40 +00002707 if( (rc&0xff)!=SQLITE_CORRUPT ) p->nErr++;
2708 return rc;
2709 }
2710 rc = sqlite3_step(pSelect);
2711 nResult = sqlite3_column_count(pSelect);
2712 while( rc==SQLITE_ROW ){
drh2ce15c32017-07-11 13:34:40 +00002713 z = (const char*)sqlite3_column_text(pSelect, 0);
2714 utf8_printf(p->out, "%s", z);
2715 for(i=1; i<nResult; i++){
2716 utf8_printf(p->out, ",%s", sqlite3_column_text(pSelect, i));
2717 }
2718 if( z==0 ) z = "";
2719 while( z[0] && (z[0]!='-' || z[1]!='-') ) z++;
2720 if( z[0] ){
2721 raw_printf(p->out, "\n;\n");
2722 }else{
2723 raw_printf(p->out, ";\n");
2724 }
2725 rc = sqlite3_step(pSelect);
2726 }
2727 rc = sqlite3_finalize(pSelect);
2728 if( rc!=SQLITE_OK ){
2729 utf8_printf(p->out, "/**** ERROR: (%d) %s *****/\n", rc,
2730 sqlite3_errmsg(p->db));
2731 if( (rc&0xff)!=SQLITE_CORRUPT ) p->nErr++;
2732 }
2733 return rc;
2734}
2735
2736/*
larrybrf9a49b02021-10-26 16:57:09 +00002737** Allocate space and save off string indicating current error.
drh2ce15c32017-07-11 13:34:40 +00002738*/
2739static char *save_err_msg(
larrybrf9a49b02021-10-26 16:57:09 +00002740 sqlite3 *db, /* Database to query */
drh633c7982022-02-08 12:13:16 +00002741 const char *zPhase, /* When the error occcurs */
drhf62641e2021-12-24 20:22:13 +00002742 int rc, /* Error code returned from API */
2743 const char *zSql /* SQL string, or NULL */
drh2ce15c32017-07-11 13:34:40 +00002744){
drhe3e25652021-12-16 13:29:28 +00002745 char *zErr;
drhf62641e2021-12-24 20:22:13 +00002746 char *zContext;
drh633c7982022-02-08 12:13:16 +00002747 sqlite3_str *pStr = sqlite3_str_new(0);
2748 sqlite3_str_appendf(pStr, "%s, %s", zPhase, sqlite3_errmsg(db));
2749 if( rc>1 ){
2750 sqlite3_str_appendf(pStr, " (%d)", rc);
2751 }
drhf62641e2021-12-24 20:22:13 +00002752 zContext = shell_error_context(zSql, db);
drh633c7982022-02-08 12:13:16 +00002753 if( zContext ){
2754 sqlite3_str_appendall(pStr, zContext);
2755 sqlite3_free(zContext);
2756 }
2757 zErr = sqlite3_str_finish(pStr);
drhe3e25652021-12-16 13:29:28 +00002758 shell_check_oom(zErr);
2759 return zErr;
drh2ce15c32017-07-11 13:34:40 +00002760}
2761
2762#ifdef __linux__
2763/*
2764** Attempt to display I/O stats on Linux using /proc/PID/io
2765*/
2766static void displayLinuxIoStats(FILE *out){
2767 FILE *in;
2768 char z[200];
2769 sqlite3_snprintf(sizeof(z), z, "/proc/%d/io", getpid());
2770 in = fopen(z, "rb");
2771 if( in==0 ) return;
2772 while( fgets(z, sizeof(z), in)!=0 ){
2773 static const struct {
2774 const char *zPattern;
2775 const char *zDesc;
2776 } aTrans[] = {
2777 { "rchar: ", "Bytes received by read():" },
2778 { "wchar: ", "Bytes sent to write():" },
2779 { "syscr: ", "Read() system calls:" },
2780 { "syscw: ", "Write() system calls:" },
2781 { "read_bytes: ", "Bytes read from storage:" },
2782 { "write_bytes: ", "Bytes written to storage:" },
2783 { "cancelled_write_bytes: ", "Cancelled write bytes:" },
2784 };
2785 int i;
2786 for(i=0; i<ArraySize(aTrans); i++){
drhaf2770f2018-01-05 14:55:43 +00002787 int n = strlen30(aTrans[i].zPattern);
drhbf70f1b2022-10-19 18:04:42 +00002788 if( cli_strncmp(aTrans[i].zPattern, z, n)==0 ){
drh2ce15c32017-07-11 13:34:40 +00002789 utf8_printf(out, "%-36s %s", aTrans[i].zDesc, &z[n]);
2790 break;
2791 }
2792 }
2793 }
2794 fclose(in);
2795}
2796#endif
2797
2798/*
2799** Display a single line of status using 64-bit values.
2800*/
2801static void displayStatLine(
2802 ShellState *p, /* The shell context */
2803 char *zLabel, /* Label for this one line */
2804 char *zFormat, /* Format for the result */
2805 int iStatusCtrl, /* Which status to display */
2806 int bReset /* True to reset the stats */
2807){
2808 sqlite3_int64 iCur = -1;
2809 sqlite3_int64 iHiwtr = -1;
2810 int i, nPercent;
2811 char zLine[200];
2812 sqlite3_status64(iStatusCtrl, &iCur, &iHiwtr, bReset);
2813 for(i=0, nPercent=0; zFormat[i]; i++){
2814 if( zFormat[i]=='%' ) nPercent++;
2815 }
2816 if( nPercent>1 ){
2817 sqlite3_snprintf(sizeof(zLine), zLine, zFormat, iCur, iHiwtr);
2818 }else{
2819 sqlite3_snprintf(sizeof(zLine), zLine, zFormat, iHiwtr);
2820 }
2821 raw_printf(p->out, "%-36s %s\n", zLabel, zLine);
2822}
2823
2824/*
2825** Display memory stats.
2826*/
2827static int display_stats(
2828 sqlite3 *db, /* Database to query */
2829 ShellState *pArg, /* Pointer to ShellState */
2830 int bReset /* True to reset the stats */
2831){
2832 int iCur;
2833 int iHiwtr;
drh393344f2018-03-09 16:37:05 +00002834 FILE *out;
2835 if( pArg==0 || pArg->out==0 ) return 0;
2836 out = pArg->out;
drh2ce15c32017-07-11 13:34:40 +00002837
drha6e6cf22021-01-09 19:10:04 +00002838 if( pArg->pStmt && pArg->statsOn==2 ){
drh393344f2018-03-09 16:37:05 +00002839 int nCol, i, x;
2840 sqlite3_stmt *pStmt = pArg->pStmt;
2841 char z[100];
2842 nCol = sqlite3_column_count(pStmt);
2843 raw_printf(out, "%-36s %d\n", "Number of output columns:", nCol);
2844 for(i=0; i<nCol; i++){
2845 sqlite3_snprintf(sizeof(z),z,"Column %d %nname:", i, &x);
2846 utf8_printf(out, "%-36s %s\n", z, sqlite3_column_name(pStmt,i));
drh929cce82018-03-17 16:26:36 +00002847#ifndef SQLITE_OMIT_DECLTYPE
drh393344f2018-03-09 16:37:05 +00002848 sqlite3_snprintf(30, z+x, "declared type:");
2849 utf8_printf(out, "%-36s %s\n", z, sqlite3_column_decltype(pStmt, i));
drh929cce82018-03-17 16:26:36 +00002850#endif
2851#ifdef SQLITE_ENABLE_COLUMN_METADATA
drh393344f2018-03-09 16:37:05 +00002852 sqlite3_snprintf(30, z+x, "database name:");
2853 utf8_printf(out, "%-36s %s\n", z, sqlite3_column_database_name(pStmt,i));
2854 sqlite3_snprintf(30, z+x, "table name:");
2855 utf8_printf(out, "%-36s %s\n", z, sqlite3_column_table_name(pStmt,i));
2856 sqlite3_snprintf(30, z+x, "origin name:");
2857 utf8_printf(out, "%-36s %s\n", z, sqlite3_column_origin_name(pStmt,i));
drh929cce82018-03-17 16:26:36 +00002858#endif
drh2ce15c32017-07-11 13:34:40 +00002859 }
drh929cce82018-03-17 16:26:36 +00002860 }
drh2ce15c32017-07-11 13:34:40 +00002861
drha6e6cf22021-01-09 19:10:04 +00002862 if( pArg->statsOn==3 ){
2863 if( pArg->pStmt ){
2864 iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_VM_STEP, bReset);
2865 raw_printf(pArg->out, "VM-steps: %d\n", iCur);
2866 }
2867 return 0;
2868 }
2869
drh393344f2018-03-09 16:37:05 +00002870 displayStatLine(pArg, "Memory Used:",
2871 "%lld (max %lld) bytes", SQLITE_STATUS_MEMORY_USED, bReset);
2872 displayStatLine(pArg, "Number of Outstanding Allocations:",
2873 "%lld (max %lld)", SQLITE_STATUS_MALLOC_COUNT, bReset);
2874 if( pArg->shellFlgs & SHFLG_Pagecache ){
2875 displayStatLine(pArg, "Number of Pcache Pages Used:",
2876 "%lld (max %lld) pages", SQLITE_STATUS_PAGECACHE_USED, bReset);
2877 }
2878 displayStatLine(pArg, "Number of Pcache Overflow Bytes:",
2879 "%lld (max %lld) bytes", SQLITE_STATUS_PAGECACHE_OVERFLOW, bReset);
2880 displayStatLine(pArg, "Largest Allocation:",
2881 "%lld bytes", SQLITE_STATUS_MALLOC_SIZE, bReset);
2882 displayStatLine(pArg, "Largest Pcache Allocation:",
2883 "%lld bytes", SQLITE_STATUS_PAGECACHE_SIZE, bReset);
2884#ifdef YYTRACKMAXSTACKDEPTH
2885 displayStatLine(pArg, "Deepest Parser Stack:",
2886 "%lld (max %lld)", SQLITE_STATUS_PARSER_STACK, bReset);
2887#endif
2888
2889 if( db ){
drh2ce15c32017-07-11 13:34:40 +00002890 if( pArg->shellFlgs & SHFLG_Lookaside ){
2891 iHiwtr = iCur = -1;
2892 sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_USED,
2893 &iCur, &iHiwtr, bReset);
2894 raw_printf(pArg->out,
2895 "Lookaside Slots Used: %d (max %d)\n",
2896 iCur, iHiwtr);
2897 sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_HIT,
2898 &iCur, &iHiwtr, bReset);
2899 raw_printf(pArg->out, "Successful lookaside attempts: %d\n",
2900 iHiwtr);
2901 sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE,
2902 &iCur, &iHiwtr, bReset);
2903 raw_printf(pArg->out, "Lookaside failures due to size: %d\n",
2904 iHiwtr);
2905 sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL,
2906 &iCur, &iHiwtr, bReset);
2907 raw_printf(pArg->out, "Lookaside failures due to OOM: %d\n",
2908 iHiwtr);
2909 }
2910 iHiwtr = iCur = -1;
2911 sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_USED, &iCur, &iHiwtr, bReset);
2912 raw_printf(pArg->out, "Pager Heap Usage: %d bytes\n",
2913 iCur);
2914 iHiwtr = iCur = -1;
2915 sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_HIT, &iCur, &iHiwtr, 1);
2916 raw_printf(pArg->out, "Page cache hits: %d\n", iCur);
2917 iHiwtr = iCur = -1;
2918 sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_MISS, &iCur, &iHiwtr, 1);
2919 raw_printf(pArg->out, "Page cache misses: %d\n", iCur);
2920 iHiwtr = iCur = -1;
2921 sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_WRITE, &iCur, &iHiwtr, 1);
2922 raw_printf(pArg->out, "Page cache writes: %d\n", iCur);
2923 iHiwtr = iCur = -1;
drhffc78a42018-03-14 14:53:50 +00002924 sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_SPILL, &iCur, &iHiwtr, 1);
2925 raw_printf(pArg->out, "Page cache spills: %d\n", iCur);
2926 iHiwtr = iCur = -1;
drh2ce15c32017-07-11 13:34:40 +00002927 sqlite3_db_status(db, SQLITE_DBSTATUS_SCHEMA_USED, &iCur, &iHiwtr, bReset);
2928 raw_printf(pArg->out, "Schema Heap Usage: %d bytes\n",
2929 iCur);
2930 iHiwtr = iCur = -1;
2931 sqlite3_db_status(db, SQLITE_DBSTATUS_STMT_USED, &iCur, &iHiwtr, bReset);
2932 raw_printf(pArg->out, "Statement Heap/Lookaside Usage: %d bytes\n",
2933 iCur);
2934 }
2935
drh393344f2018-03-09 16:37:05 +00002936 if( pArg->pStmt ){
drh23d41e62021-12-06 21:45:31 +00002937 int iHit, iMiss;
drh2ce15c32017-07-11 13:34:40 +00002938 iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_FULLSCAN_STEP,
2939 bReset);
2940 raw_printf(pArg->out, "Fullscan Steps: %d\n", iCur);
2941 iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_SORT, bReset);
2942 raw_printf(pArg->out, "Sort Operations: %d\n", iCur);
2943 iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_AUTOINDEX,bReset);
2944 raw_printf(pArg->out, "Autoindex Inserts: %d\n", iCur);
drh23d41e62021-12-06 21:45:31 +00002945 iHit = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_FILTER_HIT, bReset);
2946 iMiss = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_FILTER_MISS, bReset);
2947 if( iHit || iMiss ){
2948 raw_printf(pArg->out, "Bloom filter bypass taken: %d/%d\n",
2949 iHit, iHit+iMiss);
2950 }
drh2ce15c32017-07-11 13:34:40 +00002951 iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_VM_STEP, bReset);
2952 raw_printf(pArg->out, "Virtual Machine Steps: %d\n", iCur);
drhe2754c12019-08-26 12:50:01 +00002953 iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_REPREPARE,bReset);
drh393344f2018-03-09 16:37:05 +00002954 raw_printf(pArg->out, "Reprepare operations: %d\n", iCur);
2955 iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_RUN, bReset);
2956 raw_printf(pArg->out, "Number of times run: %d\n", iCur);
2957 iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_MEMUSED, bReset);
2958 raw_printf(pArg->out, "Memory used by prepared stmt: %d\n", iCur);
drh2ce15c32017-07-11 13:34:40 +00002959 }
2960
2961#ifdef __linux__
2962 displayLinuxIoStats(pArg->out);
2963#endif
2964
2965 /* Do not remove this machine readable comment: extra-stats-output-here */
2966
2967 return 0;
2968}
2969
2970/*
2971** Display scan stats.
2972*/
2973static void display_scanstats(
2974 sqlite3 *db, /* Database to query */
2975 ShellState *pArg /* Pointer to ShellState */
2976){
2977#ifndef SQLITE_ENABLE_STMT_SCANSTATUS
2978 UNUSED_PARAMETER(db);
2979 UNUSED_PARAMETER(pArg);
2980#else
2981 int i, k, n, mx;
2982 raw_printf(pArg->out, "-------- scanstats --------\n");
2983 mx = 0;
2984 for(k=0; k<=mx; k++){
2985 double rEstLoop = 1.0;
2986 for(i=n=0; 1; i++){
2987 sqlite3_stmt *p = pArg->pStmt;
2988 sqlite3_int64 nLoop, nVisit;
2989 double rEst;
2990 int iSid;
2991 const char *zExplain;
2992 if( sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_NLOOP, (void*)&nLoop) ){
2993 break;
2994 }
2995 sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_SELECTID, (void*)&iSid);
2996 if( iSid>mx ) mx = iSid;
2997 if( iSid!=k ) continue;
2998 if( n==0 ){
2999 rEstLoop = (double)nLoop;
3000 if( k>0 ) raw_printf(pArg->out, "-------- subquery %d -------\n", k);
3001 }
3002 n++;
3003 sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_NVISIT, (void*)&nVisit);
3004 sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_EST, (void*)&rEst);
3005 sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_EXPLAIN, (void*)&zExplain);
3006 utf8_printf(pArg->out, "Loop %2d: %s\n", n, zExplain);
3007 rEstLoop *= rEst;
3008 raw_printf(pArg->out,
3009 " nLoop=%-8lld nRow=%-8lld estRow=%-8lld estRow/Loop=%-8g\n",
3010 nLoop, nVisit, (sqlite3_int64)(rEstLoop+0.5), rEst
3011 );
3012 }
3013 }
3014 raw_printf(pArg->out, "---------------------------\n");
3015#endif
3016}
3017
3018/*
3019** Parameter azArray points to a zero-terminated array of strings. zStr
3020** points to a single nul-terminated string. Return non-zero if zStr
3021** is equal, according to strcmp(), to any of the strings in the array.
3022** Otherwise, return zero.
3023*/
3024static int str_in_array(const char *zStr, const char **azArray){
3025 int i;
3026 for(i=0; azArray[i]; i++){
drhbf70f1b2022-10-19 18:04:42 +00003027 if( 0==cli_strcmp(zStr, azArray[i]) ) return 1;
drh2ce15c32017-07-11 13:34:40 +00003028 }
3029 return 0;
3030}
3031
3032/*
3033** If compiled statement pSql appears to be an EXPLAIN statement, allocate
3034** and populate the ShellState.aiIndent[] array with the number of
3035** spaces each opcode should be indented before it is output.
3036**
3037** The indenting rules are:
3038**
3039** * For each "Next", "Prev", "VNext" or "VPrev" instruction, indent
3040** all opcodes that occur between the p2 jump destination and the opcode
3041** itself by 2 spaces.
3042**
drhe603ab02022-04-07 19:06:31 +00003043** * Do the previous for "Return" instructions for when P2 is positive.
3044** See tag-20220407a in wherecode.c and vdbe.c.
3045**
drh2ce15c32017-07-11 13:34:40 +00003046** * For each "Goto", if the jump destination is earlier in the program
3047** and ends on one of:
3048** Yield SeekGt SeekLt RowSetRead Rewind
3049** or if the P1 parameter is one instead of zero,
3050** then indent all opcodes between the earlier instruction
3051** and "Goto" by 2 spaces.
3052*/
3053static void explain_data_prepare(ShellState *p, sqlite3_stmt *pSql){
3054 const char *zSql; /* The text of the SQL statement */
3055 const char *z; /* Used to check if this is an EXPLAIN */
3056 int *abYield = 0; /* True if op is an OP_Yield */
3057 int nAlloc = 0; /* Allocated size of p->aiIndent[], abYield */
3058 int iOp; /* Index of operation in p->aiIndent[] */
3059
drhe603ab02022-04-07 19:06:31 +00003060 const char *azNext[] = { "Next", "Prev", "VPrev", "VNext", "SorterNext",
3061 "Return", 0 };
drh2ce15c32017-07-11 13:34:40 +00003062 const char *azYield[] = { "Yield", "SeekLT", "SeekGT", "RowSetRead",
3063 "Rewind", 0 };
3064 const char *azGoto[] = { "Goto", 0 };
3065
3066 /* Try to figure out if this is really an EXPLAIN statement. If this
3067 ** cannot be verified, return early. */
3068 if( sqlite3_column_count(pSql)!=8 ){
3069 p->cMode = p->mode;
3070 return;
3071 }
3072 zSql = sqlite3_sql(pSql);
3073 if( zSql==0 ) return;
3074 for(z=zSql; *z==' ' || *z=='\t' || *z=='\n' || *z=='\f' || *z=='\r'; z++);
3075 if( sqlite3_strnicmp(z, "explain", 7) ){
3076 p->cMode = p->mode;
3077 return;
3078 }
3079
3080 for(iOp=0; SQLITE_ROW==sqlite3_step(pSql); iOp++){
3081 int i;
3082 int iAddr = sqlite3_column_int(pSql, 0);
3083 const char *zOp = (const char*)sqlite3_column_text(pSql, 1);
3084
3085 /* Set p2 to the P2 field of the current opcode. Then, assuming that
3086 ** p2 is an instruction address, set variable p2op to the index of that
3087 ** instruction in the aiIndent[] array. p2 and p2op may be different if
3088 ** the current instruction is part of a sub-program generated by an
3089 ** SQL trigger or foreign key. */
3090 int p2 = sqlite3_column_int(pSql, 3);
3091 int p2op = (p2 + (iOp-iAddr));
3092
3093 /* Grow the p->aiIndent array as required */
3094 if( iOp>=nAlloc ){
3095 if( iOp==0 ){
3096 /* Do further verfication that this is explain output. Abort if
3097 ** it is not */
3098 static const char *explainCols[] = {
3099 "addr", "opcode", "p1", "p2", "p3", "p4", "p5", "comment" };
3100 int jj;
3101 for(jj=0; jj<ArraySize(explainCols); jj++){
drhbf70f1b2022-10-19 18:04:42 +00003102 if( cli_strcmp(sqlite3_column_name(pSql,jj),explainCols[jj])!=0 ){
drh2ce15c32017-07-11 13:34:40 +00003103 p->cMode = p->mode;
3104 sqlite3_reset(pSql);
3105 return;
3106 }
3107 }
3108 }
3109 nAlloc += 100;
3110 p->aiIndent = (int*)sqlite3_realloc64(p->aiIndent, nAlloc*sizeof(int));
drhe3e25652021-12-16 13:29:28 +00003111 shell_check_oom(p->aiIndent);
drh2ce15c32017-07-11 13:34:40 +00003112 abYield = (int*)sqlite3_realloc64(abYield, nAlloc*sizeof(int));
drhe3e25652021-12-16 13:29:28 +00003113 shell_check_oom(abYield);
drh2ce15c32017-07-11 13:34:40 +00003114 }
3115 abYield[iOp] = str_in_array(zOp, azYield);
3116 p->aiIndent[iOp] = 0;
3117 p->nIndent = iOp+1;
3118
drhe603ab02022-04-07 19:06:31 +00003119 if( str_in_array(zOp, azNext) && p2op>0 ){
drh2ce15c32017-07-11 13:34:40 +00003120 for(i=p2op; i<iOp; i++) p->aiIndent[i] += 2;
3121 }
3122 if( str_in_array(zOp, azGoto) && p2op<p->nIndent
3123 && (abYield[p2op] || sqlite3_column_int(pSql, 2))
3124 ){
3125 for(i=p2op; i<iOp; i++) p->aiIndent[i] += 2;
3126 }
3127 }
3128
3129 p->iIndent = 0;
3130 sqlite3_free(abYield);
3131 sqlite3_reset(pSql);
3132}
3133
3134/*
3135** Free the array allocated by explain_data_prepare().
3136*/
3137static void explain_data_delete(ShellState *p){
3138 sqlite3_free(p->aiIndent);
3139 p->aiIndent = 0;
3140 p->nIndent = 0;
3141 p->iIndent = 0;
3142}
3143
3144/*
drh5e431be2022-04-06 11:08:38 +00003145** Disable and restore .wheretrace and .treetrace/.selecttrace settings.
drh2ce15c32017-07-11 13:34:40 +00003146*/
drhc0622a42020-12-04 01:17:57 +00003147static unsigned int savedSelectTrace;
3148static unsigned int savedWhereTrace;
drh2ce15c32017-07-11 13:34:40 +00003149static void disable_debug_trace_modes(void){
drh0a2fb792020-12-04 16:58:20 +00003150 unsigned int zero = 0;
drhc0622a42020-12-04 01:17:57 +00003151 sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 0, &savedSelectTrace);
drh0a2fb792020-12-04 16:58:20 +00003152 sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 1, &zero);
drhc0622a42020-12-04 01:17:57 +00003153 sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 2, &savedWhereTrace);
drh0a2fb792020-12-04 16:58:20 +00003154 sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 3, &zero);
drh2ce15c32017-07-11 13:34:40 +00003155}
3156static void restore_debug_trace_modes(void){
drhc0622a42020-12-04 01:17:57 +00003157 sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 1, &savedSelectTrace);
3158 sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 3, &savedWhereTrace);
drh2ce15c32017-07-11 13:34:40 +00003159}
3160
drh9cb02642019-02-28 20:10:52 +00003161/* Create the TEMP table used to store parameter bindings */
3162static void bind_table_init(ShellState *p){
drh346f4e22019-03-25 21:35:41 +00003163 int wrSchema = 0;
drh4b86e202020-01-19 20:37:26 +00003164 int defensiveMode = 0;
3165 sqlite3_db_config(p->db, SQLITE_DBCONFIG_DEFENSIVE, -1, &defensiveMode);
3166 sqlite3_db_config(p->db, SQLITE_DBCONFIG_DEFENSIVE, 0, 0);
drh346f4e22019-03-25 21:35:41 +00003167 sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, -1, &wrSchema);
3168 sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, 1, 0);
drh9cb02642019-02-28 20:10:52 +00003169 sqlite3_exec(p->db,
drh65c29fd2019-03-25 21:56:26 +00003170 "CREATE TABLE IF NOT EXISTS temp.sqlite_parameters(\n"
drh9cb02642019-02-28 20:10:52 +00003171 " key TEXT PRIMARY KEY,\n"
larrybrdabada62021-04-04 12:52:58 +00003172 " value\n"
drh9cb02642019-02-28 20:10:52 +00003173 ") WITHOUT ROWID;",
3174 0, 0, 0);
drh346f4e22019-03-25 21:35:41 +00003175 sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, wrSchema, 0);
drh4b86e202020-01-19 20:37:26 +00003176 sqlite3_db_config(p->db, SQLITE_DBCONFIG_DEFENSIVE, defensiveMode, 0);
drh9cb02642019-02-28 20:10:52 +00003177}
3178
drh8b738d02019-02-25 18:43:54 +00003179/*
3180** Bind parameters on a prepared statement.
3181**
3182** Parameter bindings are taken from a TEMP table of the form:
3183**
drh1cb02632019-03-25 22:05:22 +00003184** CREATE TEMP TABLE sqlite_parameters(key TEXT PRIMARY KEY, value)
drh8b738d02019-02-25 18:43:54 +00003185** WITHOUT ROWID;
3186**
drh91654b22020-04-02 13:21:10 +00003187** No bindings occur if this table does not exist. The name of the table
3188** begins with "sqlite_" so that it will not collide with ordinary application
3189** tables. The table must be in the TEMP schema.
drh8b738d02019-02-25 18:43:54 +00003190*/
3191static void bind_prepared_stmt(ShellState *pArg, sqlite3_stmt *pStmt){
3192 int nVar;
3193 int i;
3194 int rc;
3195 sqlite3_stmt *pQ = 0;
3196
3197 nVar = sqlite3_bind_parameter_count(pStmt);
3198 if( nVar==0 ) return; /* Nothing to do */
drh65c29fd2019-03-25 21:56:26 +00003199 if( sqlite3_table_column_metadata(pArg->db, "TEMP", "sqlite_parameters",
drh8b738d02019-02-25 18:43:54 +00003200 "key", 0, 0, 0, 0, 0)!=SQLITE_OK ){
3201 return; /* Parameter table does not exist */
3202 }
3203 rc = sqlite3_prepare_v2(pArg->db,
drh65c29fd2019-03-25 21:56:26 +00003204 "SELECT value FROM temp.sqlite_parameters"
drh8b738d02019-02-25 18:43:54 +00003205 " WHERE key=?1", -1, &pQ, 0);
3206 if( rc || pQ==0 ) return;
3207 for(i=1; i<=nVar; i++){
3208 char zNum[30];
3209 const char *zVar = sqlite3_bind_parameter_name(pStmt, i);
3210 if( zVar==0 ){
3211 sqlite3_snprintf(sizeof(zNum),zNum,"?%d",i);
3212 zVar = zNum;
3213 }
3214 sqlite3_bind_text(pQ, 1, zVar, -1, SQLITE_STATIC);
3215 if( sqlite3_step(pQ)==SQLITE_ROW ){
3216 sqlite3_bind_value(pStmt, i, sqlite3_column_value(pQ, 0));
3217 }else{
3218 sqlite3_bind_null(pStmt, i);
3219 }
3220 sqlite3_reset(pQ);
3221 }
3222 sqlite3_finalize(pQ);
3223}
3224
drh30c54a02020-05-28 23:49:50 +00003225/*
drh0908e382020-06-04 18:05:39 +00003226** UTF8 box-drawing characters. Imagine box lines like this:
3227**
3228** 1
3229** |
3230** 4 --+-- 2
3231** |
3232** 3
3233**
3234** Each box characters has between 2 and 4 of the lines leading from
3235** the center. The characters are here identified by the numbers of
3236** their corresponding lines.
3237*/
3238#define BOX_24 "\342\224\200" /* U+2500 --- */
3239#define BOX_13 "\342\224\202" /* U+2502 | */
3240#define BOX_23 "\342\224\214" /* U+250c ,- */
3241#define BOX_34 "\342\224\220" /* U+2510 -, */
3242#define BOX_12 "\342\224\224" /* U+2514 '- */
3243#define BOX_14 "\342\224\230" /* U+2518 -' */
3244#define BOX_123 "\342\224\234" /* U+251c |- */
3245#define BOX_134 "\342\224\244" /* U+2524 -| */
3246#define BOX_234 "\342\224\254" /* U+252c -,- */
3247#define BOX_124 "\342\224\264" /* U+2534 -'- */
3248#define BOX_1234 "\342\224\274" /* U+253c -|- */
3249
3250/* Draw horizontal line N characters long using unicode box
3251** characters
3252*/
3253static void print_box_line(FILE *out, int N){
3254 const char zDash[] =
3255 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24
3256 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24;
3257 const int nDash = sizeof(zDash) - 1;
3258 N *= 3;
3259 while( N>nDash ){
3260 utf8_printf(out, zDash);
3261 N -= nDash;
3262 }
3263 utf8_printf(out, "%.*s", N, zDash);
3264}
3265
3266/*
3267** Draw a horizontal separator for a MODE_Box table.
3268*/
3269static void print_box_row_separator(
3270 ShellState *p,
3271 int nArg,
3272 const char *zSep1,
3273 const char *zSep2,
3274 const char *zSep3
3275){
3276 int i;
3277 if( nArg>0 ){
3278 utf8_printf(p->out, "%s", zSep1);
3279 print_box_line(p->out, p->actualWidth[0]+2);
3280 for(i=1; i<nArg; i++){
3281 utf8_printf(p->out, "%s", zSep2);
3282 print_box_line(p->out, p->actualWidth[i]+2);
3283 }
3284 utf8_printf(p->out, "%s", zSep3);
3285 }
3286 fputs("\n", p->out);
3287}
3288
drh09a39ed2022-01-30 21:09:03 +00003289/*
3290** z[] is a line of text that is to be displayed the .mode box or table or
3291** similar tabular formats. z[] might contain control characters such
3292** as \n, \t, \f, or \r.
3293**
3294** Compute characters to display on the first line of z[]. Stop at the
3295** first \r, \n, or \f. Expand \t into spaces. Return a copy (obtained
larrybrcc4d55c2022-02-01 02:50:45 +00003296** from malloc()) of that first line, which caller should free sometime.
3297** Write anything to display on the next line into *pzTail. If this is
3298** the last line, write a NULL into *pzTail. (*pzTail is not allocated.)
drh09a39ed2022-01-30 21:09:03 +00003299*/
3300static char *translateForDisplayAndDup(
drhca1776b2022-02-01 12:28:17 +00003301 const unsigned char *z, /* Input text to be transformed */
3302 const unsigned char **pzTail, /* OUT: Tail of the input for next line */
3303 int mxWidth, /* Max width. 0 means no limit */
3304 u8 bWordWrap /* If true, avoid breaking mid-word */
drh09a39ed2022-01-30 21:09:03 +00003305){
drhca1776b2022-02-01 12:28:17 +00003306 int i; /* Input bytes consumed */
3307 int j; /* Output bytes generated */
3308 int k; /* Input bytes to be displayed */
3309 int n; /* Output column number */
3310 unsigned char *zOut; /* Output text */
3311
drh09a39ed2022-01-30 21:09:03 +00003312 if( z==0 ){
3313 *pzTail = 0;
3314 return 0;
3315 }
3316 if( mxWidth<0 ) mxWidth = -mxWidth;
3317 if( mxWidth==0 ) mxWidth = 1000000;
drhca1776b2022-02-01 12:28:17 +00003318 i = j = n = 0;
drh09a39ed2022-01-30 21:09:03 +00003319 while( n<mxWidth ){
3320 if( z[i]>=' ' ){
3321 n++;
drhb6172192022-01-31 10:55:50 +00003322 do{ i++; j++; }while( (z[i]&0xc0)==0x80 );
drh09a39ed2022-01-30 21:09:03 +00003323 continue;
3324 }
3325 if( z[i]=='\t' ){
drhb6172192022-01-31 10:55:50 +00003326 do{
3327 n++;
3328 j++;
3329 }while( (n&7)!=0 && n<mxWidth );
drh09a39ed2022-01-30 21:09:03 +00003330 i++;
3331 continue;
3332 }
3333 break;
3334 }
drhca1776b2022-02-01 12:28:17 +00003335 if( n>=mxWidth && bWordWrap ){
3336 /* Perhaps try to back up to a better place to break the line */
3337 for(k=i; k>i/2; k--){
3338 if( isspace(z[k-1]) ) break;
3339 }
3340 if( k<=i/2 ){
3341 for(k=i; k>i/2; k--){
drhe66532a2022-02-01 13:17:11 +00003342 if( isalnum(z[k-1])!=isalnum(z[k]) && (z[k]&0xc0)!=0x80 ) break;
drhca1776b2022-02-01 12:28:17 +00003343 }
3344 }
3345 if( k<=i/2 ){
3346 k = i;
3347 }else{
3348 i = k;
3349 while( z[i]==' ' ) i++;
3350 }
3351 }else{
3352 k = i;
larrybrcc4d55c2022-02-01 02:50:45 +00003353 }
drh09a39ed2022-01-30 21:09:03 +00003354 if( n>=mxWidth && z[i]>=' ' ){
3355 *pzTail = &z[i];
3356 }else if( z[i]=='\r' && z[i+1]=='\n' ){
3357 *pzTail = z[i+2] ? &z[i+2] : 0;
drhb6172192022-01-31 10:55:50 +00003358 }else if( z[i]==0 || z[i+1]==0 ){
drh09a39ed2022-01-30 21:09:03 +00003359 *pzTail = 0;
3360 }else{
3361 *pzTail = &z[i+1];
3362 }
drhb6172192022-01-31 10:55:50 +00003363 zOut = malloc( j+1 );
drh09a39ed2022-01-30 21:09:03 +00003364 shell_check_oom(zOut);
drhb6172192022-01-31 10:55:50 +00003365 i = j = n = 0;
drhca1776b2022-02-01 12:28:17 +00003366 while( i<k ){
drh09a39ed2022-01-30 21:09:03 +00003367 if( z[i]>=' ' ){
drhb6172192022-01-31 10:55:50 +00003368 n++;
3369 do{ zOut[j++] = z[i++]; }while( (z[i]&0xc0)==0x80 );
drh09a39ed2022-01-30 21:09:03 +00003370 continue;
3371 }
3372 if( z[i]=='\t' ){
3373 do{
drhb6172192022-01-31 10:55:50 +00003374 n++;
3375 zOut[j++] = ' ';
drh09a39ed2022-01-30 21:09:03 +00003376 }while( (n&7)!=0 && n<mxWidth );
3377 i++;
3378 continue;
3379 }
3380 break;
3381 }
drhb6172192022-01-31 10:55:50 +00003382 zOut[j] = 0;
drh09a39ed2022-01-30 21:09:03 +00003383 return (char*)zOut;
3384}
3385
drhe40f2862022-01-31 14:14:29 +00003386/* Extract the value of the i-th current column for pStmt as an SQL literal
3387** value. Memory is obtained from sqlite3_malloc64() and must be freed by
3388** the caller.
3389*/
3390static char *quoted_column(sqlite3_stmt *pStmt, int i){
3391 switch( sqlite3_column_type(pStmt, i) ){
3392 case SQLITE_NULL: {
3393 return sqlite3_mprintf("NULL");
3394 }
3395 case SQLITE_INTEGER:
3396 case SQLITE_FLOAT: {
3397 return sqlite3_mprintf("%s",sqlite3_column_text(pStmt,i));
3398 }
3399 case SQLITE_TEXT: {
3400 return sqlite3_mprintf("%Q",sqlite3_column_text(pStmt,i));
3401 }
3402 case SQLITE_BLOB: {
3403 int j;
3404 sqlite3_str *pStr = sqlite3_str_new(0);
3405 const unsigned char *a = sqlite3_column_blob(pStmt,i);
3406 int n = sqlite3_column_bytes(pStmt,i);
3407 sqlite3_str_append(pStr, "x'", 2);
3408 for(j=0; j<n; j++){
3409 sqlite3_str_appendf(pStr, "%02x", a[j]);
3410 }
3411 sqlite3_str_append(pStr, "'", 1);
3412 return sqlite3_str_finish(pStr);
3413 }
3414 }
3415 return 0; /* Not reached */
3416}
drh0908e382020-06-04 18:05:39 +00003417
3418/*
drh30c54a02020-05-28 23:49:50 +00003419** Run a prepared statement and output the result in one of the
drh0908e382020-06-04 18:05:39 +00003420** table-oriented formats: MODE_Column, MODE_Markdown, MODE_Table,
3421** or MODE_Box.
drh30c54a02020-05-28 23:49:50 +00003422**
3423** This is different from ordinary exec_prepared_stmt() in that
3424** it has to run the entire query and gather the results into memory
3425** first, in order to determine column widths, before providing
3426** any output.
3427*/
drh8c748632020-05-29 16:15:58 +00003428static void exec_prepared_stmt_columnar(
3429 ShellState *p, /* Pointer to ShellState */
3430 sqlite3_stmt *pStmt /* Statment to run */
drh30c54a02020-05-28 23:49:50 +00003431){
drhf82ce382020-08-06 16:45:22 +00003432 sqlite3_int64 nRow = 0;
drh8c748632020-05-29 16:15:58 +00003433 int nColumn = 0;
3434 char **azData = 0;
drhf82ce382020-08-06 16:45:22 +00003435 sqlite3_int64 nAlloc = 0;
drh09a39ed2022-01-30 21:09:03 +00003436 char *abRowDiv = 0;
3437 const unsigned char *uz;
drh8c748632020-05-29 16:15:58 +00003438 const char *z;
drhe40f2862022-01-31 14:14:29 +00003439 char **azQuoted = 0;
drh8c748632020-05-29 16:15:58 +00003440 int rc;
drhf82ce382020-08-06 16:45:22 +00003441 sqlite3_int64 i, nData;
3442 int j, nTotal, w, n;
drh0908e382020-06-04 18:05:39 +00003443 const char *colSep = 0;
3444 const char *rowSep = 0;
drh09a39ed2022-01-30 21:09:03 +00003445 const unsigned char **azNextLine = 0;
3446 int bNextLine = 0;
3447 int bMultiLineRowExists = 0;
drhca1776b2022-02-01 12:28:17 +00003448 int bw = p->cmOpts.bWordWrap;
larrybr6403e772022-04-20 22:41:10 +00003449 const char *zEmpty = "";
3450 const char *zShowNull = p->nullValue;
drh30c54a02020-05-28 23:49:50 +00003451
drhf82ce382020-08-06 16:45:22 +00003452 rc = sqlite3_step(pStmt);
3453 if( rc!=SQLITE_ROW ) return;
3454 nColumn = sqlite3_column_count(pStmt);
3455 nAlloc = nColumn*4;
drh01a8ad22021-03-20 23:15:52 +00003456 if( nAlloc<=0 ) nAlloc = 1;
drhf82ce382020-08-06 16:45:22 +00003457 azData = sqlite3_malloc64( nAlloc*sizeof(char*) );
drhe3e25652021-12-16 13:29:28 +00003458 shell_check_oom(azData);
drh09a39ed2022-01-30 21:09:03 +00003459 azNextLine = sqlite3_malloc64( nColumn*sizeof(char*) );
drh5dce6f92022-01-31 16:29:06 +00003460 shell_check_oom((void*)azNextLine);
3461 memset((void*)azNextLine, 0, nColumn*sizeof(char*) );
larrybrcc4d55c2022-02-01 02:50:45 +00003462 if( p->cmOpts.bQuote ){
drhe40f2862022-01-31 14:14:29 +00003463 azQuoted = sqlite3_malloc64( nColumn*sizeof(char*) );
3464 shell_check_oom(azQuoted);
3465 memset(azQuoted, 0, nColumn*sizeof(char*) );
3466 }
drh09a39ed2022-01-30 21:09:03 +00003467 abRowDiv = sqlite3_malloc64( nAlloc/nColumn );
3468 shell_check_oom(abRowDiv);
drh8c748632020-05-29 16:15:58 +00003469 if( nColumn>p->nWidth ){
drh76fc88f2021-10-02 16:39:16 +00003470 p->colWidth = realloc(p->colWidth, (nColumn+1)*2*sizeof(int));
drhe3e25652021-12-16 13:29:28 +00003471 shell_check_oom(p->colWidth);
drh8c748632020-05-29 16:15:58 +00003472 for(i=p->nWidth; i<nColumn; i++) p->colWidth[i] = 0;
3473 p->nWidth = nColumn;
3474 p->actualWidth = &p->colWidth[nColumn];
3475 }
3476 memset(p->actualWidth, 0, nColumn*sizeof(int));
3477 for(i=0; i<nColumn; i++){
3478 w = p->colWidth[i];
3479 if( w<0 ) w = -w;
3480 p->actualWidth[i] = w;
3481 }
drh09a39ed2022-01-30 21:09:03 +00003482 for(i=0; i<nColumn; i++){
drh47741b82022-01-31 22:14:53 +00003483 const unsigned char *zNotUsed;
3484 int wx = p->colWidth[i];
larrybrcc4d55c2022-02-01 02:50:45 +00003485 if( wx==0 ){
3486 wx = p->cmOpts.iWrap;
larrybrcc4d55c2022-02-01 02:50:45 +00003487 }
drh47741b82022-01-31 22:14:53 +00003488 if( wx<0 ) wx = -wx;
3489 uz = (const unsigned char*)sqlite3_column_name(pStmt,i);
larrybrcc4d55c2022-02-01 02:50:45 +00003490 azData[i] = translateForDisplayAndDup(uz, &zNotUsed, wx, bw);
drh09a39ed2022-01-30 21:09:03 +00003491 }
3492 do{
3493 int useNextLine = bNextLine;
3494 bNextLine = 0;
3495 if( (nRow+2)*nColumn >= nAlloc ){
3496 nAlloc *= 2;
3497 azData = sqlite3_realloc64(azData, nAlloc*sizeof(char*));
3498 shell_check_oom(azData);
3499 abRowDiv = sqlite3_realloc64(abRowDiv, nAlloc/nColumn);
3500 shell_check_oom(abRowDiv);
3501 }
3502 abRowDiv[nRow] = 1;
3503 nRow++;
3504 for(i=0; i<nColumn; i++){
drh5dce6f92022-01-31 16:29:06 +00003505 int wx = p->colWidth[i];
larrybrcc4d55c2022-02-01 02:50:45 +00003506 if( wx==0 ){
3507 wx = p->cmOpts.iWrap;
larrybrcc4d55c2022-02-01 02:50:45 +00003508 }
drh47741b82022-01-31 22:14:53 +00003509 if( wx<0 ) wx = -wx;
drh09a39ed2022-01-30 21:09:03 +00003510 if( useNextLine ){
3511 uz = azNextLine[i];
drh7e9a56f2022-04-21 19:14:23 +00003512 if( uz==0 ) uz = (u8*)zEmpty;
larrybrcc4d55c2022-02-01 02:50:45 +00003513 }else if( p->cmOpts.bQuote ){
drhe40f2862022-01-31 14:14:29 +00003514 sqlite3_free(azQuoted[i]);
3515 azQuoted[i] = quoted_column(pStmt,i);
3516 uz = (const unsigned char*)azQuoted[i];
drh09a39ed2022-01-30 21:09:03 +00003517 }else{
3518 uz = (const unsigned char*)sqlite3_column_text(pStmt,i);
drh7e9a56f2022-04-21 19:14:23 +00003519 if( uz==0 ) uz = (u8*)zShowNull;
drh09a39ed2022-01-30 21:09:03 +00003520 }
larrybrcc4d55c2022-02-01 02:50:45 +00003521 azData[nRow*nColumn + i]
3522 = translateForDisplayAndDup(uz, &azNextLine[i], wx, bw);
drh09a39ed2022-01-30 21:09:03 +00003523 if( azNextLine[i] ){
3524 bNextLine = 1;
3525 abRowDiv[nRow-1] = 0;
3526 bMultiLineRowExists = 1;
3527 }
3528 }
3529 }while( bNextLine || sqlite3_step(pStmt)==SQLITE_ROW );
drh8c748632020-05-29 16:15:58 +00003530 nTotal = nColumn*(nRow+1);
3531 for(i=0; i<nTotal; i++){
3532 z = azData[i];
larrybr6403e772022-04-20 22:41:10 +00003533 if( z==0 ) z = (char*)zEmpty;
drh8c748632020-05-29 16:15:58 +00003534 n = strlenChar(z);
3535 j = i%nColumn;
3536 if( n>p->actualWidth[j] ) p->actualWidth[j] = n;
3537 }
drh99942982020-06-15 20:05:37 +00003538 if( seenInterrupt ) goto columnar_end;
drh01a8ad22021-03-20 23:15:52 +00003539 if( nColumn==0 ) goto columnar_end;
drh0908e382020-06-04 18:05:39 +00003540 switch( p->cMode ){
3541 case MODE_Column: {
3542 colSep = " ";
3543 rowSep = "\n";
3544 if( p->showHeader ){
3545 for(i=0; i<nColumn; i++){
3546 w = p->actualWidth[i];
3547 if( p->colWidth[i]<0 ) w = -w;
3548 utf8_width_print(p->out, w, azData[i]);
3549 fputs(i==nColumn-1?"\n":" ", p->out);
3550 }
3551 for(i=0; i<nColumn; i++){
3552 print_dashes(p->out, p->actualWidth[i]);
3553 fputs(i==nColumn-1?"\n":" ", p->out);
3554 }
3555 }
3556 break;
3557 }
3558 case MODE_Table: {
3559 colSep = " | ";
3560 rowSep = " |\n";
3561 print_row_separator(p, nColumn, "+");
3562 fputs("| ", p->out);
drh8c748632020-05-29 16:15:58 +00003563 for(i=0; i<nColumn; i++){
3564 w = p->actualWidth[i];
drh0908e382020-06-04 18:05:39 +00003565 n = strlenChar(azData[i]);
3566 utf8_printf(p->out, "%*s%s%*s", (w-n)/2, "", azData[i], (w-n+1)/2, "");
3567 fputs(i==nColumn-1?" |\n":" | ", p->out);
drh8c748632020-05-29 16:15:58 +00003568 }
drh0908e382020-06-04 18:05:39 +00003569 print_row_separator(p, nColumn, "+");
3570 break;
3571 }
3572 case MODE_Markdown: {
3573 colSep = " | ";
3574 rowSep = " |\n";
3575 fputs("| ", p->out);
drh8c748632020-05-29 16:15:58 +00003576 for(i=0; i<nColumn; i++){
drh0908e382020-06-04 18:05:39 +00003577 w = p->actualWidth[i];
3578 n = strlenChar(azData[i]);
3579 utf8_printf(p->out, "%*s%s%*s", (w-n)/2, "", azData[i], (w-n+1)/2, "");
3580 fputs(i==nColumn-1?" |\n":" | ", p->out);
drh8c748632020-05-29 16:15:58 +00003581 }
drh0908e382020-06-04 18:05:39 +00003582 print_row_separator(p, nColumn, "|");
3583 break;
drh8c748632020-05-29 16:15:58 +00003584 }
drh0908e382020-06-04 18:05:39 +00003585 case MODE_Box: {
3586 colSep = " " BOX_13 " ";
3587 rowSep = " " BOX_13 "\n";
3588 print_box_row_separator(p, nColumn, BOX_23, BOX_234, BOX_34);
3589 utf8_printf(p->out, BOX_13 " ");
3590 for(i=0; i<nColumn; i++){
3591 w = p->actualWidth[i];
3592 n = strlenChar(azData[i]);
3593 utf8_printf(p->out, "%*s%s%*s%s",
3594 (w-n)/2, "", azData[i], (w-n+1)/2, "",
3595 i==nColumn-1?" "BOX_13"\n":" "BOX_13" ");
3596 }
3597 print_box_row_separator(p, nColumn, BOX_123, BOX_1234, BOX_134);
3598 break;
drh8c748632020-05-29 16:15:58 +00003599 }
drh8c748632020-05-29 16:15:58 +00003600 }
3601 for(i=nColumn, j=0; i<nTotal; i++, j++){
drh0908e382020-06-04 18:05:39 +00003602 if( j==0 && p->cMode!=MODE_Column ){
3603 utf8_printf(p->out, "%s", p->cMode==MODE_Box?BOX_13" ":"| ");
3604 }
drh8c748632020-05-29 16:15:58 +00003605 z = azData[i];
3606 if( z==0 ) z = p->nullValue;
3607 w = p->actualWidth[j];
3608 if( p->colWidth[j]<0 ) w = -w;
3609 utf8_width_print(p->out, w, z);
3610 if( j==nColumn-1 ){
drh0908e382020-06-04 18:05:39 +00003611 utf8_printf(p->out, "%s", rowSep);
drh09a39ed2022-01-30 21:09:03 +00003612 if( bMultiLineRowExists && abRowDiv[i/nColumn-1] && i+1<nTotal ){
3613 if( p->cMode==MODE_Table ){
3614 print_row_separator(p, nColumn, "+");
3615 }else if( p->cMode==MODE_Box ){
3616 print_box_row_separator(p, nColumn, BOX_123, BOX_1234, BOX_134);
drh5aabdae2022-02-01 00:00:08 +00003617 }else if( p->cMode==MODE_Column ){
3618 raw_printf(p->out, "\n");
drh09a39ed2022-01-30 21:09:03 +00003619 }
3620 }
drh8c748632020-05-29 16:15:58 +00003621 j = -1;
drhdd853c32020-06-16 17:34:40 +00003622 if( seenInterrupt ) goto columnar_end;
drh8c748632020-05-29 16:15:58 +00003623 }else{
drh0908e382020-06-04 18:05:39 +00003624 utf8_printf(p->out, "%s", colSep);
drh8c748632020-05-29 16:15:58 +00003625 }
3626 }
3627 if( p->cMode==MODE_Table ){
3628 print_row_separator(p, nColumn, "+");
drh0908e382020-06-04 18:05:39 +00003629 }else if( p->cMode==MODE_Box ){
3630 print_box_row_separator(p, nColumn, BOX_12, BOX_124, BOX_14);
drh8c748632020-05-29 16:15:58 +00003631 }
drh99942982020-06-15 20:05:37 +00003632columnar_end:
drhdd853c32020-06-16 17:34:40 +00003633 if( seenInterrupt ){
3634 utf8_printf(p->out, "Interrupt\n");
3635 }
drhf82ce382020-08-06 16:45:22 +00003636 nData = (nRow+1)*nColumn;
larrybr6403e772022-04-20 22:41:10 +00003637 for(i=0; i<nData; i++){
3638 z = azData[i];
drh744c17c2022-05-05 10:02:19 +00003639 if( z!=zEmpty && z!=zShowNull ) free(azData[i]);
larrybr6403e772022-04-20 22:41:10 +00003640 }
drhf82ce382020-08-06 16:45:22 +00003641 sqlite3_free(azData);
drh5dce6f92022-01-31 16:29:06 +00003642 sqlite3_free((void*)azNextLine);
drh09a39ed2022-01-30 21:09:03 +00003643 sqlite3_free(abRowDiv);
drhe40f2862022-01-31 14:14:29 +00003644 if( azQuoted ){
3645 for(i=0; i<nColumn; i++) sqlite3_free(azQuoted[i]);
3646 sqlite3_free(azQuoted);
3647 }
drh30c54a02020-05-28 23:49:50 +00003648}
drh30c54a02020-05-28 23:49:50 +00003649
drh2ce15c32017-07-11 13:34:40 +00003650/*
3651** Run a prepared statement
3652*/
3653static void exec_prepared_stmt(
3654 ShellState *pArg, /* Pointer to ShellState */
drha10b9992018-03-09 15:24:33 +00003655 sqlite3_stmt *pStmt /* Statment to run */
drh2ce15c32017-07-11 13:34:40 +00003656){
3657 int rc;
drh5d88be82021-12-09 16:17:43 +00003658 sqlite3_uint64 nRow = 0;
drh2ce15c32017-07-11 13:34:40 +00003659
drh8c748632020-05-29 16:15:58 +00003660 if( pArg->cMode==MODE_Column
3661 || pArg->cMode==MODE_Table
drh0908e382020-06-04 18:05:39 +00003662 || pArg->cMode==MODE_Box
drh8c748632020-05-29 16:15:58 +00003663 || pArg->cMode==MODE_Markdown
3664 ){
3665 exec_prepared_stmt_columnar(pArg, pStmt);
3666 return;
3667 }
3668
drh2ce15c32017-07-11 13:34:40 +00003669 /* perform the first step. this will tell us if we
3670 ** have a result set or not and how wide it is.
3671 */
3672 rc = sqlite3_step(pStmt);
3673 /* if we have a result set... */
3674 if( SQLITE_ROW == rc ){
drha10b9992018-03-09 15:24:33 +00003675 /* allocate space for col name ptr, value ptr, and type */
3676 int nCol = sqlite3_column_count(pStmt);
3677 void *pData = sqlite3_malloc64(3*nCol*sizeof(const char*) + 1);
3678 if( !pData ){
drhe85e1da2021-10-01 21:01:07 +00003679 shell_out_of_memory();
drh2ce15c32017-07-11 13:34:40 +00003680 }else{
drha10b9992018-03-09 15:24:33 +00003681 char **azCols = (char **)pData; /* Names of result columns */
3682 char **azVals = &azCols[nCol]; /* Results */
3683 int *aiTypes = (int *)&azVals[nCol]; /* Result types */
3684 int i, x;
3685 assert(sizeof(int) <= sizeof(char *));
3686 /* save off ptrs to column names */
3687 for(i=0; i<nCol; i++){
3688 azCols[i] = (char *)sqlite3_column_name(pStmt, i);
3689 }
drh2ce15c32017-07-11 13:34:40 +00003690 do{
drh5d88be82021-12-09 16:17:43 +00003691 nRow++;
drha10b9992018-03-09 15:24:33 +00003692 /* extract the data and data types */
3693 for(i=0; i<nCol; i++){
3694 aiTypes[i] = x = sqlite3_column_type(pStmt, i);
drh5d1bf4f2022-01-02 20:54:33 +00003695 if( x==SQLITE_BLOB
3696 && pArg
3697 && (pArg->cMode==MODE_Insert || pArg->cMode==MODE_Quote)
3698 ){
drha10b9992018-03-09 15:24:33 +00003699 azVals[i] = "";
3700 }else{
3701 azVals[i] = (char*)sqlite3_column_text(pStmt, i);
3702 }
3703 if( !azVals[i] && (aiTypes[i]!=SQLITE_NULL) ){
3704 rc = SQLITE_NOMEM;
3705 break; /* from for */
3706 }
3707 } /* end for */
3708
3709 /* if data and types extracted successfully... */
3710 if( SQLITE_ROW == rc ){
3711 /* call the supplied callback with the result row data */
3712 if( shell_callback(pArg, nCol, azVals, azCols, aiTypes) ){
3713 rc = SQLITE_ABORT;
3714 }else{
3715 rc = sqlite3_step(pStmt);
3716 }
3717 }
3718 } while( SQLITE_ROW == rc );
3719 sqlite3_free(pData);
drh0908e382020-06-04 18:05:39 +00003720 if( pArg->cMode==MODE_Json ){
drh30c54a02020-05-28 23:49:50 +00003721 fputs("]\n", pArg->out);
drh5d88be82021-12-09 16:17:43 +00003722 }else if( pArg->cMode==MODE_Count ){
mistachkinc158c072021-12-31 19:08:20 +00003723 char zBuf[200];
3724 sqlite3_snprintf(sizeof(zBuf), zBuf, "%llu row%s\n",
3725 nRow, nRow!=1 ? "s" : "");
3726 printf("%s", zBuf);
drh30c54a02020-05-28 23:49:50 +00003727 }
drh2ce15c32017-07-11 13:34:40 +00003728 }
3729 }
3730}
3731
dan6b046be2018-01-09 15:25:55 +00003732#ifndef SQLITE_OMIT_VIRTUALTABLE
drh2ce15c32017-07-11 13:34:40 +00003733/*
dan43efc182017-12-19 17:42:13 +00003734** This function is called to process SQL if the previous shell command
3735** was ".expert". It passes the SQL in the second argument directly to
3736** the sqlite3expert object.
3737**
3738** If successful, SQLITE_OK is returned. Otherwise, an SQLite error
3739** code. In this case, (*pzErr) may be set to point to a buffer containing
3740** an English language error message. It is the responsibility of the
3741** caller to eventually free this buffer using sqlite3_free().
3742*/
3743static int expertHandleSQL(
3744 ShellState *pState,
3745 const char *zSql,
3746 char **pzErr
3747){
3748 assert( pState->expert.pExpert );
3749 assert( pzErr==0 || *pzErr==0 );
3750 return sqlite3_expert_sql(pState->expert.pExpert, zSql, pzErr);
3751}
3752
3753/*
3754** This function is called either to silently clean up the object
3755** created by the ".expert" command (if bCancel==1), or to generate a
3756** report from it and then clean it up (if bCancel==0).
3757**
3758** If successful, SQLITE_OK is returned. Otherwise, an SQLite error
3759** code. In this case, (*pzErr) may be set to point to a buffer containing
3760** an English language error message. It is the responsibility of the
3761** caller to eventually free this buffer using sqlite3_free().
3762*/
3763static int expertFinish(
3764 ShellState *pState,
3765 int bCancel,
3766 char **pzErr
3767){
3768 int rc = SQLITE_OK;
3769 sqlite3expert *p = pState->expert.pExpert;
3770 assert( p );
3771 assert( bCancel || pzErr==0 || *pzErr==0 );
3772 if( bCancel==0 ){
3773 FILE *out = pState->out;
3774 int bVerbose = pState->expert.bVerbose;
3775
3776 rc = sqlite3_expert_analyze(p, pzErr);
3777 if( rc==SQLITE_OK ){
3778 int nQuery = sqlite3_expert_count(p);
3779 int i;
3780
3781 if( bVerbose ){
3782 const char *zCand = sqlite3_expert_report(p,0,EXPERT_REPORT_CANDIDATES);
3783 raw_printf(out, "-- Candidates -----------------------------\n");
3784 raw_printf(out, "%s\n", zCand);
3785 }
3786 for(i=0; i<nQuery; i++){
3787 const char *zSql = sqlite3_expert_report(p, i, EXPERT_REPORT_SQL);
3788 const char *zIdx = sqlite3_expert_report(p, i, EXPERT_REPORT_INDEXES);
3789 const char *zEQP = sqlite3_expert_report(p, i, EXPERT_REPORT_PLAN);
3790 if( zIdx==0 ) zIdx = "(no new indexes)\n";
3791 if( bVerbose ){
3792 raw_printf(out, "-- Query %d --------------------------------\n",i+1);
3793 raw_printf(out, "%s\n\n", zSql);
3794 }
3795 raw_printf(out, "%s\n", zIdx);
3796 raw_printf(out, "%s\n", zEQP);
3797 }
3798 }
3799 }
3800 sqlite3_expert_destroy(p);
3801 pState->expert.pExpert = 0;
3802 return rc;
3803}
3804
dan6b046be2018-01-09 15:25:55 +00003805/*
3806** Implementation of ".expert" dot command.
3807*/
3808static int expertDotCommand(
3809 ShellState *pState, /* Current shell tool state */
3810 char **azArg, /* Array of arguments passed to dot command */
3811 int nArg /* Number of entries in azArg[] */
3812){
3813 int rc = SQLITE_OK;
3814 char *zErr = 0;
3815 int i;
3816 int iSample = 0;
3817
3818 assert( pState->expert.pExpert==0 );
3819 memset(&pState->expert, 0, sizeof(ExpertInfo));
3820
3821 for(i=1; rc==SQLITE_OK && i<nArg; i++){
3822 char *z = azArg[i];
3823 int n;
3824 if( z[0]=='-' && z[1]=='-' ) z++;
3825 n = strlen30(z);
drhbf70f1b2022-10-19 18:04:42 +00003826 if( n>=2 && 0==cli_strncmp(z, "-verbose", n) ){
dan6b046be2018-01-09 15:25:55 +00003827 pState->expert.bVerbose = 1;
3828 }
drhbf70f1b2022-10-19 18:04:42 +00003829 else if( n>=2 && 0==cli_strncmp(z, "-sample", n) ){
dan6b046be2018-01-09 15:25:55 +00003830 if( i==(nArg-1) ){
3831 raw_printf(stderr, "option requires an argument: %s\n", z);
3832 rc = SQLITE_ERROR;
3833 }else{
3834 iSample = (int)integerValue(azArg[++i]);
3835 if( iSample<0 || iSample>100 ){
3836 raw_printf(stderr, "value out of range: %s\n", azArg[i]);
3837 rc = SQLITE_ERROR;
3838 }
3839 }
3840 }
3841 else{
3842 raw_printf(stderr, "unknown option: %s\n", z);
3843 rc = SQLITE_ERROR;
3844 }
3845 }
3846
3847 if( rc==SQLITE_OK ){
3848 pState->expert.pExpert = sqlite3_expert_new(pState->db, &zErr);
3849 if( pState->expert.pExpert==0 ){
drhe0adf602021-12-16 14:26:16 +00003850 raw_printf(stderr, "sqlite3_expert_new: %s\n", zErr ? zErr : "out of memory");
dan6b046be2018-01-09 15:25:55 +00003851 rc = SQLITE_ERROR;
3852 }else{
3853 sqlite3_expert_config(
3854 pState->expert.pExpert, EXPERT_CONFIG_SAMPLE, iSample
3855 );
3856 }
3857 }
drhe0adf602021-12-16 14:26:16 +00003858 sqlite3_free(zErr);
dan6b046be2018-01-09 15:25:55 +00003859
3860 return rc;
3861}
3862#endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */
dan43efc182017-12-19 17:42:13 +00003863
3864/*
drh2ce15c32017-07-11 13:34:40 +00003865** Execute a statement or set of statements. Print
3866** any result rows/columns depending on the current mode
3867** set via the supplied callback.
3868**
3869** This is very similar to SQLite's built-in sqlite3_exec()
3870** function except it takes a slightly different callback
3871** and callback data argument.
3872*/
3873static int shell_exec(
drh2ce15c32017-07-11 13:34:40 +00003874 ShellState *pArg, /* Pointer to ShellState */
drha10b9992018-03-09 15:24:33 +00003875 const char *zSql, /* SQL to be evaluated */
drh2ce15c32017-07-11 13:34:40 +00003876 char **pzErrMsg /* Error msg written here */
3877){
3878 sqlite3_stmt *pStmt = NULL; /* Statement to execute. */
3879 int rc = SQLITE_OK; /* Return Code */
3880 int rc2;
3881 const char *zLeftover; /* Tail of unprocessed SQL */
drha10b9992018-03-09 15:24:33 +00003882 sqlite3 *db = pArg->db;
drh2ce15c32017-07-11 13:34:40 +00003883
3884 if( pzErrMsg ){
3885 *pzErrMsg = NULL;
3886 }
3887
dan6b046be2018-01-09 15:25:55 +00003888#ifndef SQLITE_OMIT_VIRTUALTABLE
dan43efc182017-12-19 17:42:13 +00003889 if( pArg->expert.pExpert ){
3890 rc = expertHandleSQL(pArg, zSql, pzErrMsg);
3891 return expertFinish(pArg, (rc!=SQLITE_OK), pzErrMsg);
3892 }
dan6b046be2018-01-09 15:25:55 +00003893#endif
dan43efc182017-12-19 17:42:13 +00003894
drh2ce15c32017-07-11 13:34:40 +00003895 while( zSql[0] && (SQLITE_OK == rc) ){
3896 static const char *zStmtSql;
3897 rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zLeftover);
3898 if( SQLITE_OK != rc ){
3899 if( pzErrMsg ){
drh633c7982022-02-08 12:13:16 +00003900 *pzErrMsg = save_err_msg(db, "in prepare", rc, zSql);
drh2ce15c32017-07-11 13:34:40 +00003901 }
3902 }else{
3903 if( !pStmt ){
3904 /* this happens for a comment or white-space */
3905 zSql = zLeftover;
3906 while( IsSpace(zSql[0]) ) zSql++;
3907 continue;
3908 }
3909 zStmtSql = sqlite3_sql(pStmt);
3910 if( zStmtSql==0 ) zStmtSql = "";
3911 while( IsSpace(zStmtSql[0]) ) zStmtSql++;
3912
3913 /* save off the prepared statment handle and reset row count */
3914 if( pArg ){
3915 pArg->pStmt = pStmt;
3916 pArg->cnt = 0;
3917 }
3918
drh2ce15c32017-07-11 13:34:40 +00003919 /* Show the EXPLAIN QUERY PLAN if .eqp is on */
drh39c5c4a2019-03-06 14:53:27 +00003920 if( pArg && pArg->autoEQP && sqlite3_stmt_isexplain(pStmt)==0 ){
drh2ce15c32017-07-11 13:34:40 +00003921 sqlite3_stmt *pExplain;
3922 char *zEQP;
drhada70452017-12-21 21:02:27 +00003923 int triggerEQP = 0;
drh2ce15c32017-07-11 13:34:40 +00003924 disable_debug_trace_modes();
drhada70452017-12-21 21:02:27 +00003925 sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, -1, &triggerEQP);
3926 if( pArg->autoEQP>=AUTOEQP_trigger ){
3927 sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, 1, 0);
3928 }
drh2ce15c32017-07-11 13:34:40 +00003929 zEQP = sqlite3_mprintf("EXPLAIN QUERY PLAN %s", zStmtSql);
drhe3e25652021-12-16 13:29:28 +00003930 shell_check_oom(zEQP);
drh2ce15c32017-07-11 13:34:40 +00003931 rc = sqlite3_prepare_v2(db, zEQP, -1, &pExplain, 0);
3932 if( rc==SQLITE_OK ){
3933 while( sqlite3_step(pExplain)==SQLITE_ROW ){
drh4b5345c2018-04-24 13:07:40 +00003934 const char *zEQPLine = (const char*)sqlite3_column_text(pExplain,3);
drhe2ca99c2018-05-02 00:33:43 +00003935 int iEqpId = sqlite3_column_int(pExplain, 0);
3936 int iParentId = sqlite3_column_int(pExplain, 1);
drh7e088a62020-05-02 00:01:39 +00003937 if( zEQPLine==0 ) zEQPLine = "";
drh4b5345c2018-04-24 13:07:40 +00003938 if( zEQPLine[0]=='-' ) eqp_render(pArg);
drhe2ca99c2018-05-02 00:33:43 +00003939 eqp_append(pArg, iEqpId, iParentId, zEQPLine);
drh2ce15c32017-07-11 13:34:40 +00003940 }
drh4b5345c2018-04-24 13:07:40 +00003941 eqp_render(pArg);
drh2ce15c32017-07-11 13:34:40 +00003942 }
3943 sqlite3_finalize(pExplain);
3944 sqlite3_free(zEQP);
drhada70452017-12-21 21:02:27 +00003945 if( pArg->autoEQP>=AUTOEQP_full ){
drh2ce15c32017-07-11 13:34:40 +00003946 /* Also do an EXPLAIN for ".eqp full" mode */
3947 zEQP = sqlite3_mprintf("EXPLAIN %s", zStmtSql);
drhe3e25652021-12-16 13:29:28 +00003948 shell_check_oom(zEQP);
drh2ce15c32017-07-11 13:34:40 +00003949 rc = sqlite3_prepare_v2(db, zEQP, -1, &pExplain, 0);
3950 if( rc==SQLITE_OK ){
3951 pArg->cMode = MODE_Explain;
3952 explain_data_prepare(pArg, pExplain);
drha10b9992018-03-09 15:24:33 +00003953 exec_prepared_stmt(pArg, pExplain);
drh2ce15c32017-07-11 13:34:40 +00003954 explain_data_delete(pArg);
3955 }
3956 sqlite3_finalize(pExplain);
3957 sqlite3_free(zEQP);
3958 }
drh51efe092018-03-20 12:04:38 +00003959 if( pArg->autoEQP>=AUTOEQP_trigger && triggerEQP==0 ){
3960 sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, 0, 0);
3961 /* Reprepare pStmt before reactiving trace modes */
3962 sqlite3_finalize(pStmt);
3963 sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
drh3c49eaf2018-06-07 15:23:43 +00003964 if( pArg ) pArg->pStmt = pStmt;
drh51efe092018-03-20 12:04:38 +00003965 }
drh2ce15c32017-07-11 13:34:40 +00003966 restore_debug_trace_modes();
3967 }
3968
3969 if( pArg ){
3970 pArg->cMode = pArg->mode;
drh4b5345c2018-04-24 13:07:40 +00003971 if( pArg->autoExplain ){
drh39c5c4a2019-03-06 14:53:27 +00003972 if( sqlite3_stmt_isexplain(pStmt)==1 ){
drh4b5345c2018-04-24 13:07:40 +00003973 pArg->cMode = MODE_Explain;
3974 }
drh39c5c4a2019-03-06 14:53:27 +00003975 if( sqlite3_stmt_isexplain(pStmt)==2 ){
drh4b5345c2018-04-24 13:07:40 +00003976 pArg->cMode = MODE_EQP;
3977 }
drh2ce15c32017-07-11 13:34:40 +00003978 }
3979
3980 /* If the shell is currently in ".explain" mode, gather the extra
3981 ** data required to add indents to the output.*/
3982 if( pArg->cMode==MODE_Explain ){
3983 explain_data_prepare(pArg, pStmt);
3984 }
3985 }
3986
drh8b738d02019-02-25 18:43:54 +00003987 bind_prepared_stmt(pArg, pStmt);
drha10b9992018-03-09 15:24:33 +00003988 exec_prepared_stmt(pArg, pStmt);
drh2ce15c32017-07-11 13:34:40 +00003989 explain_data_delete(pArg);
drh4b5345c2018-04-24 13:07:40 +00003990 eqp_render(pArg);
drh2ce15c32017-07-11 13:34:40 +00003991
3992 /* print usage stats if stats on */
3993 if( pArg && pArg->statsOn ){
3994 display_stats(db, pArg, 0);
3995 }
3996
3997 /* print loop-counters if required */
3998 if( pArg && pArg->scanstatsOn ){
3999 display_scanstats(db, pArg);
4000 }
4001
4002 /* Finalize the statement just executed. If this fails, save a
4003 ** copy of the error message. Otherwise, set zSql to point to the
4004 ** next statement to execute. */
4005 rc2 = sqlite3_finalize(pStmt);
4006 if( rc!=SQLITE_NOMEM ) rc = rc2;
4007 if( rc==SQLITE_OK ){
4008 zSql = zLeftover;
4009 while( IsSpace(zSql[0]) ) zSql++;
4010 }else if( pzErrMsg ){
drh633c7982022-02-08 12:13:16 +00004011 *pzErrMsg = save_err_msg(db, "stepping", rc, 0);
drh2ce15c32017-07-11 13:34:40 +00004012 }
4013
4014 /* clear saved stmt handle */
4015 if( pArg ){
4016 pArg->pStmt = NULL;
4017 }
4018 }
4019 } /* end while */
4020
4021 return rc;
4022}
4023
4024/*
4025** Release memory previously allocated by tableColumnList().
4026*/
4027static void freeColumnList(char **azCol){
4028 int i;
4029 for(i=1; azCol[i]; i++){
4030 sqlite3_free(azCol[i]);
4031 }
4032 /* azCol[0] is a static string */
4033 sqlite3_free(azCol);
4034}
4035
4036/*
4037** Return a list of pointers to strings which are the names of all
4038** columns in table zTab. The memory to hold the names is dynamically
4039** allocated and must be released by the caller using a subsequent call
4040** to freeColumnList().
4041**
4042** The azCol[0] entry is usually NULL. However, if zTab contains a rowid
4043** value that needs to be preserved, then azCol[0] is filled in with the
4044** name of the rowid column.
4045**
4046** The first regular column in the table is azCol[1]. The list is terminated
4047** by an entry with azCol[i]==0.
4048*/
4049static char **tableColumnList(ShellState *p, const char *zTab){
4050 char **azCol = 0;
4051 sqlite3_stmt *pStmt;
4052 char *zSql;
4053 int nCol = 0;
4054 int nAlloc = 0;
4055 int nPK = 0; /* Number of PRIMARY KEY columns seen */
4056 int isIPK = 0; /* True if one PRIMARY KEY column of type INTEGER */
4057 int preserveRowid = ShellHasFlag(p, SHFLG_PreserveRowid);
4058 int rc;
4059
4060 zSql = sqlite3_mprintf("PRAGMA table_info=%Q", zTab);
drhe3e25652021-12-16 13:29:28 +00004061 shell_check_oom(zSql);
drh2ce15c32017-07-11 13:34:40 +00004062 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
4063 sqlite3_free(zSql);
4064 if( rc ) return 0;
4065 while( sqlite3_step(pStmt)==SQLITE_ROW ){
4066 if( nCol>=nAlloc-2 ){
4067 nAlloc = nAlloc*2 + nCol + 10;
4068 azCol = sqlite3_realloc(azCol, nAlloc*sizeof(azCol[0]));
drhe3e25652021-12-16 13:29:28 +00004069 shell_check_oom(azCol);
drh2ce15c32017-07-11 13:34:40 +00004070 }
4071 azCol[++nCol] = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 1));
drhe3e25652021-12-16 13:29:28 +00004072 shell_check_oom(azCol[nCol]);
drh2ce15c32017-07-11 13:34:40 +00004073 if( sqlite3_column_int(pStmt, 5) ){
4074 nPK++;
4075 if( nPK==1
4076 && sqlite3_stricmp((const char*)sqlite3_column_text(pStmt,2),
4077 "INTEGER")==0
4078 ){
4079 isIPK = 1;
4080 }else{
4081 isIPK = 0;
4082 }
4083 }
4084 }
4085 sqlite3_finalize(pStmt);
drh4c6cddc2017-10-12 10:28:30 +00004086 if( azCol==0 ) return 0;
drh2ce15c32017-07-11 13:34:40 +00004087 azCol[0] = 0;
4088 azCol[nCol+1] = 0;
4089
4090 /* The decision of whether or not a rowid really needs to be preserved
4091 ** is tricky. We never need to preserve a rowid for a WITHOUT ROWID table
4092 ** or a table with an INTEGER PRIMARY KEY. We are unable to preserve
4093 ** rowids on tables where the rowid is inaccessible because there are other
4094 ** columns in the table named "rowid", "_rowid_", and "oid".
4095 */
4096 if( preserveRowid && isIPK ){
4097 /* If a single PRIMARY KEY column with type INTEGER was seen, then it
4098 ** might be an alise for the ROWID. But it might also be a WITHOUT ROWID
4099 ** table or a INTEGER PRIMARY KEY DESC column, neither of which are
4100 ** ROWID aliases. To distinguish these cases, check to see if
4101 ** there is a "pk" entry in "PRAGMA index_list". There will be
4102 ** no "pk" index if the PRIMARY KEY really is an alias for the ROWID.
4103 */
4104 zSql = sqlite3_mprintf("SELECT 1 FROM pragma_index_list(%Q)"
4105 " WHERE origin='pk'", zTab);
drhe3e25652021-12-16 13:29:28 +00004106 shell_check_oom(zSql);
drh2ce15c32017-07-11 13:34:40 +00004107 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
4108 sqlite3_free(zSql);
4109 if( rc ){
4110 freeColumnList(azCol);
4111 return 0;
4112 }
4113 rc = sqlite3_step(pStmt);
4114 sqlite3_finalize(pStmt);
4115 preserveRowid = rc==SQLITE_ROW;
4116 }
4117 if( preserveRowid ){
4118 /* Only preserve the rowid if we can find a name to use for the
4119 ** rowid */
4120 static char *azRowid[] = { "rowid", "_rowid_", "oid" };
4121 int i, j;
4122 for(j=0; j<3; j++){
4123 for(i=1; i<=nCol; i++){
4124 if( sqlite3_stricmp(azRowid[j],azCol[i])==0 ) break;
4125 }
4126 if( i>nCol ){
4127 /* At this point, we know that azRowid[j] is not the name of any
4128 ** ordinary column in the table. Verify that azRowid[j] is a valid
4129 ** name for the rowid before adding it to azCol[0]. WITHOUT ROWID
4130 ** tables will fail this last check */
4131 rc = sqlite3_table_column_metadata(p->db,0,zTab,azRowid[j],0,0,0,0,0);
4132 if( rc==SQLITE_OK ) azCol[0] = azRowid[j];
4133 break;
4134 }
4135 }
4136 }
4137 return azCol;
4138}
4139
4140/*
4141** Toggle the reverse_unordered_selects setting.
4142*/
4143static void toggleSelectOrder(sqlite3 *db){
4144 sqlite3_stmt *pStmt = 0;
4145 int iSetting = 0;
4146 char zStmt[100];
4147 sqlite3_prepare_v2(db, "PRAGMA reverse_unordered_selects", -1, &pStmt, 0);
4148 if( sqlite3_step(pStmt)==SQLITE_ROW ){
4149 iSetting = sqlite3_column_int(pStmt, 0);
4150 }
4151 sqlite3_finalize(pStmt);
4152 sqlite3_snprintf(sizeof(zStmt), zStmt,
4153 "PRAGMA reverse_unordered_selects(%d)", !iSetting);
4154 sqlite3_exec(db, zStmt, 0, 0, 0);
4155}
4156
4157/*
4158** This is a different callback routine used for dumping the database.
4159** Each row received by this callback consists of a table name,
4160** the table type ("index" or "table") and SQL to create the table.
4161** This routine should print text sufficient to recreate the table.
4162*/
4163static int dump_callback(void *pArg, int nArg, char **azArg, char **azNotUsed){
4164 int rc;
4165 const char *zTable;
4166 const char *zType;
4167 const char *zSql;
4168 ShellState *p = (ShellState *)pArg;
mistachkina00a0162020-10-18 18:35:34 +00004169 int dataOnly;
4170 int noSys;
drh2ce15c32017-07-11 13:34:40 +00004171
4172 UNUSED_PARAMETER(azNotUsed);
drhb3c45232017-08-28 14:33:27 +00004173 if( nArg!=3 || azArg==0 ) return 0;
drh2ce15c32017-07-11 13:34:40 +00004174 zTable = azArg[0];
4175 zType = azArg[1];
4176 zSql = azArg[2];
drhd5ca2c42022-10-25 13:42:10 +00004177 if( zTable==0 ) return 0;
4178 if( zType==0 ) return 0;
mistachkina00a0162020-10-18 18:35:34 +00004179 dataOnly = (p->shellFlgs & SHFLG_DumpDataOnly)!=0;
4180 noSys = (p->shellFlgs & SHFLG_DumpNoSys)!=0;
drh2ce15c32017-07-11 13:34:40 +00004181
drhbf70f1b2022-10-19 18:04:42 +00004182 if( cli_strcmp(zTable, "sqlite_sequence")==0 && !noSys ){
drhc1962192020-10-12 16:54:28 +00004183 if( !dataOnly ) raw_printf(p->out, "DELETE FROM sqlite_sequence;\n");
4184 }else if( sqlite3_strglob("sqlite_stat?", zTable)==0 && !noSys ){
4185 if( !dataOnly ) raw_printf(p->out, "ANALYZE sqlite_schema;\n");
drhbf70f1b2022-10-19 18:04:42 +00004186 }else if( cli_strncmp(zTable, "sqlite_", 7)==0 ){
drh2ce15c32017-07-11 13:34:40 +00004187 return 0;
drhc1962192020-10-12 16:54:28 +00004188 }else if( dataOnly ){
4189 /* no-op */
drhbf70f1b2022-10-19 18:04:42 +00004190 }else if( cli_strncmp(zSql, "CREATE VIRTUAL TABLE", 20)==0 ){
drh2ce15c32017-07-11 13:34:40 +00004191 char *zIns;
4192 if( !p->writableSchema ){
4193 raw_printf(p->out, "PRAGMA writable_schema=ON;\n");
4194 p->writableSchema = 1;
4195 }
4196 zIns = sqlite3_mprintf(
drh067b92b2020-06-19 15:24:12 +00004197 "INSERT INTO sqlite_schema(type,name,tbl_name,rootpage,sql)"
drh2ce15c32017-07-11 13:34:40 +00004198 "VALUES('table','%q','%q',0,'%q');",
4199 zTable, zTable, zSql);
drhe3e25652021-12-16 13:29:28 +00004200 shell_check_oom(zIns);
drh2ce15c32017-07-11 13:34:40 +00004201 utf8_printf(p->out, "%s\n", zIns);
4202 sqlite3_free(zIns);
4203 return 0;
4204 }else{
4205 printSchemaLine(p->out, zSql, ";\n");
4206 }
4207
drhbf70f1b2022-10-19 18:04:42 +00004208 if( cli_strcmp(zType, "table")==0 ){
drh2ce15c32017-07-11 13:34:40 +00004209 ShellText sSelect;
4210 ShellText sTable;
4211 char **azCol;
4212 int i;
4213 char *savedDestTable;
4214 int savedMode;
4215
4216 azCol = tableColumnList(p, zTable);
4217 if( azCol==0 ){
4218 p->nErr++;
4219 return 0;
4220 }
4221
4222 /* Always quote the table name, even if it appears to be pure ascii,
4223 ** in case it is a keyword. Ex: INSERT INTO "table" ... */
4224 initText(&sTable);
4225 appendText(&sTable, zTable, quoteChar(zTable));
4226 /* If preserving the rowid, add a column list after the table name.
4227 ** In other words: "INSERT INTO tab(rowid,a,b,c,...) VALUES(...)"
4228 ** instead of the usual "INSERT INTO tab VALUES(...)".
4229 */
4230 if( azCol[0] ){
4231 appendText(&sTable, "(", 0);
4232 appendText(&sTable, azCol[0], 0);
4233 for(i=1; azCol[i]; i++){
4234 appendText(&sTable, ",", 0);
4235 appendText(&sTable, azCol[i], quoteChar(azCol[i]));
4236 }
4237 appendText(&sTable, ")", 0);
4238 }
4239
4240 /* Build an appropriate SELECT statement */
4241 initText(&sSelect);
4242 appendText(&sSelect, "SELECT ", 0);
4243 if( azCol[0] ){
4244 appendText(&sSelect, azCol[0], 0);
4245 appendText(&sSelect, ",", 0);
4246 }
4247 for(i=1; azCol[i]; i++){
4248 appendText(&sSelect, azCol[i], quoteChar(azCol[i]));
4249 if( azCol[i+1] ){
4250 appendText(&sSelect, ",", 0);
4251 }
4252 }
4253 freeColumnList(azCol);
4254 appendText(&sSelect, " FROM ", 0);
4255 appendText(&sSelect, zTable, quoteChar(zTable));
4256
4257 savedDestTable = p->zDestTable;
4258 savedMode = p->mode;
4259 p->zDestTable = sTable.z;
4260 p->mode = p->cMode = MODE_Insert;
drha10b9992018-03-09 15:24:33 +00004261 rc = shell_exec(p, sSelect.z, 0);
drh2ce15c32017-07-11 13:34:40 +00004262 if( (rc&0xff)==SQLITE_CORRUPT ){
4263 raw_printf(p->out, "/****** CORRUPTION ERROR *******/\n");
4264 toggleSelectOrder(p->db);
drha10b9992018-03-09 15:24:33 +00004265 shell_exec(p, sSelect.z, 0);
drh2ce15c32017-07-11 13:34:40 +00004266 toggleSelectOrder(p->db);
4267 }
4268 p->zDestTable = savedDestTable;
4269 p->mode = savedMode;
4270 freeText(&sTable);
4271 freeText(&sSelect);
4272 if( rc ) p->nErr++;
4273 }
4274 return 0;
4275}
4276
4277/*
4278** Run zQuery. Use dump_callback() as the callback routine so that
4279** the contents of the query are output as SQL statements.
4280**
4281** If we get a SQLITE_CORRUPT error, rerun the query after appending
4282** "ORDER BY rowid DESC" to the end.
4283*/
4284static int run_schema_dump_query(
4285 ShellState *p,
4286 const char *zQuery
4287){
4288 int rc;
4289 char *zErr = 0;
4290 rc = sqlite3_exec(p->db, zQuery, dump_callback, p, &zErr);
4291 if( rc==SQLITE_CORRUPT ){
4292 char *zQ2;
4293 int len = strlen30(zQuery);
4294 raw_printf(p->out, "/****** CORRUPTION ERROR *******/\n");
4295 if( zErr ){
4296 utf8_printf(p->out, "/****** %s ******/\n", zErr);
4297 sqlite3_free(zErr);
4298 zErr = 0;
4299 }
4300 zQ2 = malloc( len+100 );
4301 if( zQ2==0 ) return rc;
4302 sqlite3_snprintf(len+100, zQ2, "%s ORDER BY rowid DESC", zQuery);
4303 rc = sqlite3_exec(p->db, zQ2, dump_callback, p, &zErr);
4304 if( rc ){
4305 utf8_printf(p->out, "/****** ERROR: %s ******/\n", zErr);
4306 }else{
4307 rc = SQLITE_CORRUPT;
4308 }
4309 sqlite3_free(zErr);
4310 free(zQ2);
4311 }
4312 return rc;
4313}
4314
4315/*
drh98aa2ab2018-09-26 16:53:51 +00004316** Text of help messages.
4317**
4318** The help text for each individual command begins with a line that starts
stephan02520cc2022-05-18 22:58:34 +00004319** with ".". Subsequent lines are supplemental information.
drh98aa2ab2018-09-26 16:53:51 +00004320**
4321** There must be two or more spaces between the end of the command and the
4322** start of the description of what that command does.
drh2ce15c32017-07-11 13:34:40 +00004323*/
drh98aa2ab2018-09-26 16:53:51 +00004324static const char *(azHelp[]) = {
stephan02520cc2022-05-18 22:58:34 +00004325#if defined(SQLITE_HAVE_ZLIB) && !defined(SQLITE_OMIT_VIRTUALTABLE) \
stephan4413ec72022-07-12 15:53:02 +00004326 && !defined(SQLITE_SHELL_FIDDLE)
drh98aa2ab2018-09-26 16:53:51 +00004327 ".archive ... Manage SQL archives",
4328 " Each command must have exactly one of the following options:",
4329 " -c, --create Create a new archive",
drhe2754c12019-08-26 12:50:01 +00004330 " -u, --update Add or update files with changed mtime",
4331 " -i, --insert Like -u but always add even if unchanged",
larrybr47061b92021-11-01 17:22:52 +00004332 " -r, --remove Remove files from archive",
drh98aa2ab2018-09-26 16:53:51 +00004333 " -t, --list List contents of archive",
4334 " -x, --extract Extract files from archive",
4335 " Optional arguments:",
4336 " -v, --verbose Print each filename as it is processed",
drhe2754c12019-08-26 12:50:01 +00004337 " -f FILE, --file FILE Use archive FILE (default is current db)",
4338 " -a FILE, --append FILE Open FILE using the apndvfs VFS",
4339 " -C DIR, --directory DIR Read/extract files from directory DIR",
larrybr8f09f4b2021-11-02 00:18:11 +00004340 " -g, --glob Use glob matching for names in archive",
drh98aa2ab2018-09-26 16:53:51 +00004341 " -n, --dryrun Show the SQL that would have occurred",
4342 " Examples:",
drhe2754c12019-08-26 12:50:01 +00004343 " .ar -cf ARCHIVE foo bar # Create ARCHIVE from files foo and bar",
4344 " .ar -tf ARCHIVE # List members of ARCHIVE",
4345 " .ar -xvf ARCHIVE # Verbosely extract files from ARCHIVE",
drh98aa2ab2018-09-26 16:53:51 +00004346 " See also:",
larrybrbd0d62c2021-06-13 08:23:28 +00004347 " http://sqlite.org/cli.html#sqlite_archive_support",
drhe37c0e12018-01-06 19:19:50 +00004348#endif
drh2ce15c32017-07-11 13:34:40 +00004349#ifndef SQLITE_OMIT_AUTHORIZATION
drh98aa2ab2018-09-26 16:53:51 +00004350 ".auth ON|OFF Show authorizer callbacks",
drh2ce15c32017-07-11 13:34:40 +00004351#endif
stephan4413ec72022-07-12 15:53:02 +00004352#ifndef SQLITE_SHELL_FIDDLE
drh98aa2ab2018-09-26 16:53:51 +00004353 ".backup ?DB? FILE Backup DB (default \"main\") to FILE",
larrybra7919ad2022-02-19 21:25:48 +00004354 " Options:",
drh98aa2ab2018-09-26 16:53:51 +00004355 " --append Use the appendvfs",
drhe2754c12019-08-26 12:50:01 +00004356 " --async Write to FILE without journal and fsync()",
stephan02520cc2022-05-18 22:58:34 +00004357#endif
drh98aa2ab2018-09-26 16:53:51 +00004358 ".bail on|off Stop after hitting an error. Default OFF",
4359 ".binary on|off Turn binary output on or off. Default OFF",
stephan4413ec72022-07-12 15:53:02 +00004360#ifndef SQLITE_SHELL_FIDDLE
drh98aa2ab2018-09-26 16:53:51 +00004361 ".cd DIRECTORY Change the working directory to DIRECTORY",
stephan1c0dcec2022-05-19 21:56:50 +00004362#endif
drh98aa2ab2018-09-26 16:53:51 +00004363 ".changes on|off Show number of rows changed by SQL",
stephan4413ec72022-07-12 15:53:02 +00004364#ifndef SQLITE_SHELL_FIDDLE
stephane26d1622022-05-19 22:04:23 +00004365 ".check GLOB Fail if output since .testcase does not match",
drh98aa2ab2018-09-26 16:53:51 +00004366 ".clone NEWDB Clone data into NEWDB from the existing database",
stephan1c0dcec2022-05-19 21:56:50 +00004367#endif
drh37407122021-07-23 18:43:58 +00004368 ".connection [close] [#] Open or close an auxiliary database connection",
drh98aa2ab2018-09-26 16:53:51 +00004369 ".databases List names and files of attached databases",
4370 ".dbconfig ?op? ?val? List or change sqlite3_db_config() options",
stephan3d420832022-10-27 03:56:01 +00004371#if SQLITE_SHELL_HAVE_RECOVER
drh98aa2ab2018-09-26 16:53:51 +00004372 ".dbinfo ?DB? Show status information about the database",
larrybrf3d6e8f2022-06-05 22:58:40 +00004373#endif
larrybr7bdbe592021-03-15 12:56:00 +00004374 ".dump ?OBJECTS? Render database content as SQL",
drheb7f2a02018-09-26 18:02:32 +00004375 " Options:",
drhc1962192020-10-12 16:54:28 +00004376 " --data-only Output only INSERT statements",
drheb7f2a02018-09-26 18:02:32 +00004377 " --newlines Allow unescaped newline characters in output",
drhc1962192020-10-12 16:54:28 +00004378 " --nosys Omit system tables (ex: \"sqlite_stat1\")",
4379 " --preserve-rowids Include ROWID values in the output",
larrybr7bdbe592021-03-15 12:56:00 +00004380 " OBJECTS is a LIKE pattern for tables, indexes, triggers or views to dump",
drh8e9297f2020-03-25 12:50:13 +00004381 " Additional LIKE patterns can be given in subsequent arguments",
drh98aa2ab2018-09-26 16:53:51 +00004382 ".echo on|off Turn command echo on or off",
drhb4e50392019-01-26 15:40:04 +00004383 ".eqp on|off|full|... Enable or disable automatic EXPLAIN QUERY PLAN",
4384 " Other Modes:",
4385#ifdef SQLITE_DEBUG
4386 " test Show raw EXPLAIN QUERY PLAN output",
drhe2754c12019-08-26 12:50:01 +00004387 " trace Like \"full\" but enable \"PRAGMA vdbe_trace\"",
drhb4e50392019-01-26 15:40:04 +00004388#endif
4389 " trigger Like \"full\" but also show trigger bytecode",
stephan4413ec72022-07-12 15:53:02 +00004390#ifndef SQLITE_SHELL_FIDDLE
drhe2754c12019-08-26 12:50:01 +00004391 ".excel Display the output of next command in spreadsheet",
drh7a431002020-04-18 14:12:00 +00004392 " --bom Put a UTF8 byte-order mark on intermediate file",
stephan02520cc2022-05-18 22:58:34 +00004393#endif
stephan4413ec72022-07-12 15:53:02 +00004394#ifndef SQLITE_SHELL_FIDDLE
drheb7f2a02018-09-26 18:02:32 +00004395 ".exit ?CODE? Exit this program with return-code CODE",
stephan02520cc2022-05-18 22:58:34 +00004396#endif
drhe2754c12019-08-26 12:50:01 +00004397 ".expert EXPERIMENTAL. Suggest indexes for queries",
drh978256f2019-11-02 00:00:14 +00004398 ".explain ?on|off|auto? Change the EXPLAIN formatting mode. Default: auto",
drhd985f722019-06-05 14:29:53 +00004399 ".filectrl CMD ... Run various sqlite3_file_control() operations",
drh541ef2c2020-04-20 16:21:30 +00004400 " --schema SCHEMA Use SCHEMA instead of \"main\"",
4401 " --help Show CMD details",
drh98aa2ab2018-09-26 16:53:51 +00004402 ".fullschema ?--indent? Show schema and the content of sqlite_stat tables",
4403 ".headers on|off Turn display of headers on or off",
4404 ".help ?-all? ?PATTERN? Show help text for PATTERN",
stephan4413ec72022-07-12 15:53:02 +00004405#ifndef SQLITE_SHELL_FIDDLE
drh98aa2ab2018-09-26 16:53:51 +00004406 ".import FILE TABLE Import data from FILE into TABLE",
drhccb37812020-03-09 15:39:39 +00004407 " Options:",
4408 " --ascii Use \\037 and \\036 as column and row separators",
4409 " --csv Use , and \\n as column and row separators",
4410 " --skip N Skip the first N rows of input",
larrybr738d7b92022-01-13 21:22:54 +00004411 " --schema S Target table to be S.TABLE",
drhccb37812020-03-09 15:39:39 +00004412 " -v \"Verbose\" - increase auxiliary output",
4413 " Notes:",
4414 " * If TABLE does not exist, it is created. The first row of input",
4415 " determines the column names.",
4416 " * If neither --csv or --ascii are used, the input mode is derived",
4417 " from the \".mode\" output mode",
4418 " * If FILE begins with \"|\" then it is a command that generates the",
4419 " input text.",
stephan29f24582022-05-19 00:38:34 +00004420#endif
drh2ce15c32017-07-11 13:34:40 +00004421#ifndef SQLITE_OMIT_TEST_CONTROL
drh98aa2ab2018-09-26 16:53:51 +00004422 ".imposter INDEX TABLE Create imposter table TABLE on index INDEX",
drh2ce15c32017-07-11 13:34:40 +00004423#endif
drh98aa2ab2018-09-26 16:53:51 +00004424 ".indexes ?TABLE? Show names of indexes",
4425 " If TABLE is specified, only show indexes for",
4426 " tables matching TABLE using the LIKE operator.",
drh2ce15c32017-07-11 13:34:40 +00004427#ifdef SQLITE_ENABLE_IOTRACE
drh98aa2ab2018-09-26 16:53:51 +00004428 ".iotrace FILE Enable I/O diagnostic logging to FILE",
drh2ce15c32017-07-11 13:34:40 +00004429#endif
drh98aa2ab2018-09-26 16:53:51 +00004430 ".limit ?LIMIT? ?VAL? Display or change the value of an SQLITE_LIMIT",
4431 ".lint OPTIONS Report potential schema issues.",
4432 " Options:",
4433 " fkey-indexes Find missing foreign key indexes",
stephan4413ec72022-07-12 15:53:02 +00004434#if !defined(SQLITE_OMIT_LOAD_EXTENSION) && !defined(SQLITE_SHELL_FIDDLE)
drh98aa2ab2018-09-26 16:53:51 +00004435 ".load FILE ?ENTRY? Load an extension library",
drh2ce15c32017-07-11 13:34:40 +00004436#endif
stephan4413ec72022-07-12 15:53:02 +00004437#ifndef SQLITE_SHELL_FIDDLE
drh98aa2ab2018-09-26 16:53:51 +00004438 ".log FILE|off Turn logging on or off. FILE can be stderr/stdout",
stephan618a3752022-05-19 10:24:50 +00004439#endif
drh47741b82022-01-31 22:14:53 +00004440 ".mode MODE ?OPTIONS? Set output mode",
drh98aa2ab2018-09-26 16:53:51 +00004441 " MODE is one of:",
drhe40f2862022-01-31 14:14:29 +00004442 " ascii Columns/rows delimited by 0x1F and 0x1E",
4443 " box Tables using unicode box-drawing characters",
4444 " csv Comma-separated values",
4445 " column Output in columns. (See .width)",
4446 " html HTML <table> code",
4447 " insert SQL insert statements for TABLE",
4448 " json Results in a JSON array",
4449 " line One value per line",
4450 " list Values delimited by \"|\"",
4451 " markdown Markdown table format",
drh1f41a8c2022-10-24 11:10:40 +00004452 " qbox Shorthand for \"box --wrap 60 --quote\"",
drhe40f2862022-01-31 14:14:29 +00004453 " quote Escape answers as for SQL",
4454 " table ASCII-art table",
4455 " tabs Tab-separated values",
4456 " tcl TCL list elements",
larrybrcc4d55c2022-02-01 02:50:45 +00004457 " OPTIONS: (for columnar modes or insert mode):",
4458 " --wrap N Wrap output lines to no longer than N characters",
drhca1776b2022-02-01 12:28:17 +00004459 " --wordwrap B Wrap or not at word boundaries per B (on/off)",
4460 " --ww Shorthand for \"--wordwrap 1\"",
larrybrcc4d55c2022-02-01 02:50:45 +00004461 " --quote Quote output text as SQL literals",
4462 " --noquote Do not quote output text",
4463 " TABLE The name of SQL table used for \"insert\" mode",
stephan4413ec72022-07-12 15:53:02 +00004464#ifndef SQLITE_SHELL_FIDDLE
larrybrcc4d55c2022-02-01 02:50:45 +00004465 ".nonce STRING Suspend safe mode for one command if nonce matches",
stephane26d1622022-05-19 22:04:23 +00004466#endif
drh98aa2ab2018-09-26 16:53:51 +00004467 ".nullvalue STRING Use STRING in place of NULL values",
stephan4413ec72022-07-12 15:53:02 +00004468#ifndef SQLITE_SHELL_FIDDLE
drh7a431002020-04-18 14:12:00 +00004469 ".once ?OPTIONS? ?FILE? Output for the next SQL command only to FILE",
drh98aa2ab2018-09-26 16:53:51 +00004470 " If FILE begins with '|' then open as a pipe",
drh7a431002020-04-18 14:12:00 +00004471 " --bom Put a UTF8 byte-order mark at the beginning",
4472 " -e Send output to the system text editor",
4473 " -x Send output as CSV to a spreadsheet (same as \".excel\")",
stephande1e02e2022-05-24 19:01:21 +00004474 /* Note that .open is (partially) available in WASM builds but is
stephan085c5c62022-05-25 04:35:22 +00004475 ** currently only intended to be used by the fiddle tool, not
4476 ** end users, so is "undocumented." */
drh98aa2ab2018-09-26 16:53:51 +00004477 ".open ?OPTIONS? ?FILE? Close existing database and reopen FILE",
4478 " Options:",
drh60f34ae2018-10-30 13:19:49 +00004479 " --append Use appendvfs to append database to the end of FILE",
stephan02520cc2022-05-18 22:58:34 +00004480#endif
drh8d889af2021-05-08 17:18:23 +00004481#ifndef SQLITE_OMIT_DESERIALIZE
drhd10c3ca2021-05-08 11:57:35 +00004482 " --deserialize Load into memory using sqlite3_deserialize()",
drhe2754c12019-08-26 12:50:01 +00004483 " --hexdb Load the output of \"dbtotxt\" as an in-memory db",
drh6ca64482019-01-22 16:06:20 +00004484 " --maxsize N Maximum size for --hexdb or --deserialized database",
drha751f392018-10-30 15:31:22 +00004485#endif
drh60f34ae2018-10-30 13:19:49 +00004486 " --new Initialize FILE to an empty database",
drh0933aad2019-11-18 17:46:38 +00004487 " --nofollow Do not follow symbolic links",
drh60f34ae2018-10-30 13:19:49 +00004488 " --readonly Open FILE readonly",
4489 " --zip FILE is a ZIP archive",
stephan4413ec72022-07-12 15:53:02 +00004490#ifndef SQLITE_SHELL_FIDDLE
drh98aa2ab2018-09-26 16:53:51 +00004491 ".output ?FILE? Send output to FILE or stdout if FILE is omitted",
drh7a431002020-04-18 14:12:00 +00004492 " If FILE begins with '|' then open it as a pipe.",
4493 " Options:",
4494 " --bom Prefix output with a UTF8 byte-order mark",
4495 " -e Send output to the system text editor",
4496 " -x Send output as CSV to a spreadsheet",
stephande1e02e2022-05-24 19:01:21 +00004497#endif
drh9cb02642019-02-28 20:10:52 +00004498 ".parameter CMD ... Manage SQL parameter bindings",
4499 " clear Erase all bindings",
4500 " init Initialize the TEMP table that holds bindings",
4501 " list List the current parameter bindings",
4502 " set PARAMETER VALUE Given SQL parameter PARAMETER a value of VALUE",
drhe2754c12019-08-26 12:50:01 +00004503 " PARAMETER should start with one of: $ : @ ?",
drh9cb02642019-02-28 20:10:52 +00004504 " unset PARAMETER Remove PARAMETER from the binding table",
drh98aa2ab2018-09-26 16:53:51 +00004505 ".print STRING... Print literal STRING",
drh569b1d92019-02-05 20:51:41 +00004506#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
drh3f83f592019-02-04 14:53:18 +00004507 ".progress N Invoke progress handler after every N opcodes",
4508 " --limit N Interrupt after N progress callbacks",
4509 " --once Do no more than one progress interrupt",
4510 " --quiet|-q No output except at interrupts",
4511 " --reset Reset the count for each input and interrupt",
drh569b1d92019-02-05 20:51:41 +00004512#endif
drh98aa2ab2018-09-26 16:53:51 +00004513 ".prompt MAIN CONTINUE Replace the standard prompts",
stephan4413ec72022-07-12 15:53:02 +00004514#ifndef SQLITE_SHELL_FIDDLE
drh98aa2ab2018-09-26 16:53:51 +00004515 ".quit Exit this program",
larrybra2ba25b2021-12-28 05:08:38 +00004516 ".read FILE Read input from FILE or command output",
4517 " If FILE begins with \"|\", it is a command that generates the input.",
stephan02520cc2022-05-18 22:58:34 +00004518#endif
stephan3d420832022-10-27 03:56:01 +00004519#if SQLITE_SHELL_HAVE_RECOVER
dan42ebb012019-04-27 18:47:03 +00004520 ".recover Recover as much data as possible from corrupt db.",
danf7fea5b2022-10-27 18:19:45 +00004521 " --ignore-freelist Ignore pages that appear to be on db freelist",
drhe2754c12019-08-26 12:50:01 +00004522 " --lost-and-found TABLE Alternative name for the lost-and-found table",
dan8cce6b82019-09-14 16:44:51 +00004523 " --no-rowids Do not attempt to recover rowid values",
4524 " that are not also INTEGER PRIMARY KEYs",
dan1b162162019-04-27 20:15:15 +00004525#endif
stephan4413ec72022-07-12 15:53:02 +00004526#ifndef SQLITE_SHELL_FIDDLE
drh98aa2ab2018-09-26 16:53:51 +00004527 ".restore ?DB? FILE Restore content of DB (default \"main\") from FILE",
larrybra7919ad2022-02-19 21:25:48 +00004528 ".save ?OPTIONS? FILE Write database to FILE (an alias for .backup ...)",
stephan02520cc2022-05-18 22:58:34 +00004529#endif
drh98aa2ab2018-09-26 16:53:51 +00004530 ".scanstats on|off Turn sqlite3_stmt_scanstatus() metrics on or off",
4531 ".schema ?PATTERN? Show the CREATE statements matching PATTERN",
drhbbb29ec2020-10-12 14:56:47 +00004532 " Options:",
4533 " --indent Try to pretty-print the schema",
4534 " --nosys Omit objects whose names start with \"sqlite_\"",
drheb7f2a02018-09-26 18:02:32 +00004535 ".selftest ?OPTIONS? Run tests defined in the SELFTEST table",
4536 " Options:",
4537 " --init Create a new SELFTEST table",
4538 " -v Verbose output",
drh98aa2ab2018-09-26 16:53:51 +00004539 ".separator COL ?ROW? Change the column and row separators",
drh2ce15c32017-07-11 13:34:40 +00004540#if defined(SQLITE_ENABLE_SESSION)
drheb7f2a02018-09-26 18:02:32 +00004541 ".session ?NAME? CMD ... Create or control sessions",
4542 " Subcommands:",
4543 " attach TABLE Attach TABLE",
4544 " changeset FILE Write a changeset into FILE",
4545 " close Close one session",
4546 " enable ?BOOLEAN? Set or query the enable bit",
4547 " filter GLOB... Reject tables matching GLOBs",
4548 " indirect ?BOOLEAN? Mark or query the indirect status",
4549 " isempty Query whether the session is empty",
4550 " list List currently open session names",
4551 " open DB NAME Open a new session on DB",
4552 " patchset FILE Write a patchset into FILE",
4553 " If ?NAME? is omitted, the first defined session is used.",
drh2ce15c32017-07-11 13:34:40 +00004554#endif
drheb7f2a02018-09-26 18:02:32 +00004555 ".sha3sum ... Compute a SHA3 hash of database content",
4556 " Options:",
drh067b92b2020-06-19 15:24:12 +00004557 " --schema Also hash the sqlite_schema table",
drheb7f2a02018-09-26 18:02:32 +00004558 " --sha3-224 Use the sha3-224 algorithm",
drhe2754c12019-08-26 12:50:01 +00004559 " --sha3-256 Use the sha3-256 algorithm (default)",
drheb7f2a02018-09-26 18:02:32 +00004560 " --sha3-384 Use the sha3-384 algorithm",
4561 " --sha3-512 Use the sha3-512 algorithm",
4562 " Any other argument is a LIKE pattern for tables to hash",
stephan4413ec72022-07-12 15:53:02 +00004563#if !defined(SQLITE_NOHAVE_SYSTEM) && !defined(SQLITE_SHELL_FIDDLE)
drh98aa2ab2018-09-26 16:53:51 +00004564 ".shell CMD ARGS... Run CMD ARGS... in a system shell",
drh04a28c32018-01-31 01:38:44 +00004565#endif
drh98aa2ab2018-09-26 16:53:51 +00004566 ".show Show the current values for various settings",
drha6e6cf22021-01-09 19:10:04 +00004567 ".stats ?ARG? Show stats or turn stats on or off",
4568 " off Turn off automatic stat display",
4569 " on Turn on automatic stat display",
4570 " stmt Show statement stats",
4571 " vmstep Show the virtual machine step count only",
stephan4413ec72022-07-12 15:53:02 +00004572#if !defined(SQLITE_NOHAVE_SYSTEM) && !defined(SQLITE_SHELL_FIDDLE)
drh98aa2ab2018-09-26 16:53:51 +00004573 ".system CMD ARGS... Run CMD ARGS... in a system shell",
drh04a28c32018-01-31 01:38:44 +00004574#endif
drh98aa2ab2018-09-26 16:53:51 +00004575 ".tables ?TABLE? List names of tables matching LIKE pattern TABLE",
stephan4413ec72022-07-12 15:53:02 +00004576#ifndef SQLITE_SHELL_FIDDLE
drh98aa2ab2018-09-26 16:53:51 +00004577 ".testcase NAME Begin redirecting output to 'testcase-out.txt'",
stephan02520cc2022-05-18 22:58:34 +00004578#endif
drhd985f722019-06-05 14:29:53 +00004579 ".testctrl CMD ... Run various sqlite3_test_control() operations",
4580 " Run \".testctrl\" with no arguments for details",
drh98aa2ab2018-09-26 16:53:51 +00004581 ".timeout MS Try opening locked tables for MS milliseconds",
4582 ".timer on|off Turn SQL timer on or off",
drh707821f2018-12-05 13:39:06 +00004583#ifndef SQLITE_OMIT_TRACE
4584 ".trace ?OPTIONS? Output each SQL statement as it is run",
4585 " FILE Send output to FILE",
4586 " stdout Send output to stdout",
4587 " stderr Send output to stderr",
4588 " off Disable tracing",
4589 " --expanded Expand query parameters",
4590#ifdef SQLITE_ENABLE_NORMALIZE
4591 " --normalized Normal the SQL statements",
4592#endif
4593 " --plain Show SQL as it is input",
4594 " --stmt Trace statement execution (SQLITE_TRACE_STMT)",
4595 " --profile Profile statements (SQLITE_TRACE_PROFILE)",
4596 " --row Trace each row (SQLITE_TRACE_ROW)",
4597 " --close Trace connection close (SQLITE_TRACE_CLOSE)",
4598#endif /* SQLITE_OMIT_TRACE */
drhcc5979d2019-08-16 22:58:29 +00004599#ifdef SQLITE_DEBUG
4600 ".unmodule NAME ... Unregister virtual table modules",
drh5df84282019-08-17 19:45:25 +00004601 " --allexcept Unregister everything except those named",
drhcc5979d2019-08-16 22:58:29 +00004602#endif
drh98aa2ab2018-09-26 16:53:51 +00004603 ".vfsinfo ?AUX? Information about the top-level VFS",
4604 ".vfslist List all available VFSes",
4605 ".vfsname ?AUX? Print the name of the VFS stack",
drh7da29a32020-05-29 19:17:20 +00004606 ".width NUM1 NUM2 ... Set minimum column widths for columnar output",
drh98aa2ab2018-09-26 16:53:51 +00004607 " Negative values right-justify",
4608};
4609
4610/*
4611** Output help text.
4612**
4613** zPattern describes the set of commands for which help text is provided.
4614** If zPattern is NULL, then show all commands, but only give a one-line
4615** description of each.
4616**
4617** Return the number of matches.
4618*/
4619static int showHelp(FILE *out, const char *zPattern){
drhe93f8262018-10-11 16:53:37 +00004620 int i = 0;
4621 int j = 0;
drh98aa2ab2018-09-26 16:53:51 +00004622 int n = 0;
4623 char *zPat;
drh488cddf2018-10-06 14:38:17 +00004624 if( zPattern==0
4625 || zPattern[0]=='0'
drhbf70f1b2022-10-19 18:04:42 +00004626 || cli_strcmp(zPattern,"-a")==0
4627 || cli_strcmp(zPattern,"-all")==0
4628 || cli_strcmp(zPattern,"--all")==0
drh488cddf2018-10-06 14:38:17 +00004629 ){
drh98aa2ab2018-09-26 16:53:51 +00004630 /* Show all commands, but only one line per command */
drh488cddf2018-10-06 14:38:17 +00004631 if( zPattern==0 ) zPattern = "";
drh98aa2ab2018-09-26 16:53:51 +00004632 for(i=0; i<ArraySize(azHelp); i++){
drh488cddf2018-10-06 14:38:17 +00004633 if( azHelp[i][0]=='.' || zPattern[0] ){
drh98aa2ab2018-09-26 16:53:51 +00004634 utf8_printf(out, "%s\n", azHelp[i]);
4635 n++;
4636 }
4637 }
4638 }else{
4639 /* Look for commands that for which zPattern is an exact prefix */
4640 zPat = sqlite3_mprintf(".%s*", zPattern);
drhe3e25652021-12-16 13:29:28 +00004641 shell_check_oom(zPat);
drh98aa2ab2018-09-26 16:53:51 +00004642 for(i=0; i<ArraySize(azHelp); i++){
4643 if( sqlite3_strglob(zPat, azHelp[i])==0 ){
4644 utf8_printf(out, "%s\n", azHelp[i]);
drheb7f2a02018-09-26 18:02:32 +00004645 j = i+1;
drh98aa2ab2018-09-26 16:53:51 +00004646 n++;
4647 }
4648 }
4649 sqlite3_free(zPat);
drheb7f2a02018-09-26 18:02:32 +00004650 if( n ){
4651 if( n==1 ){
4652 /* when zPattern is a prefix of exactly one command, then include the
4653 ** details of that command, which should begin at offset j */
4654 while( j<ArraySize(azHelp)-1 && azHelp[j][0]!='.' ){
4655 utf8_printf(out, "%s\n", azHelp[j]);
4656 j++;
4657 }
4658 }
4659 return n;
4660 }
4661 /* Look for commands that contain zPattern anywhere. Show the complete
4662 ** text of all commands that match. */
drh98aa2ab2018-09-26 16:53:51 +00004663 zPat = sqlite3_mprintf("%%%s%%", zPattern);
drhe3e25652021-12-16 13:29:28 +00004664 shell_check_oom(zPat);
drh98aa2ab2018-09-26 16:53:51 +00004665 for(i=0; i<ArraySize(azHelp); i++){
4666 if( azHelp[i][0]=='.' ) j = i;
4667 if( sqlite3_strlike(zPat, azHelp[i], 0)==0 ){
4668 utf8_printf(out, "%s\n", azHelp[j]);
4669 while( j<ArraySize(azHelp)-1 && azHelp[j+1][0]!='.' ){
4670 j++;
4671 utf8_printf(out, "%s\n", azHelp[j]);
4672 }
4673 i = j;
4674 n++;
4675 }
4676 }
4677 sqlite3_free(zPat);
4678 }
4679 return n;
4680}
drh2ce15c32017-07-11 13:34:40 +00004681
drh2ce15c32017-07-11 13:34:40 +00004682/* Forward reference */
drh60379d42018-12-13 18:30:01 +00004683static int process_input(ShellState *p);
drh2ce15c32017-07-11 13:34:40 +00004684
4685/*
4686** Read the content of file zName into memory obtained from sqlite3_malloc64()
4687** and return a pointer to the buffer. The caller is responsible for freeing
4688** the memory.
4689**
4690** If parameter pnByte is not NULL, (*pnByte) is set to the number of bytes
4691** read.
4692**
4693** For convenience, a nul-terminator byte is always appended to the data read
4694** from the file before the buffer is returned. This byte is not included in
4695** the final value of (*pnByte), if applicable.
4696**
4697** NULL is returned if any error is encountered. The final value of *pnByte
4698** is undefined in this case.
4699*/
4700static char *readFile(const char *zName, int *pnByte){
4701 FILE *in = fopen(zName, "rb");
4702 long nIn;
4703 size_t nRead;
4704 char *pBuf;
4705 if( in==0 ) return 0;
4706 fseek(in, 0, SEEK_END);
4707 nIn = ftell(in);
4708 rewind(in);
4709 pBuf = sqlite3_malloc64( nIn+1 );
drh1dbb1472018-10-11 10:37:24 +00004710 if( pBuf==0 ){ fclose(in); return 0; }
drh2ce15c32017-07-11 13:34:40 +00004711 nRead = fread(pBuf, nIn, 1, in);
4712 fclose(in);
4713 if( nRead!=1 ){
4714 sqlite3_free(pBuf);
4715 return 0;
4716 }
4717 pBuf[nIn] = 0;
4718 if( pnByte ) *pnByte = nIn;
4719 return pBuf;
4720}
4721
4722#if defined(SQLITE_ENABLE_SESSION)
4723/*
4724** Close a single OpenSession object and release all of its associated
4725** resources.
4726*/
4727static void session_close(OpenSession *pSession){
4728 int i;
4729 sqlite3session_delete(pSession->p);
4730 sqlite3_free(pSession->zName);
4731 for(i=0; i<pSession->nFilter; i++){
4732 sqlite3_free(pSession->azFilter[i]);
4733 }
4734 sqlite3_free(pSession->azFilter);
4735 memset(pSession, 0, sizeof(OpenSession));
4736}
4737#endif
4738
4739/*
4740** Close all OpenSession objects and release all associated resources.
4741*/
4742#if defined(SQLITE_ENABLE_SESSION)
drh37407122021-07-23 18:43:58 +00004743static void session_close_all(ShellState *p, int i){
4744 int j;
4745 struct AuxDb *pAuxDb = i<0 ? p->pAuxDb : &p->aAuxDb[i];
4746 for(j=0; j<pAuxDb->nSession; j++){
4747 session_close(&pAuxDb->aSession[j]);
drh2ce15c32017-07-11 13:34:40 +00004748 }
drh37407122021-07-23 18:43:58 +00004749 pAuxDb->nSession = 0;
drh2ce15c32017-07-11 13:34:40 +00004750}
4751#else
drh37407122021-07-23 18:43:58 +00004752# define session_close_all(X,Y)
drh2ce15c32017-07-11 13:34:40 +00004753#endif
4754
4755/*
4756** Implementation of the xFilter function for an open session. Omit
4757** any tables named by ".session filter" but let all other table through.
4758*/
4759#if defined(SQLITE_ENABLE_SESSION)
4760static int session_filter(void *pCtx, const char *zTab){
4761 OpenSession *pSession = (OpenSession*)pCtx;
4762 int i;
4763 for(i=0; i<pSession->nFilter; i++){
4764 if( sqlite3_strglob(pSession->azFilter[i], zTab)==0 ) return 0;
4765 }
4766 return 1;
4767}
4768#endif
4769
4770/*
drh1fa6d9f2018-01-06 21:46:01 +00004771** Try to deduce the type of file for zName based on its content. Return
4772** one of the SHELL_OPEN_* constants.
drh1bf208c2018-03-09 21:54:01 +00004773**
4774** If the file does not exist or is empty but its name looks like a ZIP
4775** archive and the dfltZip flag is true, then assume it is a ZIP archive.
4776** Otherwise, assume an ordinary database regardless of the filename if
4777** the type cannot be determined from content.
drh1fa6d9f2018-01-06 21:46:01 +00004778*/
drhfc97c1c2018-05-14 00:41:12 +00004779int deduceDatabaseType(const char *zName, int dfltZip){
drh1fa6d9f2018-01-06 21:46:01 +00004780 FILE *f = fopen(zName, "rb");
4781 size_t n;
4782 int rc = SHELL_OPEN_UNSPEC;
4783 char zBuf[100];
drh1bf208c2018-03-09 21:54:01 +00004784 if( f==0 ){
drhbe4ccb22018-05-17 20:04:24 +00004785 if( dfltZip && sqlite3_strlike("%.zip",zName,0)==0 ){
4786 return SHELL_OPEN_ZIPFILE;
4787 }else{
4788 return SHELL_OPEN_NORMAL;
4789 }
drh1bf208c2018-03-09 21:54:01 +00004790 }
drh2b3c4af2018-10-30 14:36:21 +00004791 n = fread(zBuf, 16, 1, f);
4792 if( n==1 && memcmp(zBuf, "SQLite format 3", 16)==0 ){
4793 fclose(f);
4794 return SHELL_OPEN_NORMAL;
4795 }
drh1fa6d9f2018-01-06 21:46:01 +00004796 fseek(f, -25, SEEK_END);
4797 n = fread(zBuf, 25, 1, f);
4798 if( n==1 && memcmp(zBuf, "Start-Of-SQLite3-", 17)==0 ){
4799 rc = SHELL_OPEN_APPENDVFS;
4800 }else{
4801 fseek(f, -22, SEEK_END);
4802 n = fread(zBuf, 22, 1, f);
4803 if( n==1 && zBuf[0]==0x50 && zBuf[1]==0x4b && zBuf[2]==0x05
4804 && zBuf[3]==0x06 ){
4805 rc = SHELL_OPEN_ZIPFILE;
drh1bf208c2018-03-09 21:54:01 +00004806 }else if( n==0 && dfltZip && sqlite3_strlike("%.zip",zName,0)==0 ){
mistachkina3926f42018-05-14 12:23:04 +00004807 rc = SHELL_OPEN_ZIPFILE;
drh1fa6d9f2018-01-06 21:46:01 +00004808 }
4809 }
4810 fclose(f);
4811 return rc;
4812}
4813
drh8d889af2021-05-08 17:18:23 +00004814#ifndef SQLITE_OMIT_DESERIALIZE
drh33746482018-12-13 15:06:26 +00004815/*
4816** Reconstruct an in-memory database using the output from the "dbtotxt"
drh37407122021-07-23 18:43:58 +00004817** program. Read content from the file in p->aAuxDb[].zDbFilename.
4818** If p->aAuxDb[].zDbFilename is 0, then read from standard input.
drh33746482018-12-13 15:06:26 +00004819*/
4820static unsigned char *readHexDb(ShellState *p, int *pnData){
4821 unsigned char *a = 0;
drh2c8ee022018-12-13 18:59:30 +00004822 int nLine;
drh33746482018-12-13 15:06:26 +00004823 int n = 0;
4824 int pgsz = 0;
4825 int iOffset = 0;
4826 int j, k;
4827 int rc;
4828 FILE *in;
drh37407122021-07-23 18:43:58 +00004829 const char *zDbFilename = p->pAuxDb->zDbFilename;
drh3ea557e2019-04-23 15:30:58 +00004830 unsigned int x[16];
drh2c8ee022018-12-13 18:59:30 +00004831 char zLine[1000];
drh37407122021-07-23 18:43:58 +00004832 if( zDbFilename ){
4833 in = fopen(zDbFilename, "r");
drh33746482018-12-13 15:06:26 +00004834 if( in==0 ){
drh37407122021-07-23 18:43:58 +00004835 utf8_printf(stderr, "cannot open \"%s\" for reading\n", zDbFilename);
drh33746482018-12-13 15:06:26 +00004836 return 0;
4837 }
drh2c8ee022018-12-13 18:59:30 +00004838 nLine = 0;
drh33746482018-12-13 15:06:26 +00004839 }else{
drh60379d42018-12-13 18:30:01 +00004840 in = p->in;
drh2c8ee022018-12-13 18:59:30 +00004841 nLine = p->lineno;
drh5bf46442019-05-03 02:41:36 +00004842 if( in==0 ) in = stdin;
drh33746482018-12-13 15:06:26 +00004843 }
4844 *pnData = 0;
drh2c8ee022018-12-13 18:59:30 +00004845 nLine++;
drh33746482018-12-13 15:06:26 +00004846 if( fgets(zLine, sizeof(zLine), in)==0 ) goto readHexDb_error;
4847 rc = sscanf(zLine, "| size %d pagesize %d", &n, &pgsz);
4848 if( rc!=2 ) goto readHexDb_error;
drh68feae52019-05-09 11:18:41 +00004849 if( n<0 ) goto readHexDb_error;
drh09ea1252019-07-17 15:05:16 +00004850 if( pgsz<512 || pgsz>65536 || (pgsz&(pgsz-1))!=0 ) goto readHexDb_error;
4851 n = (n+pgsz-1)&~(pgsz-1); /* Round n up to the next multiple of pgsz */
drh68feae52019-05-09 11:18:41 +00004852 a = sqlite3_malloc( n ? n : 1 );
drhe3e25652021-12-16 13:29:28 +00004853 shell_check_oom(a);
drh33746482018-12-13 15:06:26 +00004854 memset(a, 0, n);
4855 if( pgsz<512 || pgsz>65536 || (pgsz & (pgsz-1))!=0 ){
4856 utf8_printf(stderr, "invalid pagesize\n");
4857 goto readHexDb_error;
4858 }
drh2c8ee022018-12-13 18:59:30 +00004859 for(nLine++; fgets(zLine, sizeof(zLine), in)!=0; nLine++){
drh33746482018-12-13 15:06:26 +00004860 rc = sscanf(zLine, "| page %d offset %d", &j, &k);
4861 if( rc==2 ){
4862 iOffset = k;
4863 continue;
4864 }
drhbf70f1b2022-10-19 18:04:42 +00004865 if( cli_strncmp(zLine, "| end ", 6)==0 ){
drh33746482018-12-13 15:06:26 +00004866 break;
4867 }
drh3ea557e2019-04-23 15:30:58 +00004868 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 +00004869 &j, &x[0], &x[1], &x[2], &x[3], &x[4], &x[5], &x[6], &x[7],
4870 &x[8], &x[9], &x[10], &x[11], &x[12], &x[13], &x[14], &x[15]);
4871 if( rc==17 ){
4872 k = iOffset+j;
drh82978ac2021-10-01 17:06:44 +00004873 if( k+16<=n && k>=0 ){
drh3ea557e2019-04-23 15:30:58 +00004874 int ii;
4875 for(ii=0; ii<16; ii++) a[k+ii] = x[ii]&0xff;
drh33746482018-12-13 15:06:26 +00004876 }
drh33746482018-12-13 15:06:26 +00004877 }
4878 }
4879 *pnData = n;
drh2c8ee022018-12-13 18:59:30 +00004880 if( in!=p->in ){
4881 fclose(in);
4882 }else{
4883 p->lineno = nLine;
4884 }
drh33746482018-12-13 15:06:26 +00004885 return a;
4886
4887readHexDb_error:
drh68feae52019-05-09 11:18:41 +00004888 if( in!=p->in ){
drh33746482018-12-13 15:06:26 +00004889 fclose(in);
4890 }else{
drh60379d42018-12-13 18:30:01 +00004891 while( fgets(zLine, sizeof(zLine), p->in)!=0 ){
drh2c8ee022018-12-13 18:59:30 +00004892 nLine++;
drhbf70f1b2022-10-19 18:04:42 +00004893 if(cli_strncmp(zLine, "| end ", 6)==0 ) break;
drh33746482018-12-13 15:06:26 +00004894 }
drh2c8ee022018-12-13 18:59:30 +00004895 p->lineno = nLine;
drh33746482018-12-13 15:06:26 +00004896 }
4897 sqlite3_free(a);
4898 utf8_printf(stderr,"Error on line %d of --hexdb input\n", nLine);
4899 return 0;
4900}
drh8d889af2021-05-08 17:18:23 +00004901#endif /* SQLITE_OMIT_DESERIALIZE */
drh33746482018-12-13 15:06:26 +00004902
danb1825882019-04-23 20:48:32 +00004903/*
dan9c014f82019-04-25 19:23:15 +00004904** Scalar function "shell_int32". The first argument to this function
4905** must be a blob. The second a non-negative integer. This function
4906** reads and returns a 32-bit big-endian integer from byte
4907** offset (4*<arg2>) of the blob.
4908*/
4909static void shellInt32(
4910 sqlite3_context *context,
4911 int argc,
4912 sqlite3_value **argv
4913){
4914 const unsigned char *pBlob;
4915 int nBlob;
4916 int iInt;
drh9546c762019-05-10 17:50:33 +00004917
4918 UNUSED_PARAMETER(argc);
dan9c014f82019-04-25 19:23:15 +00004919 nBlob = sqlite3_value_bytes(argv[0]);
4920 pBlob = (const unsigned char*)sqlite3_value_blob(argv[0]);
4921 iInt = sqlite3_value_int(argv[1]);
4922
4923 if( iInt>=0 && (iInt+1)*4<=nBlob ){
4924 const unsigned char *a = &pBlob[iInt*4];
4925 sqlite3_int64 iVal = ((sqlite3_int64)a[0]<<24)
4926 + ((sqlite3_int64)a[1]<<16)
4927 + ((sqlite3_int64)a[2]<< 8)
4928 + ((sqlite3_int64)a[3]<< 0);
4929 sqlite3_result_int64(context, iVal);
4930 }
4931}
4932
4933/*
drha2de66c2019-08-06 20:26:17 +00004934** Scalar function "shell_idquote(X)" returns string X quoted as an identifier,
4935** using "..." with internal double-quote characters doubled.
4936*/
4937static void shellIdQuote(
4938 sqlite3_context *context,
4939 int argc,
4940 sqlite3_value **argv
4941){
4942 const char *zName = (const char*)sqlite3_value_text(argv[0]);
drh51755a72019-08-08 19:40:29 +00004943 UNUSED_PARAMETER(argc);
drha2de66c2019-08-06 20:26:17 +00004944 if( zName ){
4945 char *z = sqlite3_mprintf("\"%w\"", zName);
4946 sqlite3_result_text(context, z, -1, sqlite3_free);
4947 }
4948}
4949
4950/*
drhddcfe922020-09-15 12:29:35 +00004951** Scalar function "usleep(X)" invokes sqlite3_sleep(X) and returns X.
4952*/
4953static void shellUSleepFunc(
4954 sqlite3_context *context,
drhd36f5882020-11-25 16:28:04 +00004955 int argcUnused,
drhddcfe922020-09-15 12:29:35 +00004956 sqlite3_value **argv
4957){
4958 int sleep = sqlite3_value_int(argv[0]);
drhd36f5882020-11-25 16:28:04 +00004959 (void)argcUnused;
drhddcfe922020-09-15 12:29:35 +00004960 sqlite3_sleep(sleep/1000);
4961 sqlite3_result_int(context, sleep);
4962}
4963
4964/*
danb1825882019-04-23 20:48:32 +00004965** Scalar function "shell_escape_crnl" used by the .recover command.
4966** The argument passed to this function is the output of built-in
4967** function quote(). If the first character of the input is "'",
4968** indicating that the value passed to quote() was a text value,
4969** then this function searches the input for "\n" and "\r" characters
4970** and adds a wrapper similar to the following:
4971**
4972** replace(replace(<input>, '\n', char(10), '\r', char(13));
4973**
4974** Or, if the first character of the input is not "'", then a copy
4975** of the input is returned.
4976*/
4977static void shellEscapeCrnl(
4978 sqlite3_context *context,
4979 int argc,
4980 sqlite3_value **argv
4981){
4982 const char *zText = (const char*)sqlite3_value_text(argv[0]);
drh9546c762019-05-10 17:50:33 +00004983 UNUSED_PARAMETER(argc);
drh621a5e02021-12-16 17:35:27 +00004984 if( zText && zText[0]=='\'' ){
drh7d23d152022-10-11 12:02:42 +00004985 i64 nText = sqlite3_value_bytes(argv[0]);
4986 i64 i;
danb1825882019-04-23 20:48:32 +00004987 char zBuf1[20];
4988 char zBuf2[20];
4989 const char *zNL = 0;
4990 const char *zCR = 0;
drh7d23d152022-10-11 12:02:42 +00004991 i64 nCR = 0;
4992 i64 nNL = 0;
danb1825882019-04-23 20:48:32 +00004993
4994 for(i=0; zText[i]; i++){
4995 if( zNL==0 && zText[i]=='\n' ){
4996 zNL = unused_string(zText, "\\n", "\\012", zBuf1);
drh7d23d152022-10-11 12:02:42 +00004997 nNL = strlen(zNL);
danb1825882019-04-23 20:48:32 +00004998 }
4999 if( zCR==0 && zText[i]=='\r' ){
5000 zCR = unused_string(zText, "\\r", "\\015", zBuf2);
drh7d23d152022-10-11 12:02:42 +00005001 nCR = strlen(zCR);
danb1825882019-04-23 20:48:32 +00005002 }
5003 }
5004
5005 if( zNL || zCR ){
drh7d23d152022-10-11 12:02:42 +00005006 i64 iOut = 0;
danb1825882019-04-23 20:48:32 +00005007 i64 nMax = (nNL > nCR) ? nNL : nCR;
dan51f5ffa2019-04-29 11:41:46 +00005008 i64 nAlloc = nMax * nText + (nMax+64)*2;
danb1825882019-04-23 20:48:32 +00005009 char *zOut = (char*)sqlite3_malloc64(nAlloc);
5010 if( zOut==0 ){
5011 sqlite3_result_error_nomem(context);
5012 return;
5013 }
5014
5015 if( zNL && zCR ){
5016 memcpy(&zOut[iOut], "replace(replace(", 16);
5017 iOut += 16;
5018 }else{
5019 memcpy(&zOut[iOut], "replace(", 8);
5020 iOut += 8;
5021 }
5022 for(i=0; zText[i]; i++){
5023 if( zText[i]=='\n' ){
5024 memcpy(&zOut[iOut], zNL, nNL);
5025 iOut += nNL;
5026 }else if( zText[i]=='\r' ){
5027 memcpy(&zOut[iOut], zCR, nCR);
5028 iOut += nCR;
5029 }else{
5030 zOut[iOut] = zText[i];
5031 iOut++;
5032 }
5033 }
5034
5035 if( zNL ){
5036 memcpy(&zOut[iOut], ",'", 2); iOut += 2;
5037 memcpy(&zOut[iOut], zNL, nNL); iOut += nNL;
5038 memcpy(&zOut[iOut], "', char(10))", 12); iOut += 12;
5039 }
5040 if( zCR ){
5041 memcpy(&zOut[iOut], ",'", 2); iOut += 2;
5042 memcpy(&zOut[iOut], zCR, nCR); iOut += nCR;
5043 memcpy(&zOut[iOut], "', char(13))", 12); iOut += 12;
5044 }
5045
5046 sqlite3_result_text(context, zOut, iOut, SQLITE_TRANSIENT);
5047 sqlite3_free(zOut);
5048 return;
5049 }
5050 }
5051
5052 sqlite3_result_value(context, argv[0]);
5053}
5054
drhbe4ccb22018-05-17 20:04:24 +00005055/* Flags for open_db().
5056**
5057** The default behavior of open_db() is to exit(1) if the database fails to
5058** open. The OPEN_DB_KEEPALIVE flag changes that so that it prints an error
5059** but still returns without calling exit.
5060**
5061** The OPEN_DB_ZIPFILE flag causes open_db() to prefer to open files as a
5062** ZIP archive if the file does not exist or is empty and its name matches
5063** the *.zip pattern.
5064*/
5065#define OPEN_DB_KEEPALIVE 0x001 /* Return after error if true */
5066#define OPEN_DB_ZIPFILE 0x002 /* Open as ZIP if name matches *.zip */
5067
drh1fa6d9f2018-01-06 21:46:01 +00005068/*
drh2ce15c32017-07-11 13:34:40 +00005069** Make sure the database is open. If it is not, then open it. If
5070** the database fails to open, print an error message and exit.
5071*/
drhbe4ccb22018-05-17 20:04:24 +00005072static void open_db(ShellState *p, int openFlags){
drh2ce15c32017-07-11 13:34:40 +00005073 if( p->db==0 ){
drh37407122021-07-23 18:43:58 +00005074 const char *zDbFilename = p->pAuxDb->zDbFilename;
drhf2072d12018-05-11 15:10:11 +00005075 if( p->openMode==SHELL_OPEN_UNSPEC ){
drh37407122021-07-23 18:43:58 +00005076 if( zDbFilename==0 || zDbFilename[0]==0 ){
drhf2072d12018-05-11 15:10:11 +00005077 p->openMode = SHELL_OPEN_NORMAL;
drhbe4ccb22018-05-17 20:04:24 +00005078 }else{
drh37407122021-07-23 18:43:58 +00005079 p->openMode = (u8)deduceDatabaseType(zDbFilename,
drhbe4ccb22018-05-17 20:04:24 +00005080 (openFlags & OPEN_DB_ZIPFILE)!=0);
drhf2072d12018-05-11 15:10:11 +00005081 }
drh1fa6d9f2018-01-06 21:46:01 +00005082 }
5083 switch( p->openMode ){
5084 case SHELL_OPEN_APPENDVFS: {
drh37407122021-07-23 18:43:58 +00005085 sqlite3_open_v2(zDbFilename, &p->db,
drh0933aad2019-11-18 17:46:38 +00005086 SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|p->openFlags, "apndvfs");
drh1fa6d9f2018-01-06 21:46:01 +00005087 break;
5088 }
drh33746482018-12-13 15:06:26 +00005089 case SHELL_OPEN_HEXDB:
drh60f34ae2018-10-30 13:19:49 +00005090 case SHELL_OPEN_DESERIALIZE: {
5091 sqlite3_open(0, &p->db);
5092 break;
5093 }
drh1fa6d9f2018-01-06 21:46:01 +00005094 case SHELL_OPEN_ZIPFILE: {
5095 sqlite3_open(":memory:", &p->db);
5096 break;
5097 }
drhee269a62018-02-14 23:27:43 +00005098 case SHELL_OPEN_READONLY: {
drh37407122021-07-23 18:43:58 +00005099 sqlite3_open_v2(zDbFilename, &p->db,
drh0933aad2019-11-18 17:46:38 +00005100 SQLITE_OPEN_READONLY|p->openFlags, 0);
drhee269a62018-02-14 23:27:43 +00005101 break;
5102 }
drh1fa6d9f2018-01-06 21:46:01 +00005103 case SHELL_OPEN_UNSPEC:
5104 case SHELL_OPEN_NORMAL: {
drh37407122021-07-23 18:43:58 +00005105 sqlite3_open_v2(zDbFilename, &p->db,
drh0933aad2019-11-18 17:46:38 +00005106 SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|p->openFlags, 0);
drh1fa6d9f2018-01-06 21:46:01 +00005107 break;
5108 }
5109 }
drh2ce15c32017-07-11 13:34:40 +00005110 globalDb = p->db;
5111 if( p->db==0 || SQLITE_OK!=sqlite3_errcode(p->db) ){
5112 utf8_printf(stderr,"Error: unable to open database \"%s\": %s\n",
drh37407122021-07-23 18:43:58 +00005113 zDbFilename, sqlite3_errmsg(p->db));
drhf25cc4f2019-01-04 14:29:21 +00005114 if( openFlags & OPEN_DB_KEEPALIVE ){
5115 sqlite3_open(":memory:", &p->db);
5116 return;
5117 }
drh2ce15c32017-07-11 13:34:40 +00005118 exit(1);
5119 }
5120#ifndef SQLITE_OMIT_LOAD_EXTENSION
5121 sqlite3_enable_load_extension(p->db, 1);
5122#endif
drh2ce15c32017-07-11 13:34:40 +00005123 sqlite3_shathree_init(p->db, 0, 0);
drhf05dd032020-04-14 15:53:58 +00005124 sqlite3_uint_init(p->db, 0, 0);
drhbeb9def2020-06-22 19:12:23 +00005125 sqlite3_decimal_init(p->db, 0, 0);
drh64689902021-06-03 13:51:31 +00005126 sqlite3_regexp_init(p->db, 0, 0);
drh8cda77d2020-06-24 15:06:29 +00005127 sqlite3_ieee_init(p->db, 0, 0);
mistachkin72c38d82020-08-28 18:47:39 +00005128 sqlite3_series_init(p->db, 0, 0);
stephan4413ec72022-07-12 15:53:02 +00005129#ifndef SQLITE_SHELL_FIDDLE
stephanf8cd3d22022-05-18 17:14:24 +00005130 sqlite3_fileio_init(p->db, 0, 0);
5131 sqlite3_completion_init(p->db, 0, 0);
5132#endif
stephan3d420832022-10-27 03:56:01 +00005133#if SQLITE_SHELL_HAVE_RECOVER
dan68cb86e2019-04-20 20:57:28 +00005134 sqlite3_dbdata_init(p->db, 0, 0);
dan1b162162019-04-27 20:15:15 +00005135#endif
dan72afc3c2017-12-05 18:32:40 +00005136#ifdef SQLITE_HAVE_ZLIB
drh9198f5a2022-03-19 15:19:35 +00005137 if( !p->bSafeModePersist ){
5138 sqlite3_zipfile_init(p->db, 0, 0);
5139 sqlite3_sqlar_init(p->db, 0, 0);
5140 }
dan72afc3c2017-12-05 18:32:40 +00005141#endif
drhceba7922018-01-01 21:28:25 +00005142 sqlite3_create_function(p->db, "shell_add_schema", 3, SQLITE_UTF8, 0,
drh2ce15c32017-07-11 13:34:40 +00005143 shellAddSchemaName, 0, 0);
drh667a2a22018-01-02 00:04:37 +00005144 sqlite3_create_function(p->db, "shell_module_schema", 1, SQLITE_UTF8, 0,
5145 shellModuleSchema, 0, 0);
drh634c70f2018-01-10 16:50:18 +00005146 sqlite3_create_function(p->db, "shell_putsnl", 1, SQLITE_UTF8, p,
5147 shellPutsFunc, 0, 0);
danb1825882019-04-23 20:48:32 +00005148 sqlite3_create_function(p->db, "shell_escape_crnl", 1, SQLITE_UTF8, 0,
5149 shellEscapeCrnl, 0, 0);
dan9c014f82019-04-25 19:23:15 +00005150 sqlite3_create_function(p->db, "shell_int32", 2, SQLITE_UTF8, 0,
5151 shellInt32, 0, 0);
drha2de66c2019-08-06 20:26:17 +00005152 sqlite3_create_function(p->db, "shell_idquote", 1, SQLITE_UTF8, 0,
5153 shellIdQuote, 0, 0);
drhddcfe922020-09-15 12:29:35 +00005154 sqlite3_create_function(p->db, "usleep",1,SQLITE_UTF8,0,
5155 shellUSleepFunc, 0, 0);
drh04a28c32018-01-31 01:38:44 +00005156#ifndef SQLITE_NOHAVE_SYSTEM
drh97913132018-01-11 00:04:00 +00005157 sqlite3_create_function(p->db, "edit", 1, SQLITE_UTF8, 0,
5158 editFunc, 0, 0);
5159 sqlite3_create_function(p->db, "edit", 2, SQLITE_UTF8, 0,
5160 editFunc, 0, 0);
drh04a28c32018-01-31 01:38:44 +00005161#endif
drh1fa6d9f2018-01-06 21:46:01 +00005162 if( p->openMode==SHELL_OPEN_ZIPFILE ){
5163 char *zSql = sqlite3_mprintf(
drh37407122021-07-23 18:43:58 +00005164 "CREATE VIRTUAL TABLE zip USING zipfile(%Q);", zDbFilename);
drhe3e25652021-12-16 13:29:28 +00005165 shell_check_oom(zSql);
drh1fa6d9f2018-01-06 21:46:01 +00005166 sqlite3_exec(p->db, zSql, 0, 0, 0);
5167 sqlite3_free(zSql);
drha751f392018-10-30 15:31:22 +00005168 }
drh8d889af2021-05-08 17:18:23 +00005169#ifndef SQLITE_OMIT_DESERIALIZE
drh33746482018-12-13 15:06:26 +00005170 else
5171 if( p->openMode==SHELL_OPEN_DESERIALIZE || p->openMode==SHELL_OPEN_HEXDB ){
mistachkin99490932018-12-17 22:19:57 +00005172 int rc;
drh60f34ae2018-10-30 13:19:49 +00005173 int nData = 0;
drh33746482018-12-13 15:06:26 +00005174 unsigned char *aData;
5175 if( p->openMode==SHELL_OPEN_DESERIALIZE ){
drh37407122021-07-23 18:43:58 +00005176 aData = (unsigned char*)readFile(zDbFilename, &nData);
drh33746482018-12-13 15:06:26 +00005177 }else{
5178 aData = readHexDb(p, &nData);
5179 if( aData==0 ){
drh33746482018-12-13 15:06:26 +00005180 return;
5181 }
5182 }
mistachkin99490932018-12-17 22:19:57 +00005183 rc = sqlite3_deserialize(p->db, "main", aData, nData, nData,
drh60f34ae2018-10-30 13:19:49 +00005184 SQLITE_DESERIALIZE_RESIZEABLE |
5185 SQLITE_DESERIALIZE_FREEONCLOSE);
5186 if( rc ){
5187 utf8_printf(stderr, "Error: sqlite3_deserialize() returns %d\n", rc);
5188 }
drh6ca64482019-01-22 16:06:20 +00005189 if( p->szMax>0 ){
5190 sqlite3_file_control(p->db, "main", SQLITE_FCNTL_SIZE_LIMIT, &p->szMax);
5191 }
drh1fa6d9f2018-01-06 21:46:01 +00005192 }
drha751f392018-10-30 15:31:22 +00005193#endif
drh2ce15c32017-07-11 13:34:40 +00005194 }
drhb97e2ad2021-08-26 18:31:39 +00005195 if( p->bSafeModePersist && p->db!=0 ){
5196 sqlite3_set_authorizer(p->db, safeModeAuth, p);
5197 }
drh2ce15c32017-07-11 13:34:40 +00005198}
5199
drh9e804032018-05-18 17:11:50 +00005200/*
5201** Attempt to close the databaes connection. Report errors.
5202*/
5203void close_db(sqlite3 *db){
5204 int rc = sqlite3_close(db);
5205 if( rc ){
5206 utf8_printf(stderr, "Error: sqlite3_close() returns %d: %s\n",
5207 rc, sqlite3_errmsg(db));
5208 }
5209}
5210
drh56eb09b2017-07-11 13:59:07 +00005211#if HAVE_READLINE || HAVE_EDITLINE
5212/*
5213** Readline completion callbacks
5214*/
5215static char *readline_completion_generator(const char *text, int state){
5216 static sqlite3_stmt *pStmt = 0;
5217 char *zRet;
5218 if( state==0 ){
5219 char *zSql;
drh56eb09b2017-07-11 13:59:07 +00005220 sqlite3_finalize(pStmt);
5221 zSql = sqlite3_mprintf("SELECT DISTINCT candidate COLLATE nocase"
5222 " FROM completion(%Q) ORDER BY 1", text);
drhe3e25652021-12-16 13:29:28 +00005223 shell_check_oom(zSql);
drh56eb09b2017-07-11 13:59:07 +00005224 sqlite3_prepare_v2(globalDb, zSql, -1, &pStmt, 0);
5225 sqlite3_free(zSql);
5226 }
5227 if( sqlite3_step(pStmt)==SQLITE_ROW ){
drh621a5e02021-12-16 17:35:27 +00005228 const char *z = (const char*)sqlite3_column_text(pStmt,0);
5229 zRet = z ? strdup(z) : 0;
drh56eb09b2017-07-11 13:59:07 +00005230 }else{
5231 sqlite3_finalize(pStmt);
5232 pStmt = 0;
5233 zRet = 0;
5234 }
5235 return zRet;
5236}
5237static char **readline_completion(const char *zText, int iStart, int iEnd){
5238 rl_attempted_completion_over = 1;
5239 return rl_completion_matches(zText, readline_completion_generator);
5240}
5241
5242#elif HAVE_LINENOISE
5243/*
5244** Linenoise completion callback
5245*/
5246static void linenoise_completion(const char *zLine, linenoiseCompletions *lc){
drh7d23d152022-10-11 12:02:42 +00005247 i64 nLine = strlen(zLine);
5248 i64 i, iStart;
drh56eb09b2017-07-11 13:59:07 +00005249 sqlite3_stmt *pStmt = 0;
5250 char *zSql;
5251 char zBuf[1000];
5252
5253 if( nLine>sizeof(zBuf)-30 ) return;
drh1615c372018-05-12 23:56:22 +00005254 if( zLine[0]=='.' || zLine[0]=='#') return;
drh56eb09b2017-07-11 13:59:07 +00005255 for(i=nLine-1; i>=0 && (isalnum(zLine[i]) || zLine[i]=='_'); i--){}
5256 if( i==nLine-1 ) return;
5257 iStart = i+1;
5258 memcpy(zBuf, zLine, iStart);
5259 zSql = sqlite3_mprintf("SELECT DISTINCT candidate COLLATE nocase"
5260 " FROM completion(%Q,%Q) ORDER BY 1",
5261 &zLine[iStart], zLine);
drhe3e25652021-12-16 13:29:28 +00005262 shell_check_oom(zSql);
drh56eb09b2017-07-11 13:59:07 +00005263 sqlite3_prepare_v2(globalDb, zSql, -1, &pStmt, 0);
5264 sqlite3_free(zSql);
5265 sqlite3_exec(globalDb, "PRAGMA page_count", 0, 0, 0); /* Load the schema */
5266 while( sqlite3_step(pStmt)==SQLITE_ROW ){
5267 const char *zCompletion = (const char*)sqlite3_column_text(pStmt, 0);
5268 int nCompletion = sqlite3_column_bytes(pStmt, 0);
drh621a5e02021-12-16 17:35:27 +00005269 if( iStart+nCompletion < sizeof(zBuf)-1 && zCompletion ){
drh56eb09b2017-07-11 13:59:07 +00005270 memcpy(zBuf+iStart, zCompletion, nCompletion+1);
5271 linenoiseAddCompletion(lc, zBuf);
5272 }
5273 }
5274 sqlite3_finalize(pStmt);
5275}
5276#endif
5277
drh2ce15c32017-07-11 13:34:40 +00005278/*
5279** Do C-language style dequoting.
5280**
5281** \a -> alarm
5282** \b -> backspace
5283** \t -> tab
5284** \n -> newline
5285** \v -> vertical tab
5286** \f -> form feed
5287** \r -> carriage return
5288** \s -> space
5289** \" -> "
5290** \' -> '
5291** \\ -> backslash
5292** \NNN -> ascii character NNN in octal
5293*/
5294static void resolve_backslashes(char *z){
5295 int i, j;
5296 char c;
5297 while( *z && *z!='\\' ) z++;
5298 for(i=j=0; (c = z[i])!=0; i++, j++){
5299 if( c=='\\' && z[i+1]!=0 ){
5300 c = z[++i];
5301 if( c=='a' ){
5302 c = '\a';
5303 }else if( c=='b' ){
5304 c = '\b';
5305 }else if( c=='t' ){
5306 c = '\t';
5307 }else if( c=='n' ){
5308 c = '\n';
5309 }else if( c=='v' ){
5310 c = '\v';
5311 }else if( c=='f' ){
5312 c = '\f';
5313 }else if( c=='r' ){
5314 c = '\r';
5315 }else if( c=='"' ){
5316 c = '"';
5317 }else if( c=='\'' ){
5318 c = '\'';
5319 }else if( c=='\\' ){
5320 c = '\\';
5321 }else if( c>='0' && c<='7' ){
5322 c -= '0';
5323 if( z[i+1]>='0' && z[i+1]<='7' ){
5324 i++;
5325 c = (c<<3) + z[i] - '0';
5326 if( z[i+1]>='0' && z[i+1]<='7' ){
5327 i++;
5328 c = (c<<3) + z[i] - '0';
5329 }
5330 }
5331 }
5332 }
5333 z[j] = c;
5334 }
5335 if( j<i ) z[j] = 0;
5336}
5337
5338/*
drh2ce15c32017-07-11 13:34:40 +00005339** Interpret zArg as either an integer or a boolean value. Return 1 or 0
5340** for TRUE and FALSE. Return the integer value if appropriate.
5341*/
5342static int booleanValue(const char *zArg){
5343 int i;
5344 if( zArg[0]=='0' && zArg[1]=='x' ){
5345 for(i=2; hexDigitValue(zArg[i])>=0; i++){}
5346 }else{
5347 for(i=0; zArg[i]>='0' && zArg[i]<='9'; i++){}
5348 }
5349 if( i>0 && zArg[i]==0 ) return (int)(integerValue(zArg) & 0xffffffff);
5350 if( sqlite3_stricmp(zArg, "on")==0 || sqlite3_stricmp(zArg,"yes")==0 ){
5351 return 1;
5352 }
5353 if( sqlite3_stricmp(zArg, "off")==0 || sqlite3_stricmp(zArg,"no")==0 ){
5354 return 0;
5355 }
5356 utf8_printf(stderr, "ERROR: Not a boolean value: \"%s\". Assuming \"no\".\n",
5357 zArg);
5358 return 0;
5359}
5360
5361/*
5362** Set or clear a shell flag according to a boolean value.
5363*/
5364static void setOrClearFlag(ShellState *p, unsigned mFlag, const char *zArg){
5365 if( booleanValue(zArg) ){
5366 ShellSetFlag(p, mFlag);
5367 }else{
5368 ShellClearFlag(p, mFlag);
5369 }
5370}
5371
5372/*
5373** Close an output file, assuming it is not stderr or stdout
5374*/
5375static void output_file_close(FILE *f){
5376 if( f && f!=stdout && f!=stderr ) fclose(f);
5377}
5378
5379/*
5380** Try to open an output file. The names "stdout" and "stderr" are
5381** recognized and do the right thing. NULL is returned if the output
5382** filename is "off".
5383*/
drha92a01a2018-01-10 22:15:37 +00005384static FILE *output_file_open(const char *zFile, int bTextMode){
drh2ce15c32017-07-11 13:34:40 +00005385 FILE *f;
drhbf70f1b2022-10-19 18:04:42 +00005386 if( cli_strcmp(zFile,"stdout")==0 ){
drh2ce15c32017-07-11 13:34:40 +00005387 f = stdout;
drhbf70f1b2022-10-19 18:04:42 +00005388 }else if( cli_strcmp(zFile, "stderr")==0 ){
drh2ce15c32017-07-11 13:34:40 +00005389 f = stderr;
drhbf70f1b2022-10-19 18:04:42 +00005390 }else if( cli_strcmp(zFile, "off")==0 ){
drh2ce15c32017-07-11 13:34:40 +00005391 f = 0;
5392 }else{
drha92a01a2018-01-10 22:15:37 +00005393 f = fopen(zFile, bTextMode ? "w" : "wb");
drh2ce15c32017-07-11 13:34:40 +00005394 if( f==0 ){
5395 utf8_printf(stderr, "Error: cannot open \"%s\"\n", zFile);
5396 }
5397 }
5398 return f;
5399}
5400
drh707821f2018-12-05 13:39:06 +00005401#ifndef SQLITE_OMIT_TRACE
drh2ce15c32017-07-11 13:34:40 +00005402/*
5403** A routine for handling output from sqlite3_trace().
5404*/
5405static int sql_trace_callback(
drh707821f2018-12-05 13:39:06 +00005406 unsigned mType, /* The trace type */
5407 void *pArg, /* The ShellState pointer */
5408 void *pP, /* Usually a pointer to sqlite_stmt */
5409 void *pX /* Auxiliary output */
drh2ce15c32017-07-11 13:34:40 +00005410){
drh707821f2018-12-05 13:39:06 +00005411 ShellState *p = (ShellState*)pArg;
5412 sqlite3_stmt *pStmt;
5413 const char *zSql;
drh7d23d152022-10-11 12:02:42 +00005414 i64 nSql;
drh707821f2018-12-05 13:39:06 +00005415 if( p->traceOut==0 ) return 0;
5416 if( mType==SQLITE_TRACE_CLOSE ){
5417 utf8_printf(p->traceOut, "-- closing database connection\n");
5418 return 0;
5419 }
5420 if( mType!=SQLITE_TRACE_ROW && ((const char*)pX)[0]=='-' ){
5421 zSql = (const char*)pX;
5422 }else{
5423 pStmt = (sqlite3_stmt*)pP;
5424 switch( p->eTraceType ){
5425 case SHELL_TRACE_EXPANDED: {
5426 zSql = sqlite3_expanded_sql(pStmt);
5427 break;
5428 }
5429#ifdef SQLITE_ENABLE_NORMALIZE
5430 case SHELL_TRACE_NORMALIZED: {
5431 zSql = sqlite3_normalized_sql(pStmt);
5432 break;
5433 }
5434#endif
5435 default: {
5436 zSql = sqlite3_sql(pStmt);
5437 break;
5438 }
5439 }
5440 }
5441 if( zSql==0 ) return 0;
drh7d23d152022-10-11 12:02:42 +00005442 nSql = strlen(zSql);
5443 if( nSql>1000000000 ) nSql = 1000000000;
drh707821f2018-12-05 13:39:06 +00005444 while( nSql>0 && zSql[nSql-1]==';' ){ nSql--; }
5445 switch( mType ){
5446 case SQLITE_TRACE_ROW:
5447 case SQLITE_TRACE_STMT: {
drh7d23d152022-10-11 12:02:42 +00005448 utf8_printf(p->traceOut, "%.*s;\n", (int)nSql, zSql);
drh707821f2018-12-05 13:39:06 +00005449 break;
5450 }
5451 case SQLITE_TRACE_PROFILE: {
5452 sqlite3_int64 nNanosec = *(sqlite3_int64*)pX;
drh7d23d152022-10-11 12:02:42 +00005453 utf8_printf(p->traceOut, "%.*s; -- %lld ns\n", (int)nSql, zSql, nNanosec);
drh707821f2018-12-05 13:39:06 +00005454 break;
5455 }
drh2ce15c32017-07-11 13:34:40 +00005456 }
5457 return 0;
5458}
5459#endif
drh2ce15c32017-07-11 13:34:40 +00005460
5461/*
5462** A no-op routine that runs with the ".breakpoint" doc-command. This is
5463** a useful spot to set a debugger breakpoint.
5464*/
5465static void test_breakpoint(void){
5466 static int nCall = 0;
5467 nCall++;
5468}
5469
5470/*
5471** An object used to read a CSV and other files for import.
5472*/
5473typedef struct ImportCtx ImportCtx;
5474struct ImportCtx {
5475 const char *zFile; /* Name of the input file */
5476 FILE *in; /* Read the CSV text from this input stream */
drh97767842020-05-29 19:39:35 +00005477 int (SQLITE_CDECL *xCloser)(FILE*); /* Func to close in */
drh2ce15c32017-07-11 13:34:40 +00005478 char *z; /* Accumulated text for a field */
5479 int n; /* Number of bytes in z */
5480 int nAlloc; /* Space allocated for z[] */
5481 int nLine; /* Current line number */
drhccb37812020-03-09 15:39:39 +00005482 int nRow; /* Number of rows imported */
5483 int nErr; /* Number of errors encountered */
drh2ce15c32017-07-11 13:34:40 +00005484 int bNotFirst; /* True if one or more bytes already read */
5485 int cTerm; /* Character that terminated the most recent field */
5486 int cColSep; /* The column separator character. (Usually ",") */
5487 int cRowSep; /* The row separator character. (Usually "\n") */
5488};
5489
drh97767842020-05-29 19:39:35 +00005490/* Clean up resourced used by an ImportCtx */
5491static void import_cleanup(ImportCtx *p){
drh42c2a042020-05-29 20:16:19 +00005492 if( p->in!=0 && p->xCloser!=0 ){
drh97767842020-05-29 19:39:35 +00005493 p->xCloser(p->in);
5494 p->in = 0;
5495 }
5496 sqlite3_free(p->z);
5497 p->z = 0;
5498}
5499
drh2ce15c32017-07-11 13:34:40 +00005500/* Append a single byte to z[] */
5501static void import_append_char(ImportCtx *p, int c){
5502 if( p->n+1>=p->nAlloc ){
5503 p->nAlloc += p->nAlloc + 100;
5504 p->z = sqlite3_realloc64(p->z, p->nAlloc);
drhe3e25652021-12-16 13:29:28 +00005505 shell_check_oom(p->z);
drh2ce15c32017-07-11 13:34:40 +00005506 }
5507 p->z[p->n++] = (char)c;
5508}
5509
5510/* Read a single field of CSV text. Compatible with rfc4180 and extended
5511** with the option of having a separator other than ",".
5512**
5513** + Input comes from p->in.
5514** + Store results in p->z of length p->n. Space to hold p->z comes
5515** from sqlite3_malloc64().
5516** + Use p->cSep as the column separator. The default is ",".
5517** + Use p->rSep as the row separator. The default is "\n".
5518** + Keep track of the line number in p->nLine.
5519** + Store the character that terminates the field in p->cTerm. Store
5520** EOF on end-of-file.
5521** + Report syntax errors on stderr
5522*/
5523static char *SQLITE_CDECL csv_read_one_field(ImportCtx *p){
5524 int c;
5525 int cSep = p->cColSep;
5526 int rSep = p->cRowSep;
5527 p->n = 0;
5528 c = fgetc(p->in);
5529 if( c==EOF || seenInterrupt ){
5530 p->cTerm = EOF;
5531 return 0;
5532 }
5533 if( c=='"' ){
5534 int pc, ppc;
5535 int startLine = p->nLine;
5536 int cQuote = c;
5537 pc = ppc = 0;
5538 while( 1 ){
5539 c = fgetc(p->in);
5540 if( c==rSep ) p->nLine++;
5541 if( c==cQuote ){
5542 if( pc==cQuote ){
5543 pc = 0;
5544 continue;
5545 }
5546 }
5547 if( (c==cSep && pc==cQuote)
5548 || (c==rSep && pc==cQuote)
5549 || (c==rSep && pc=='\r' && ppc==cQuote)
5550 || (c==EOF && pc==cQuote)
5551 ){
5552 do{ p->n--; }while( p->z[p->n]!=cQuote );
5553 p->cTerm = c;
5554 break;
5555 }
5556 if( pc==cQuote && c!='\r' ){
5557 utf8_printf(stderr, "%s:%d: unescaped %c character\n",
5558 p->zFile, p->nLine, cQuote);
5559 }
5560 if( c==EOF ){
5561 utf8_printf(stderr, "%s:%d: unterminated %c-quoted field\n",
5562 p->zFile, startLine, cQuote);
5563 p->cTerm = c;
5564 break;
5565 }
5566 import_append_char(p, c);
5567 ppc = pc;
5568 pc = c;
5569 }
5570 }else{
5571 /* If this is the first field being parsed and it begins with the
5572 ** UTF-8 BOM (0xEF BB BF) then skip the BOM */
5573 if( (c&0xff)==0xef && p->bNotFirst==0 ){
5574 import_append_char(p, c);
5575 c = fgetc(p->in);
5576 if( (c&0xff)==0xbb ){
5577 import_append_char(p, c);
5578 c = fgetc(p->in);
5579 if( (c&0xff)==0xbf ){
5580 p->bNotFirst = 1;
5581 p->n = 0;
5582 return csv_read_one_field(p);
5583 }
5584 }
5585 }
5586 while( c!=EOF && c!=cSep && c!=rSep ){
5587 import_append_char(p, c);
5588 c = fgetc(p->in);
5589 }
5590 if( c==rSep ){
5591 p->nLine++;
5592 if( p->n>0 && p->z[p->n-1]=='\r' ) p->n--;
5593 }
5594 p->cTerm = c;
5595 }
5596 if( p->z ) p->z[p->n] = 0;
5597 p->bNotFirst = 1;
5598 return p->z;
5599}
5600
5601/* Read a single field of ASCII delimited text.
5602**
5603** + Input comes from p->in.
5604** + Store results in p->z of length p->n. Space to hold p->z comes
5605** from sqlite3_malloc64().
5606** + Use p->cSep as the column separator. The default is "\x1F".
5607** + Use p->rSep as the row separator. The default is "\x1E".
5608** + Keep track of the row number in p->nLine.
5609** + Store the character that terminates the field in p->cTerm. Store
5610** EOF on end-of-file.
5611** + Report syntax errors on stderr
5612*/
5613static char *SQLITE_CDECL ascii_read_one_field(ImportCtx *p){
5614 int c;
5615 int cSep = p->cColSep;
5616 int rSep = p->cRowSep;
5617 p->n = 0;
5618 c = fgetc(p->in);
5619 if( c==EOF || seenInterrupt ){
5620 p->cTerm = EOF;
5621 return 0;
5622 }
5623 while( c!=EOF && c!=cSep && c!=rSep ){
5624 import_append_char(p, c);
5625 c = fgetc(p->in);
5626 }
5627 if( c==rSep ){
5628 p->nLine++;
5629 }
5630 p->cTerm = c;
5631 if( p->z ) p->z[p->n] = 0;
5632 return p->z;
5633}
5634
5635/*
5636** Try to transfer data for table zTable. If an error is seen while
5637** moving forward, try to go backwards. The backwards movement won't
5638** work for WITHOUT ROWID tables.
5639*/
5640static void tryToCloneData(
5641 ShellState *p,
5642 sqlite3 *newDb,
5643 const char *zTable
5644){
5645 sqlite3_stmt *pQuery = 0;
5646 sqlite3_stmt *pInsert = 0;
5647 char *zQuery = 0;
5648 char *zInsert = 0;
5649 int rc;
5650 int i, j, n;
drhaf2770f2018-01-05 14:55:43 +00005651 int nTable = strlen30(zTable);
drh2ce15c32017-07-11 13:34:40 +00005652 int k = 0;
5653 int cnt = 0;
5654 const int spinRate = 10000;
5655
5656 zQuery = sqlite3_mprintf("SELECT * FROM \"%w\"", zTable);
drhe3e25652021-12-16 13:29:28 +00005657 shell_check_oom(zQuery);
drh2ce15c32017-07-11 13:34:40 +00005658 rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
5659 if( rc ){
5660 utf8_printf(stderr, "Error %d: %s on [%s]\n",
5661 sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db),
5662 zQuery);
5663 goto end_data_xfer;
5664 }
5665 n = sqlite3_column_count(pQuery);
5666 zInsert = sqlite3_malloc64(200 + nTable + n*3);
drhe3e25652021-12-16 13:29:28 +00005667 shell_check_oom(zInsert);
drh2ce15c32017-07-11 13:34:40 +00005668 sqlite3_snprintf(200+nTable,zInsert,
5669 "INSERT OR IGNORE INTO \"%s\" VALUES(?", zTable);
drhaf2770f2018-01-05 14:55:43 +00005670 i = strlen30(zInsert);
drh2ce15c32017-07-11 13:34:40 +00005671 for(j=1; j<n; j++){
5672 memcpy(zInsert+i, ",?", 2);
5673 i += 2;
5674 }
5675 memcpy(zInsert+i, ");", 3);
5676 rc = sqlite3_prepare_v2(newDb, zInsert, -1, &pInsert, 0);
5677 if( rc ){
5678 utf8_printf(stderr, "Error %d: %s on [%s]\n",
5679 sqlite3_extended_errcode(newDb), sqlite3_errmsg(newDb),
5680 zQuery);
5681 goto end_data_xfer;
5682 }
5683 for(k=0; k<2; k++){
5684 while( (rc = sqlite3_step(pQuery))==SQLITE_ROW ){
5685 for(i=0; i<n; i++){
5686 switch( sqlite3_column_type(pQuery, i) ){
5687 case SQLITE_NULL: {
5688 sqlite3_bind_null(pInsert, i+1);
5689 break;
5690 }
5691 case SQLITE_INTEGER: {
5692 sqlite3_bind_int64(pInsert, i+1, sqlite3_column_int64(pQuery,i));
5693 break;
5694 }
5695 case SQLITE_FLOAT: {
5696 sqlite3_bind_double(pInsert, i+1, sqlite3_column_double(pQuery,i));
5697 break;
5698 }
5699 case SQLITE_TEXT: {
5700 sqlite3_bind_text(pInsert, i+1,
5701 (const char*)sqlite3_column_text(pQuery,i),
5702 -1, SQLITE_STATIC);
5703 break;
5704 }
5705 case SQLITE_BLOB: {
5706 sqlite3_bind_blob(pInsert, i+1, sqlite3_column_blob(pQuery,i),
5707 sqlite3_column_bytes(pQuery,i),
5708 SQLITE_STATIC);
5709 break;
5710 }
5711 }
5712 } /* End for */
5713 rc = sqlite3_step(pInsert);
5714 if( rc!=SQLITE_OK && rc!=SQLITE_ROW && rc!=SQLITE_DONE ){
5715 utf8_printf(stderr, "Error %d: %s\n", sqlite3_extended_errcode(newDb),
5716 sqlite3_errmsg(newDb));
5717 }
5718 sqlite3_reset(pInsert);
5719 cnt++;
5720 if( (cnt%spinRate)==0 ){
5721 printf("%c\b", "|/-\\"[(cnt/spinRate)%4]);
5722 fflush(stdout);
5723 }
5724 } /* End while */
5725 if( rc==SQLITE_DONE ) break;
5726 sqlite3_finalize(pQuery);
5727 sqlite3_free(zQuery);
5728 zQuery = sqlite3_mprintf("SELECT * FROM \"%w\" ORDER BY rowid DESC;",
5729 zTable);
drhe3e25652021-12-16 13:29:28 +00005730 shell_check_oom(zQuery);
drh2ce15c32017-07-11 13:34:40 +00005731 rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
5732 if( rc ){
5733 utf8_printf(stderr, "Warning: cannot step \"%s\" backwards", zTable);
5734 break;
5735 }
5736 } /* End for(k=0...) */
5737
5738end_data_xfer:
5739 sqlite3_finalize(pQuery);
5740 sqlite3_finalize(pInsert);
5741 sqlite3_free(zQuery);
5742 sqlite3_free(zInsert);
5743}
5744
5745
5746/*
5747** Try to transfer all rows of the schema that match zWhere. For
5748** each row, invoke xForEach() on the object defined by that row.
5749** If an error is encountered while moving forward through the
drh067b92b2020-06-19 15:24:12 +00005750** sqlite_schema table, try again moving backwards.
drh2ce15c32017-07-11 13:34:40 +00005751*/
5752static void tryToCloneSchema(
5753 ShellState *p,
5754 sqlite3 *newDb,
5755 const char *zWhere,
5756 void (*xForEach)(ShellState*,sqlite3*,const char*)
5757){
5758 sqlite3_stmt *pQuery = 0;
5759 char *zQuery = 0;
5760 int rc;
5761 const unsigned char *zName;
5762 const unsigned char *zSql;
5763 char *zErrMsg = 0;
5764
drh067b92b2020-06-19 15:24:12 +00005765 zQuery = sqlite3_mprintf("SELECT name, sql FROM sqlite_schema"
drh2ce15c32017-07-11 13:34:40 +00005766 " WHERE %s", zWhere);
drhe3e25652021-12-16 13:29:28 +00005767 shell_check_oom(zQuery);
drh2ce15c32017-07-11 13:34:40 +00005768 rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
5769 if( rc ){
5770 utf8_printf(stderr, "Error: (%d) %s on [%s]\n",
5771 sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db),
5772 zQuery);
5773 goto end_schema_xfer;
5774 }
5775 while( (rc = sqlite3_step(pQuery))==SQLITE_ROW ){
5776 zName = sqlite3_column_text(pQuery, 0);
5777 zSql = sqlite3_column_text(pQuery, 1);
drh621a5e02021-12-16 17:35:27 +00005778 if( zName==0 || zSql==0 ) continue;
drh2ce15c32017-07-11 13:34:40 +00005779 printf("%s... ", zName); fflush(stdout);
5780 sqlite3_exec(newDb, (const char*)zSql, 0, 0, &zErrMsg);
5781 if( zErrMsg ){
5782 utf8_printf(stderr, "Error: %s\nSQL: [%s]\n", zErrMsg, zSql);
5783 sqlite3_free(zErrMsg);
5784 zErrMsg = 0;
5785 }
5786 if( xForEach ){
5787 xForEach(p, newDb, (const char*)zName);
5788 }
5789 printf("done\n");
5790 }
5791 if( rc!=SQLITE_DONE ){
5792 sqlite3_finalize(pQuery);
5793 sqlite3_free(zQuery);
drh067b92b2020-06-19 15:24:12 +00005794 zQuery = sqlite3_mprintf("SELECT name, sql FROM sqlite_schema"
drh2ce15c32017-07-11 13:34:40 +00005795 " WHERE %s ORDER BY rowid DESC", zWhere);
drhe3e25652021-12-16 13:29:28 +00005796 shell_check_oom(zQuery);
drh2ce15c32017-07-11 13:34:40 +00005797 rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
5798 if( rc ){
5799 utf8_printf(stderr, "Error: (%d) %s on [%s]\n",
5800 sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db),
5801 zQuery);
5802 goto end_schema_xfer;
5803 }
drh76fc88f2021-10-02 16:39:16 +00005804 while( sqlite3_step(pQuery)==SQLITE_ROW ){
drh2ce15c32017-07-11 13:34:40 +00005805 zName = sqlite3_column_text(pQuery, 0);
5806 zSql = sqlite3_column_text(pQuery, 1);
drh621a5e02021-12-16 17:35:27 +00005807 if( zName==0 || zSql==0 ) continue;
drh2ce15c32017-07-11 13:34:40 +00005808 printf("%s... ", zName); fflush(stdout);
5809 sqlite3_exec(newDb, (const char*)zSql, 0, 0, &zErrMsg);
5810 if( zErrMsg ){
5811 utf8_printf(stderr, "Error: %s\nSQL: [%s]\n", zErrMsg, zSql);
5812 sqlite3_free(zErrMsg);
5813 zErrMsg = 0;
5814 }
5815 if( xForEach ){
5816 xForEach(p, newDb, (const char*)zName);
5817 }
5818 printf("done\n");
5819 }
5820 }
5821end_schema_xfer:
5822 sqlite3_finalize(pQuery);
5823 sqlite3_free(zQuery);
5824}
5825
5826/*
5827** Open a new database file named "zNewDb". Try to recover as much information
5828** as possible out of the main database (which might be corrupt) and write it
5829** into zNewDb.
5830*/
5831static void tryToClone(ShellState *p, const char *zNewDb){
5832 int rc;
5833 sqlite3 *newDb = 0;
5834 if( access(zNewDb,0)==0 ){
5835 utf8_printf(stderr, "File \"%s\" already exists.\n", zNewDb);
5836 return;
5837 }
5838 rc = sqlite3_open(zNewDb, &newDb);
5839 if( rc ){
5840 utf8_printf(stderr, "Cannot create output database: %s\n",
5841 sqlite3_errmsg(newDb));
5842 }else{
5843 sqlite3_exec(p->db, "PRAGMA writable_schema=ON;", 0, 0, 0);
5844 sqlite3_exec(newDb, "BEGIN EXCLUSIVE;", 0, 0, 0);
5845 tryToCloneSchema(p, newDb, "type='table'", tryToCloneData);
5846 tryToCloneSchema(p, newDb, "type!='table'", 0);
5847 sqlite3_exec(newDb, "COMMIT;", 0, 0, 0);
5848 sqlite3_exec(p->db, "PRAGMA writable_schema=OFF;", 0, 0, 0);
5849 }
drh9e804032018-05-18 17:11:50 +00005850 close_db(newDb);
drh2ce15c32017-07-11 13:34:40 +00005851}
5852
5853/*
drh13c20932018-01-10 21:41:55 +00005854** Change the output file back to stdout.
5855**
5856** If the p->doXdgOpen flag is set, that means the output was being
5857** redirected to a temporary file named by p->zTempFile. In that case,
5858** launch start/open/xdg-open on that temporary file.
drh2ce15c32017-07-11 13:34:40 +00005859*/
5860static void output_reset(ShellState *p){
5861 if( p->outfile[0]=='|' ){
5862#ifndef SQLITE_OMIT_POPEN
5863 pclose(p->out);
5864#endif
5865 }else{
5866 output_file_close(p->out);
drh04a28c32018-01-31 01:38:44 +00005867#ifndef SQLITE_NOHAVE_SYSTEM
drh13c20932018-01-10 21:41:55 +00005868 if( p->doXdgOpen ){
5869 const char *zXdgOpenCmd =
5870#if defined(_WIN32)
5871 "start";
5872#elif defined(__APPLE__)
5873 "open";
5874#else
5875 "xdg-open";
5876#endif
5877 char *zCmd;
5878 zCmd = sqlite3_mprintf("%s %s", zXdgOpenCmd, p->zTempFile);
drha92a01a2018-01-10 22:15:37 +00005879 if( system(zCmd) ){
5880 utf8_printf(stderr, "Failed: [%s]\n", zCmd);
drh1d9ea272020-04-17 23:46:54 +00005881 }else{
5882 /* Give the start/open/xdg-open command some time to get
5883 ** going before we continue, and potential delete the
5884 ** p->zTempFile data file out from under it */
5885 sqlite3_sleep(2000);
drha92a01a2018-01-10 22:15:37 +00005886 }
drh13c20932018-01-10 21:41:55 +00005887 sqlite3_free(zCmd);
drh3c484e82018-01-10 22:27:21 +00005888 outputModePop(p);
drh13c20932018-01-10 21:41:55 +00005889 p->doXdgOpen = 0;
5890 }
drh04a28c32018-01-31 01:38:44 +00005891#endif /* !defined(SQLITE_NOHAVE_SYSTEM) */
drh2ce15c32017-07-11 13:34:40 +00005892 }
5893 p->outfile[0] = 0;
5894 p->out = stdout;
5895}
5896
5897/*
5898** Run an SQL command and return the single integer result.
5899*/
larrybr58a53d62022-02-10 03:21:48 +00005900static int db_int(sqlite3 *db, const char *zSql){
drh2ce15c32017-07-11 13:34:40 +00005901 sqlite3_stmt *pStmt;
5902 int res = 0;
larrybr58a53d62022-02-10 03:21:48 +00005903 sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
drh2ce15c32017-07-11 13:34:40 +00005904 if( pStmt && sqlite3_step(pStmt)==SQLITE_ROW ){
5905 res = sqlite3_column_int(pStmt,0);
5906 }
5907 sqlite3_finalize(pStmt);
5908 return res;
5909}
5910
drh04836682022-06-08 18:29:23 +00005911#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
drh2ce15c32017-07-11 13:34:40 +00005912/*
5913** Convert a 2-byte or 4-byte big-endian integer into a native integer
5914*/
5915static unsigned int get2byteInt(unsigned char *a){
5916 return (a[0]<<8) + a[1];
5917}
5918static unsigned int get4byteInt(unsigned char *a){
5919 return (a[0]<<24) + (a[1]<<16) + (a[2]<<8) + a[3];
5920}
5921
5922/*
drh76c12062020-01-14 13:13:19 +00005923** Implementation of the ".dbinfo" command.
drh2ce15c32017-07-11 13:34:40 +00005924**
5925** Return 1 on error, 2 to exit, and 0 otherwise.
5926*/
5927static int shell_dbinfo_command(ShellState *p, int nArg, char **azArg){
5928 static const struct { const char *zName; int ofst; } aField[] = {
5929 { "file change counter:", 24 },
5930 { "database page count:", 28 },
5931 { "freelist page count:", 36 },
5932 { "schema cookie:", 40 },
5933 { "schema format:", 44 },
5934 { "default cache size:", 48 },
5935 { "autovacuum top root:", 52 },
5936 { "incremental vacuum:", 64 },
5937 { "text encoding:", 56 },
5938 { "user version:", 60 },
5939 { "application id:", 68 },
5940 { "software version:", 96 },
5941 };
5942 static const struct { const char *zName; const char *zSql; } aQuery[] = {
5943 { "number of tables:",
5944 "SELECT count(*) FROM %s WHERE type='table'" },
5945 { "number of indexes:",
5946 "SELECT count(*) FROM %s WHERE type='index'" },
5947 { "number of triggers:",
5948 "SELECT count(*) FROM %s WHERE type='trigger'" },
5949 { "number of views:",
5950 "SELECT count(*) FROM %s WHERE type='view'" },
5951 { "schema size:",
5952 "SELECT total(length(sql)) FROM %s" },
5953 };
drh87c889c2019-03-20 18:22:51 +00005954 int i, rc;
drhea99a312018-07-18 19:09:07 +00005955 unsigned iDataVersion;
drh2ce15c32017-07-11 13:34:40 +00005956 char *zSchemaTab;
5957 char *zDb = nArg>=2 ? azArg[1] : "main";
drh512e6c32017-10-11 17:51:08 +00005958 sqlite3_stmt *pStmt = 0;
drh2ce15c32017-07-11 13:34:40 +00005959 unsigned char aHdr[100];
5960 open_db(p, 0);
5961 if( p->db==0 ) return 1;
drh87c889c2019-03-20 18:22:51 +00005962 rc = sqlite3_prepare_v2(p->db,
5963 "SELECT data FROM sqlite_dbpage(?1) WHERE pgno=1",
5964 -1, &pStmt, 0);
5965 if( rc ){
drh451f89a2020-04-28 23:09:56 +00005966 utf8_printf(stderr, "error: %s\n", sqlite3_errmsg(p->db));
drh87c889c2019-03-20 18:22:51 +00005967 sqlite3_finalize(pStmt);
5968 return 1;
5969 }
drh512e6c32017-10-11 17:51:08 +00005970 sqlite3_bind_text(pStmt, 1, zDb, -1, SQLITE_STATIC);
5971 if( sqlite3_step(pStmt)==SQLITE_ROW
5972 && sqlite3_column_bytes(pStmt,0)>100
5973 ){
5974 memcpy(aHdr, sqlite3_column_blob(pStmt,0), 100);
5975 sqlite3_finalize(pStmt);
5976 }else{
drh2ce15c32017-07-11 13:34:40 +00005977 raw_printf(stderr, "unable to read database header\n");
drh512e6c32017-10-11 17:51:08 +00005978 sqlite3_finalize(pStmt);
drh2ce15c32017-07-11 13:34:40 +00005979 return 1;
5980 }
5981 i = get2byteInt(aHdr+16);
5982 if( i==1 ) i = 65536;
5983 utf8_printf(p->out, "%-20s %d\n", "database page size:", i);
5984 utf8_printf(p->out, "%-20s %d\n", "write format:", aHdr[18]);
5985 utf8_printf(p->out, "%-20s %d\n", "read format:", aHdr[19]);
5986 utf8_printf(p->out, "%-20s %d\n", "reserved bytes:", aHdr[20]);
5987 for(i=0; i<ArraySize(aField); i++){
5988 int ofst = aField[i].ofst;
5989 unsigned int val = get4byteInt(aHdr + ofst);
5990 utf8_printf(p->out, "%-20s %u", aField[i].zName, val);
5991 switch( ofst ){
5992 case 56: {
5993 if( val==1 ) raw_printf(p->out, " (utf8)");
5994 if( val==2 ) raw_printf(p->out, " (utf16le)");
5995 if( val==3 ) raw_printf(p->out, " (utf16be)");
5996 }
5997 }
5998 raw_printf(p->out, "\n");
5999 }
6000 if( zDb==0 ){
drh067b92b2020-06-19 15:24:12 +00006001 zSchemaTab = sqlite3_mprintf("main.sqlite_schema");
drhbf70f1b2022-10-19 18:04:42 +00006002 }else if( cli_strcmp(zDb,"temp")==0 ){
drh067b92b2020-06-19 15:24:12 +00006003 zSchemaTab = sqlite3_mprintf("%s", "sqlite_temp_schema");
drh2ce15c32017-07-11 13:34:40 +00006004 }else{
drh067b92b2020-06-19 15:24:12 +00006005 zSchemaTab = sqlite3_mprintf("\"%w\".sqlite_schema", zDb);
drh2ce15c32017-07-11 13:34:40 +00006006 }
6007 for(i=0; i<ArraySize(aQuery); i++){
6008 char *zSql = sqlite3_mprintf(aQuery[i].zSql, zSchemaTab);
larrybr58a53d62022-02-10 03:21:48 +00006009 int val = db_int(p->db, zSql);
drh2ce15c32017-07-11 13:34:40 +00006010 sqlite3_free(zSql);
6011 utf8_printf(p->out, "%-20s %d\n", aQuery[i].zName, val);
6012 }
6013 sqlite3_free(zSchemaTab);
drhea99a312018-07-18 19:09:07 +00006014 sqlite3_file_control(p->db, zDb, SQLITE_FCNTL_DATA_VERSION, &iDataVersion);
6015 utf8_printf(p->out, "%-20s %u\n", "data version", iDataVersion);
drh2ce15c32017-07-11 13:34:40 +00006016 return 0;
6017}
stephan3d420832022-10-27 03:56:01 +00006018#endif /* SQLITE_SHELL_HAVE_RECOVER */
drh2ce15c32017-07-11 13:34:40 +00006019
6020/*
6021** Print the current sqlite3_errmsg() value to stderr and return 1.
6022*/
6023static int shellDatabaseError(sqlite3 *db){
6024 const char *zErr = sqlite3_errmsg(db);
6025 utf8_printf(stderr, "Error: %s\n", zErr);
6026 return 1;
6027}
6028
6029/*
drh2ce15c32017-07-11 13:34:40 +00006030** Compare the pattern in zGlob[] against the text in z[]. Return TRUE
6031** if they match and FALSE (0) if they do not match.
6032**
6033** Globbing rules:
6034**
6035** '*' Matches any sequence of zero or more characters.
6036**
6037** '?' Matches exactly one character.
6038**
6039** [...] Matches one character from the enclosed list of
6040** characters.
6041**
6042** [^...] Matches one character not in the enclosed list.
6043**
6044** '#' Matches any sequence of one or more digits with an
6045** optional + or - sign in front
6046**
6047** ' ' Any span of whitespace matches any other span of
6048** whitespace.
6049**
6050** Extra whitespace at the end of z[] is ignored.
6051*/
6052static int testcase_glob(const char *zGlob, const char *z){
6053 int c, c2;
6054 int invert;
6055 int seen;
6056
6057 while( (c = (*(zGlob++)))!=0 ){
6058 if( IsSpace(c) ){
6059 if( !IsSpace(*z) ) return 0;
6060 while( IsSpace(*zGlob) ) zGlob++;
6061 while( IsSpace(*z) ) z++;
6062 }else if( c=='*' ){
6063 while( (c=(*(zGlob++))) == '*' || c=='?' ){
6064 if( c=='?' && (*(z++))==0 ) return 0;
6065 }
6066 if( c==0 ){
6067 return 1;
6068 }else if( c=='[' ){
6069 while( *z && testcase_glob(zGlob-1,z)==0 ){
6070 z++;
6071 }
6072 return (*z)!=0;
6073 }
6074 while( (c2 = (*(z++)))!=0 ){
6075 while( c2!=c ){
6076 c2 = *(z++);
6077 if( c2==0 ) return 0;
6078 }
6079 if( testcase_glob(zGlob,z) ) return 1;
6080 }
6081 return 0;
6082 }else if( c=='?' ){
6083 if( (*(z++))==0 ) return 0;
6084 }else if( c=='[' ){
6085 int prior_c = 0;
6086 seen = 0;
6087 invert = 0;
6088 c = *(z++);
6089 if( c==0 ) return 0;
6090 c2 = *(zGlob++);
6091 if( c2=='^' ){
6092 invert = 1;
6093 c2 = *(zGlob++);
6094 }
6095 if( c2==']' ){
6096 if( c==']' ) seen = 1;
6097 c2 = *(zGlob++);
6098 }
6099 while( c2 && c2!=']' ){
6100 if( c2=='-' && zGlob[0]!=']' && zGlob[0]!=0 && prior_c>0 ){
6101 c2 = *(zGlob++);
6102 if( c>=prior_c && c<=c2 ) seen = 1;
6103 prior_c = 0;
6104 }else{
6105 if( c==c2 ){
6106 seen = 1;
6107 }
6108 prior_c = c2;
6109 }
6110 c2 = *(zGlob++);
6111 }
6112 if( c2==0 || (seen ^ invert)==0 ) return 0;
6113 }else if( c=='#' ){
6114 if( (z[0]=='-' || z[0]=='+') && IsDigit(z[1]) ) z++;
6115 if( !IsDigit(z[0]) ) return 0;
6116 z++;
6117 while( IsDigit(z[0]) ){ z++; }
6118 }else{
6119 if( c!=(*(z++)) ) return 0;
6120 }
6121 }
6122 while( IsSpace(*z) ){ z++; }
6123 return *z==0;
6124}
6125
6126
6127/*
6128** Compare the string as a command-line option with either one or two
6129** initial "-" characters.
6130*/
6131static int optionMatch(const char *zStr, const char *zOpt){
6132 if( zStr[0]!='-' ) return 0;
6133 zStr++;
6134 if( zStr[0]=='-' ) zStr++;
drhbf70f1b2022-10-19 18:04:42 +00006135 return cli_strcmp(zStr, zOpt)==0;
drh2ce15c32017-07-11 13:34:40 +00006136}
6137
6138/*
6139** Delete a file.
6140*/
6141int shellDeleteFile(const char *zFilename){
6142 int rc;
6143#ifdef _WIN32
6144 wchar_t *z = sqlite3_win32_utf8_to_unicode(zFilename);
6145 rc = _wunlink(z);
6146 sqlite3_free(z);
6147#else
6148 rc = unlink(zFilename);
6149#endif
6150 return rc;
6151}
6152
drh13c20932018-01-10 21:41:55 +00006153/*
6154** Try to delete the temporary file (if there is one) and free the
6155** memory used to hold the name of the temp file.
6156*/
6157static void clearTempFile(ShellState *p){
6158 if( p->zTempFile==0 ) return;
drh536c3452018-01-11 00:38:39 +00006159 if( p->doXdgOpen ) return;
drh13c20932018-01-10 21:41:55 +00006160 if( shellDeleteFile(p->zTempFile) ) return;
6161 sqlite3_free(p->zTempFile);
6162 p->zTempFile = 0;
6163}
6164
6165/*
6166** Create a new temp file name with the given suffix.
6167*/
6168static void newTempFile(ShellState *p, const char *zSuffix){
6169 clearTempFile(p);
6170 sqlite3_free(p->zTempFile);
6171 p->zTempFile = 0;
drh7f3bf8a2018-01-10 21:50:08 +00006172 if( p->db ){
6173 sqlite3_file_control(p->db, 0, SQLITE_FCNTL_TEMPFILENAME, &p->zTempFile);
6174 }
drh13c20932018-01-10 21:41:55 +00006175 if( p->zTempFile==0 ){
drh1d9ea272020-04-17 23:46:54 +00006176 /* If p->db is an in-memory database then the TEMPFILENAME file-control
6177 ** will not work and we will need to fallback to guessing */
6178 char *zTemp;
drh13c20932018-01-10 21:41:55 +00006179 sqlite3_uint64 r;
6180 sqlite3_randomness(sizeof(r), &r);
drh1d9ea272020-04-17 23:46:54 +00006181 zTemp = getenv("TEMP");
6182 if( zTemp==0 ) zTemp = getenv("TMP");
6183 if( zTemp==0 ){
6184#ifdef _WIN32
6185 zTemp = "\\tmp";
6186#else
6187 zTemp = "/tmp";
6188#endif
6189 }
6190 p->zTempFile = sqlite3_mprintf("%s/temp%llx.%s", zTemp, r, zSuffix);
drh13c20932018-01-10 21:41:55 +00006191 }else{
6192 p->zTempFile = sqlite3_mprintf("%z.%s", p->zTempFile, zSuffix);
6193 }
drhe3e25652021-12-16 13:29:28 +00006194 shell_check_oom(p->zTempFile);
drh13c20932018-01-10 21:41:55 +00006195}
6196
drh2ce15c32017-07-11 13:34:40 +00006197
6198/*
6199** The implementation of SQL scalar function fkey_collate_clause(), used
6200** by the ".lint fkey-indexes" command. This scalar function is always
6201** called with four arguments - the parent table name, the parent column name,
6202** the child table name and the child column name.
6203**
6204** fkey_collate_clause('parent-tab', 'parent-col', 'child-tab', 'child-col')
6205**
6206** If either of the named tables or columns do not exist, this function
6207** returns an empty string. An empty string is also returned if both tables
6208** and columns exist but have the same default collation sequence. Or,
6209** if both exist but the default collation sequences are different, this
6210** function returns the string " COLLATE <parent-collation>", where
6211** <parent-collation> is the default collation sequence of the parent column.
6212*/
6213static void shellFkeyCollateClause(
6214 sqlite3_context *pCtx,
6215 int nVal,
6216 sqlite3_value **apVal
6217){
6218 sqlite3 *db = sqlite3_context_db_handle(pCtx);
6219 const char *zParent;
6220 const char *zParentCol;
6221 const char *zParentSeq;
6222 const char *zChild;
6223 const char *zChildCol;
6224 const char *zChildSeq = 0; /* Initialize to avoid false-positive warning */
6225 int rc;
6226
6227 assert( nVal==4 );
6228 zParent = (const char*)sqlite3_value_text(apVal[0]);
6229 zParentCol = (const char*)sqlite3_value_text(apVal[1]);
6230 zChild = (const char*)sqlite3_value_text(apVal[2]);
6231 zChildCol = (const char*)sqlite3_value_text(apVal[3]);
6232
6233 sqlite3_result_text(pCtx, "", -1, SQLITE_STATIC);
6234 rc = sqlite3_table_column_metadata(
6235 db, "main", zParent, zParentCol, 0, &zParentSeq, 0, 0, 0
6236 );
6237 if( rc==SQLITE_OK ){
6238 rc = sqlite3_table_column_metadata(
6239 db, "main", zChild, zChildCol, 0, &zChildSeq, 0, 0, 0
6240 );
6241 }
6242
6243 if( rc==SQLITE_OK && sqlite3_stricmp(zParentSeq, zChildSeq) ){
6244 char *z = sqlite3_mprintf(" COLLATE %s", zParentSeq);
6245 sqlite3_result_text(pCtx, z, -1, SQLITE_TRANSIENT);
6246 sqlite3_free(z);
6247 }
6248}
6249
6250
6251/*
6252** The implementation of dot-command ".lint fkey-indexes".
6253*/
6254static int lintFkeyIndexes(
6255 ShellState *pState, /* Current shell tool state */
6256 char **azArg, /* Array of arguments passed to dot command */
6257 int nArg /* Number of entries in azArg[] */
6258){
6259 sqlite3 *db = pState->db; /* Database handle to query "main" db of */
6260 FILE *out = pState->out; /* Stream to write non-error output to */
6261 int bVerbose = 0; /* If -verbose is present */
6262 int bGroupByParent = 0; /* If -groupbyparent is present */
6263 int i; /* To iterate through azArg[] */
6264 const char *zIndent = ""; /* How much to indent CREATE INDEX by */
6265 int rc; /* Return code */
6266 sqlite3_stmt *pSql = 0; /* Compiled version of SQL statement below */
6267
6268 /*
6269 ** This SELECT statement returns one row for each foreign key constraint
6270 ** in the schema of the main database. The column values are:
6271 **
6272 ** 0. The text of an SQL statement similar to:
6273 **
danf9679312017-12-01 18:40:18 +00006274 ** "EXPLAIN QUERY PLAN SELECT 1 FROM child_table WHERE child_key=?"
drh2ce15c32017-07-11 13:34:40 +00006275 **
danf9679312017-12-01 18:40:18 +00006276 ** This SELECT is similar to the one that the foreign keys implementation
6277 ** needs to run internally on child tables. If there is an index that can
drh2ce15c32017-07-11 13:34:40 +00006278 ** be used to optimize this query, then it can also be used by the FK
6279 ** implementation to optimize DELETE or UPDATE statements on the parent
6280 ** table.
6281 **
6282 ** 1. A GLOB pattern suitable for sqlite3_strglob(). If the plan output by
6283 ** the EXPLAIN QUERY PLAN command matches this pattern, then the schema
6284 ** contains an index that can be used to optimize the query.
6285 **
6286 ** 2. Human readable text that describes the child table and columns. e.g.
6287 **
6288 ** "child_table(child_key1, child_key2)"
6289 **
6290 ** 3. Human readable text that describes the parent table and columns. e.g.
6291 **
6292 ** "parent_table(parent_key1, parent_key2)"
6293 **
6294 ** 4. A full CREATE INDEX statement for an index that could be used to
6295 ** optimize DELETE or UPDATE statements on the parent table. e.g.
6296 **
6297 ** "CREATE INDEX child_table_child_key ON child_table(child_key)"
6298 **
6299 ** 5. The name of the parent table.
6300 **
6301 ** These six values are used by the C logic below to generate the report.
6302 */
6303 const char *zSql =
6304 "SELECT "
danf9679312017-12-01 18:40:18 +00006305 " 'EXPLAIN QUERY PLAN SELECT 1 FROM ' || quote(s.name) || ' WHERE '"
drh2ce15c32017-07-11 13:34:40 +00006306 " || group_concat(quote(s.name) || '.' || quote(f.[from]) || '=?' "
6307 " || fkey_collate_clause("
6308 " f.[table], COALESCE(f.[to], p.[name]), s.name, f.[from]),' AND ')"
6309 ", "
drh82102332021-03-20 15:11:29 +00006310 " 'SEARCH ' || s.name || ' USING COVERING INDEX*('"
drh2ce15c32017-07-11 13:34:40 +00006311 " || group_concat('*=?', ' AND ') || ')'"
6312 ", "
6313 " s.name || '(' || group_concat(f.[from], ', ') || ')'"
6314 ", "
6315 " f.[table] || '(' || group_concat(COALESCE(f.[to], p.[name])) || ')'"
6316 ", "
6317 " 'CREATE INDEX ' || quote(s.name ||'_'|| group_concat(f.[from], '_'))"
6318 " || ' ON ' || quote(s.name) || '('"
6319 " || group_concat(quote(f.[from]) ||"
6320 " fkey_collate_clause("
6321 " f.[table], COALESCE(f.[to], p.[name]), s.name, f.[from]), ', ')"
6322 " || ');'"
6323 ", "
6324 " f.[table] "
drh067b92b2020-06-19 15:24:12 +00006325 "FROM sqlite_schema AS s, pragma_foreign_key_list(s.name) AS f "
drh2ce15c32017-07-11 13:34:40 +00006326 "LEFT JOIN pragma_table_info AS p ON (pk-1=seq AND p.arg=f.[table]) "
6327 "GROUP BY s.name, f.id "
6328 "ORDER BY (CASE WHEN ? THEN f.[table] ELSE s.name END)"
6329 ;
drh82102332021-03-20 15:11:29 +00006330 const char *zGlobIPK = "SEARCH * USING INTEGER PRIMARY KEY (rowid=?)";
drh2ce15c32017-07-11 13:34:40 +00006331
6332 for(i=2; i<nArg; i++){
drhaf2770f2018-01-05 14:55:43 +00006333 int n = strlen30(azArg[i]);
drh2ce15c32017-07-11 13:34:40 +00006334 if( n>1 && sqlite3_strnicmp("-verbose", azArg[i], n)==0 ){
6335 bVerbose = 1;
6336 }
6337 else if( n>1 && sqlite3_strnicmp("-groupbyparent", azArg[i], n)==0 ){
6338 bGroupByParent = 1;
6339 zIndent = " ";
6340 }
6341 else{
6342 raw_printf(stderr, "Usage: %s %s ?-verbose? ?-groupbyparent?\n",
6343 azArg[0], azArg[1]
6344 );
6345 return SQLITE_ERROR;
6346 }
6347 }
6348
6349 /* Register the fkey_collate_clause() SQL function */
6350 rc = sqlite3_create_function(db, "fkey_collate_clause", 4, SQLITE_UTF8,
6351 0, shellFkeyCollateClause, 0, 0
6352 );
6353
6354
6355 if( rc==SQLITE_OK ){
6356 rc = sqlite3_prepare_v2(db, zSql, -1, &pSql, 0);
6357 }
6358 if( rc==SQLITE_OK ){
6359 sqlite3_bind_int(pSql, 1, bGroupByParent);
6360 }
6361
6362 if( rc==SQLITE_OK ){
6363 int rc2;
6364 char *zPrev = 0;
6365 while( SQLITE_ROW==sqlite3_step(pSql) ){
6366 int res = -1;
6367 sqlite3_stmt *pExplain = 0;
6368 const char *zEQP = (const char*)sqlite3_column_text(pSql, 0);
6369 const char *zGlob = (const char*)sqlite3_column_text(pSql, 1);
6370 const char *zFrom = (const char*)sqlite3_column_text(pSql, 2);
6371 const char *zTarget = (const char*)sqlite3_column_text(pSql, 3);
6372 const char *zCI = (const char*)sqlite3_column_text(pSql, 4);
6373 const char *zParent = (const char*)sqlite3_column_text(pSql, 5);
6374
drh621a5e02021-12-16 17:35:27 +00006375 if( zEQP==0 ) continue;
6376 if( zGlob==0 ) continue;
drh2ce15c32017-07-11 13:34:40 +00006377 rc = sqlite3_prepare_v2(db, zEQP, -1, &pExplain, 0);
6378 if( rc!=SQLITE_OK ) break;
6379 if( SQLITE_ROW==sqlite3_step(pExplain) ){
6380 const char *zPlan = (const char*)sqlite3_column_text(pExplain, 3);
drh621a5e02021-12-16 17:35:27 +00006381 res = zPlan!=0 && ( 0==sqlite3_strglob(zGlob, zPlan)
6382 || 0==sqlite3_strglob(zGlobIPK, zPlan));
drh2ce15c32017-07-11 13:34:40 +00006383 }
6384 rc = sqlite3_finalize(pExplain);
6385 if( rc!=SQLITE_OK ) break;
6386
6387 if( res<0 ){
6388 raw_printf(stderr, "Error: internal error");
6389 break;
6390 }else{
6391 if( bGroupByParent
6392 && (bVerbose || res==0)
6393 && (zPrev==0 || sqlite3_stricmp(zParent, zPrev))
6394 ){
6395 raw_printf(out, "-- Parent table %s\n", zParent);
6396 sqlite3_free(zPrev);
6397 zPrev = sqlite3_mprintf("%s", zParent);
6398 }
6399
6400 if( res==0 ){
6401 raw_printf(out, "%s%s --> %s\n", zIndent, zCI, zTarget);
6402 }else if( bVerbose ){
6403 raw_printf(out, "%s/* no extra indexes required for %s -> %s */\n",
6404 zIndent, zFrom, zTarget
6405 );
6406 }
6407 }
6408 }
6409 sqlite3_free(zPrev);
6410
6411 if( rc!=SQLITE_OK ){
6412 raw_printf(stderr, "%s\n", sqlite3_errmsg(db));
6413 }
6414
6415 rc2 = sqlite3_finalize(pSql);
6416 if( rc==SQLITE_OK && rc2!=SQLITE_OK ){
6417 rc = rc2;
6418 raw_printf(stderr, "%s\n", sqlite3_errmsg(db));
6419 }
6420 }else{
6421 raw_printf(stderr, "%s\n", sqlite3_errmsg(db));
6422 }
6423
6424 return rc;
6425}
6426
6427/*
6428** Implementation of ".lint" dot command.
6429*/
6430static int lintDotCommand(
6431 ShellState *pState, /* Current shell tool state */
6432 char **azArg, /* Array of arguments passed to dot command */
6433 int nArg /* Number of entries in azArg[] */
6434){
6435 int n;
drhaf2770f2018-01-05 14:55:43 +00006436 n = (nArg>=2 ? strlen30(azArg[1]) : 0);
drh2ce15c32017-07-11 13:34:40 +00006437 if( n<1 || sqlite3_strnicmp(azArg[1], "fkey-indexes", n) ) goto usage;
6438 return lintFkeyIndexes(pState, azArg, nArg);
6439
6440 usage:
6441 raw_printf(stderr, "Usage %s sub-command ?switches...?\n", azArg[0]);
6442 raw_printf(stderr, "Where sub-commands are:\n");
6443 raw_printf(stderr, " fkey-indexes\n");
6444 return SQLITE_ERROR;
6445}
6446
dan1b162162019-04-27 20:15:15 +00006447#if !defined SQLITE_OMIT_VIRTUALTABLE
danfd0245d2017-12-07 15:44:29 +00006448static void shellPrepare(
dand4b56e52017-12-12 20:04:59 +00006449 sqlite3 *db,
danfd0245d2017-12-07 15:44:29 +00006450 int *pRc,
6451 const char *zSql,
6452 sqlite3_stmt **ppStmt
6453){
6454 *ppStmt = 0;
6455 if( *pRc==SQLITE_OK ){
dand4b56e52017-12-12 20:04:59 +00006456 int rc = sqlite3_prepare_v2(db, zSql, -1, ppStmt, 0);
danfd0245d2017-12-07 15:44:29 +00006457 if( rc!=SQLITE_OK ){
6458 raw_printf(stderr, "sql error: %s (%d)\n",
dand4b56e52017-12-12 20:04:59 +00006459 sqlite3_errmsg(db), sqlite3_errcode(db)
danfd0245d2017-12-07 15:44:29 +00006460 );
6461 *pRc = rc;
6462 }
6463 }
6464}
6465
drh9546c762019-05-10 17:50:33 +00006466/*
6467** Create a prepared statement using printf-style arguments for the SQL.
6468**
6469** This routine is could be marked "static". But it is not always used,
6470** depending on compile-time options. By omitting the "static", we avoid
6471** nuisance compiler warnings about "defined but not used".
6472*/
6473void shellPreparePrintf(
dan3f67ddf2017-12-13 20:04:53 +00006474 sqlite3 *db,
6475 int *pRc,
danac15e2d2017-12-14 19:15:07 +00006476 sqlite3_stmt **ppStmt,
6477 const char *zFmt,
6478 ...
dan3f67ddf2017-12-13 20:04:53 +00006479){
danac15e2d2017-12-14 19:15:07 +00006480 *ppStmt = 0;
6481 if( *pRc==SQLITE_OK ){
6482 va_list ap;
6483 char *z;
6484 va_start(ap, zFmt);
6485 z = sqlite3_vmprintf(zFmt, ap);
drh1dbb1472018-10-11 10:37:24 +00006486 va_end(ap);
dan3f67ddf2017-12-13 20:04:53 +00006487 if( z==0 ){
6488 *pRc = SQLITE_NOMEM;
6489 }else{
6490 shellPrepare(db, pRc, z, ppStmt);
6491 sqlite3_free(z);
6492 }
dan3f67ddf2017-12-13 20:04:53 +00006493 }
6494}
6495
drh9546c762019-05-10 17:50:33 +00006496/* Finalize the prepared statement created using shellPreparePrintf().
6497**
6498** This routine is could be marked "static". But it is not always used,
6499** depending on compile-time options. By omitting the "static", we avoid
6500** nuisance compiler warnings about "defined but not used".
6501*/
6502void shellFinalize(
danfd0245d2017-12-07 15:44:29 +00006503 int *pRc,
6504 sqlite3_stmt *pStmt
6505){
dan25c12182017-12-07 21:03:33 +00006506 if( pStmt ){
6507 sqlite3 *db = sqlite3_db_handle(pStmt);
6508 int rc = sqlite3_finalize(pStmt);
6509 if( *pRc==SQLITE_OK ){
6510 if( rc!=SQLITE_OK ){
6511 raw_printf(stderr, "SQL error: %s\n", sqlite3_errmsg(db));
6512 }
6513 *pRc = rc;
6514 }
6515 }
danfd0245d2017-12-07 15:44:29 +00006516}
6517
drh9546c762019-05-10 17:50:33 +00006518/* Reset the prepared statement created using shellPreparePrintf().
6519**
6520** This routine is could be marked "static". But it is not always used,
6521** depending on compile-time options. By omitting the "static", we avoid
6522** nuisance compiler warnings about "defined but not used".
6523*/
6524void shellReset(
danfd0245d2017-12-07 15:44:29 +00006525 int *pRc,
6526 sqlite3_stmt *pStmt
6527){
6528 int rc = sqlite3_reset(pStmt);
dan5a78b812017-12-27 18:54:11 +00006529 if( *pRc==SQLITE_OK ){
6530 if( rc!=SQLITE_OK ){
6531 sqlite3 *db = sqlite3_db_handle(pStmt);
6532 raw_printf(stderr, "SQL error: %s\n", sqlite3_errmsg(db));
6533 }
6534 *pRc = rc;
6535 }
danfd0245d2017-12-07 15:44:29 +00006536}
dan1b162162019-04-27 20:15:15 +00006537#endif /* !defined SQLITE_OMIT_VIRTUALTABLE */
6538
6539#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
drhe2754c12019-08-26 12:50:01 +00006540/******************************************************************************
dan1b162162019-04-27 20:15:15 +00006541** The ".archive" or ".ar" command.
6542*/
drhe37c0e12018-01-06 19:19:50 +00006543/*
dan88be0202017-12-09 17:58:02 +00006544** Structure representing a single ".ar" command.
6545*/
6546typedef struct ArCommand ArCommand;
6547struct ArCommand {
drhb376b3d2018-01-10 13:11:51 +00006548 u8 eCmd; /* An AR_CMD_* value */
6549 u8 bVerbose; /* True if --verbose */
drha5676c42018-01-10 15:17:34 +00006550 u8 bZip; /* True if the archive is a ZIP */
drhb376b3d2018-01-10 13:11:51 +00006551 u8 bDryRun; /* True if --dry-run */
drha5676c42018-01-10 15:17:34 +00006552 u8 bAppend; /* True if --append */
larrybr8f09f4b2021-11-02 00:18:11 +00006553 u8 bGlob; /* True if --glob */
drhd0f9cdc2018-05-17 14:09:06 +00006554 u8 fromCmdLine; /* Run from -A instead of .archive */
drhb376b3d2018-01-10 13:11:51 +00006555 int nArg; /* Number of command arguments */
drha5676c42018-01-10 15:17:34 +00006556 char *zSrcTable; /* "sqlar", "zipfile($file)" or "zip" */
dan88be0202017-12-09 17:58:02 +00006557 const char *zFile; /* --file argument, or NULL */
6558 const char *zDir; /* --directory argument, or NULL */
dan88be0202017-12-09 17:58:02 +00006559 char **azArg; /* Array of command arguments */
drhb376b3d2018-01-10 13:11:51 +00006560 ShellState *p; /* Shell state */
6561 sqlite3 *db; /* Database containing the archive */
dan88be0202017-12-09 17:58:02 +00006562};
6563
6564/*
6565** Print a usage message for the .ar command to stderr and return SQLITE_ERROR.
6566*/
dan0d0547f2017-12-14 15:40:42 +00006567static int arUsage(FILE *f){
drh98aa2ab2018-09-26 16:53:51 +00006568 showHelp(f,"archive");
dan0d0547f2017-12-14 15:40:42 +00006569 return SQLITE_ERROR;
6570}
6571
6572/*
6573** Print an error message for the .ar command to stderr and return
6574** SQLITE_ERROR.
6575*/
drhd0f9cdc2018-05-17 14:09:06 +00006576static int arErrorMsg(ArCommand *pAr, const char *zFmt, ...){
dan0d0547f2017-12-14 15:40:42 +00006577 va_list ap;
6578 char *z;
6579 va_start(ap, zFmt);
6580 z = sqlite3_vmprintf(zFmt, ap);
6581 va_end(ap);
drhd0f9cdc2018-05-17 14:09:06 +00006582 utf8_printf(stderr, "Error: %s\n", z);
6583 if( pAr->fromCmdLine ){
6584 utf8_printf(stderr, "Use \"-A\" for more help\n");
6585 }else{
6586 utf8_printf(stderr, "Use \".archive --help\" for more help\n");
6587 }
dan0d0547f2017-12-14 15:40:42 +00006588 sqlite3_free(z);
dan88be0202017-12-09 17:58:02 +00006589 return SQLITE_ERROR;
6590}
6591
6592/*
6593** Values for ArCommand.eCmd.
6594*/
dand4b56e52017-12-12 20:04:59 +00006595#define AR_CMD_CREATE 1
drhb17ea912019-03-25 14:24:19 +00006596#define AR_CMD_UPDATE 2
6597#define AR_CMD_INSERT 3
6598#define AR_CMD_EXTRACT 4
6599#define AR_CMD_LIST 5
6600#define AR_CMD_HELP 6
larrybr47061b92021-11-01 17:22:52 +00006601#define AR_CMD_REMOVE 7
dand4b56e52017-12-12 20:04:59 +00006602
6603/*
6604** Other (non-command) switches.
6605*/
larrybr47061b92021-11-01 17:22:52 +00006606#define AR_SWITCH_VERBOSE 8
6607#define AR_SWITCH_FILE 9
6608#define AR_SWITCH_DIRECTORY 10
6609#define AR_SWITCH_APPEND 11
larrybr719506f2021-11-01 22:33:20 +00006610#define AR_SWITCH_DRYRUN 12
larrybr8f09f4b2021-11-02 00:18:11 +00006611#define AR_SWITCH_GLOB 13
dand4b56e52017-12-12 20:04:59 +00006612
6613static int arProcessSwitch(ArCommand *pAr, int eSwitch, const char *zArg){
6614 switch( eSwitch ){
6615 case AR_CMD_CREATE:
6616 case AR_CMD_EXTRACT:
6617 case AR_CMD_LIST:
larrybr47061b92021-11-01 17:22:52 +00006618 case AR_CMD_REMOVE:
dand4b56e52017-12-12 20:04:59 +00006619 case AR_CMD_UPDATE:
drhb17ea912019-03-25 14:24:19 +00006620 case AR_CMD_INSERT:
dan0d0547f2017-12-14 15:40:42 +00006621 case AR_CMD_HELP:
6622 if( pAr->eCmd ){
drhd0f9cdc2018-05-17 14:09:06 +00006623 return arErrorMsg(pAr, "multiple command options");
dan0d0547f2017-12-14 15:40:42 +00006624 }
dand4b56e52017-12-12 20:04:59 +00006625 pAr->eCmd = eSwitch;
6626 break;
6627
drhb376b3d2018-01-10 13:11:51 +00006628 case AR_SWITCH_DRYRUN:
6629 pAr->bDryRun = 1;
6630 break;
larrybr8f09f4b2021-11-02 00:18:11 +00006631 case AR_SWITCH_GLOB:
6632 pAr->bGlob = 1;
6633 break;
dand4b56e52017-12-12 20:04:59 +00006634 case AR_SWITCH_VERBOSE:
6635 pAr->bVerbose = 1;
6636 break;
drha5676c42018-01-10 15:17:34 +00006637 case AR_SWITCH_APPEND:
6638 pAr->bAppend = 1;
drhca7733b2018-01-10 18:09:20 +00006639 /* Fall thru into --file */
dand4b56e52017-12-12 20:04:59 +00006640 case AR_SWITCH_FILE:
6641 pAr->zFile = zArg;
6642 break;
6643 case AR_SWITCH_DIRECTORY:
6644 pAr->zDir = zArg;
6645 break;
6646 }
6647
6648 return SQLITE_OK;
6649}
dan88be0202017-12-09 17:58:02 +00006650
6651/*
6652** Parse the command line for an ".ar" command. The results are written into
6653** structure (*pAr). SQLITE_OK is returned if the command line is parsed
6654** successfully, otherwise an error message is written to stderr and
6655** SQLITE_ERROR returned.
6656*/
6657static int arParseCommand(
6658 char **azArg, /* Array of arguments passed to dot command */
6659 int nArg, /* Number of entries in azArg[] */
6660 ArCommand *pAr /* Populate this object */
6661){
dand4b56e52017-12-12 20:04:59 +00006662 struct ArSwitch {
dand4b56e52017-12-12 20:04:59 +00006663 const char *zLong;
drhb376b3d2018-01-10 13:11:51 +00006664 char cShort;
6665 u8 eSwitch;
6666 u8 bArg;
dand4b56e52017-12-12 20:04:59 +00006667 } aSwitch[] = {
drhb376b3d2018-01-10 13:11:51 +00006668 { "create", 'c', AR_CMD_CREATE, 0 },
6669 { "extract", 'x', AR_CMD_EXTRACT, 0 },
drhb17ea912019-03-25 14:24:19 +00006670 { "insert", 'i', AR_CMD_INSERT, 0 },
drhb376b3d2018-01-10 13:11:51 +00006671 { "list", 't', AR_CMD_LIST, 0 },
larrybr47061b92021-11-01 17:22:52 +00006672 { "remove", 'r', AR_CMD_REMOVE, 0 },
drhb376b3d2018-01-10 13:11:51 +00006673 { "update", 'u', AR_CMD_UPDATE, 0 },
6674 { "help", 'h', AR_CMD_HELP, 0 },
6675 { "verbose", 'v', AR_SWITCH_VERBOSE, 0 },
6676 { "file", 'f', AR_SWITCH_FILE, 1 },
drhca7733b2018-01-10 18:09:20 +00006677 { "append", 'a', AR_SWITCH_APPEND, 1 },
drhb376b3d2018-01-10 13:11:51 +00006678 { "directory", 'C', AR_SWITCH_DIRECTORY, 1 },
drhb376b3d2018-01-10 13:11:51 +00006679 { "dryrun", 'n', AR_SWITCH_DRYRUN, 0 },
larrybr8f09f4b2021-11-02 00:18:11 +00006680 { "glob", 'g', AR_SWITCH_GLOB, 0 },
dand4b56e52017-12-12 20:04:59 +00006681 };
6682 int nSwitch = sizeof(aSwitch) / sizeof(struct ArSwitch);
6683 struct ArSwitch *pEnd = &aSwitch[nSwitch];
6684
dan88be0202017-12-09 17:58:02 +00006685 if( nArg<=1 ){
drh98aa2ab2018-09-26 16:53:51 +00006686 utf8_printf(stderr, "Wrong number of arguments. Usage:\n");
dan0d0547f2017-12-14 15:40:42 +00006687 return arUsage(stderr);
dan88be0202017-12-09 17:58:02 +00006688 }else{
6689 char *z = azArg[1];
dan88be0202017-12-09 17:58:02 +00006690 if( z[0]!='-' ){
6691 /* Traditional style [tar] invocation */
6692 int i;
6693 int iArg = 2;
6694 for(i=0; z[i]; i++){
dand4b56e52017-12-12 20:04:59 +00006695 const char *zArg = 0;
6696 struct ArSwitch *pOpt;
6697 for(pOpt=&aSwitch[0]; pOpt<pEnd; pOpt++){
6698 if( z[i]==pOpt->cShort ) break;
dan88be0202017-12-09 17:58:02 +00006699 }
dan0d0547f2017-12-14 15:40:42 +00006700 if( pOpt==pEnd ){
drhd0f9cdc2018-05-17 14:09:06 +00006701 return arErrorMsg(pAr, "unrecognized option: %c", z[i]);
dan0d0547f2017-12-14 15:40:42 +00006702 }
dand4b56e52017-12-12 20:04:59 +00006703 if( pOpt->bArg ){
dan0d0547f2017-12-14 15:40:42 +00006704 if( iArg>=nArg ){
drhd0f9cdc2018-05-17 14:09:06 +00006705 return arErrorMsg(pAr, "option requires an argument: %c",z[i]);
dan0d0547f2017-12-14 15:40:42 +00006706 }
dand4b56e52017-12-12 20:04:59 +00006707 zArg = azArg[iArg++];
6708 }
6709 if( arProcessSwitch(pAr, pOpt->eSwitch, zArg) ) return SQLITE_ERROR;
dan88be0202017-12-09 17:58:02 +00006710 }
dan88be0202017-12-09 17:58:02 +00006711 pAr->nArg = nArg-iArg;
6712 if( pAr->nArg>0 ){
6713 pAr->azArg = &azArg[iArg];
6714 }
dand4b56e52017-12-12 20:04:59 +00006715 }else{
6716 /* Non-traditional invocation */
6717 int iArg;
6718 for(iArg=1; iArg<nArg; iArg++){
6719 int n;
6720 z = azArg[iArg];
6721 if( z[0]!='-' ){
6722 /* All remaining command line words are command arguments. */
6723 pAr->azArg = &azArg[iArg];
6724 pAr->nArg = nArg-iArg;
6725 break;
6726 }
drhaf2770f2018-01-05 14:55:43 +00006727 n = strlen30(z);
dand4b56e52017-12-12 20:04:59 +00006728
6729 if( z[1]!='-' ){
6730 int i;
6731 /* One or more short options */
6732 for(i=1; i<n; i++){
6733 const char *zArg = 0;
6734 struct ArSwitch *pOpt;
6735 for(pOpt=&aSwitch[0]; pOpt<pEnd; pOpt++){
6736 if( z[i]==pOpt->cShort ) break;
6737 }
dan0d0547f2017-12-14 15:40:42 +00006738 if( pOpt==pEnd ){
drhd0f9cdc2018-05-17 14:09:06 +00006739 return arErrorMsg(pAr, "unrecognized option: %c", z[i]);
dan0d0547f2017-12-14 15:40:42 +00006740 }
dand4b56e52017-12-12 20:04:59 +00006741 if( pOpt->bArg ){
6742 if( i<(n-1) ){
6743 zArg = &z[i+1];
6744 i = n;
6745 }else{
dan0d0547f2017-12-14 15:40:42 +00006746 if( iArg>=(nArg-1) ){
drhe2754c12019-08-26 12:50:01 +00006747 return arErrorMsg(pAr, "option requires an argument: %c",
6748 z[i]);
dan0d0547f2017-12-14 15:40:42 +00006749 }
dand4b56e52017-12-12 20:04:59 +00006750 zArg = azArg[++iArg];
6751 }
6752 }
6753 if( arProcessSwitch(pAr, pOpt->eSwitch, zArg) ) return SQLITE_ERROR;
6754 }
6755 }else if( z[2]=='\0' ){
6756 /* A -- option, indicating that all remaining command line words
6757 ** are command arguments. */
6758 pAr->azArg = &azArg[iArg+1];
6759 pAr->nArg = nArg-iArg-1;
6760 break;
6761 }else{
6762 /* A long option */
6763 const char *zArg = 0; /* Argument for option, if any */
6764 struct ArSwitch *pMatch = 0; /* Matching option */
6765 struct ArSwitch *pOpt; /* Iterator */
6766 for(pOpt=&aSwitch[0]; pOpt<pEnd; pOpt++){
6767 const char *zLong = pOpt->zLong;
drhaf2770f2018-01-05 14:55:43 +00006768 if( (n-2)<=strlen30(zLong) && 0==memcmp(&z[2], zLong, n-2) ){
dand4b56e52017-12-12 20:04:59 +00006769 if( pMatch ){
drhd0f9cdc2018-05-17 14:09:06 +00006770 return arErrorMsg(pAr, "ambiguous option: %s",z);
dand4b56e52017-12-12 20:04:59 +00006771 }else{
6772 pMatch = pOpt;
6773 }
6774 }
6775 }
6776
6777 if( pMatch==0 ){
drhd0f9cdc2018-05-17 14:09:06 +00006778 return arErrorMsg(pAr, "unrecognized option: %s", z);
dand4b56e52017-12-12 20:04:59 +00006779 }
6780 if( pMatch->bArg ){
dan0d0547f2017-12-14 15:40:42 +00006781 if( iArg>=(nArg-1) ){
drhd0f9cdc2018-05-17 14:09:06 +00006782 return arErrorMsg(pAr, "option requires an argument: %s", z);
dan0d0547f2017-12-14 15:40:42 +00006783 }
dand4b56e52017-12-12 20:04:59 +00006784 zArg = azArg[++iArg];
6785 }
6786 if( arProcessSwitch(pAr, pMatch->eSwitch, zArg) ) return SQLITE_ERROR;
6787 }
6788 }
dan88be0202017-12-09 17:58:02 +00006789 }
6790 }
6791
6792 return SQLITE_OK;
6793}
6794
6795/*
dan3f67ddf2017-12-13 20:04:53 +00006796** This function assumes that all arguments within the ArCommand.azArg[]
larrybr47061b92021-11-01 17:22:52 +00006797** array refer to archive members, as for the --extract, --list or --remove
larrybr8f09f4b2021-11-02 00:18:11 +00006798** commands. It checks that each of them are "present". If any specified
6799** file is not present in the archive, an error is printed to stderr and an
larrybr47061b92021-11-01 17:22:52 +00006800** error code returned. Otherwise, if all specified arguments are present
larrybr8f09f4b2021-11-02 00:18:11 +00006801** in the archive, SQLITE_OK is returned. Here, "present" means either an
6802** exact equality when pAr->bGlob is false or a "name GLOB pattern" match
drh0c0fb9c2021-11-02 10:54:39 +00006803** when pAr->bGlob is true.
dan3f67ddf2017-12-13 20:04:53 +00006804**
6805** This function strips any trailing '/' characters from each argument.
6806** This is consistent with the way the [tar] command seems to work on
6807** Linux.
6808*/
drhb376b3d2018-01-10 13:11:51 +00006809static int arCheckEntries(ArCommand *pAr){
dan3f67ddf2017-12-13 20:04:53 +00006810 int rc = SQLITE_OK;
6811 if( pAr->nArg ){
drhb376b3d2018-01-10 13:11:51 +00006812 int i, j;
dan3f67ddf2017-12-13 20:04:53 +00006813 sqlite3_stmt *pTest = 0;
larrybr8f09f4b2021-11-02 00:18:11 +00006814 const char *zSel = (pAr->bGlob)
6815 ? "SELECT name FROM %s WHERE glob($name,name)"
6816 : "SELECT name FROM %s WHERE name=$name";
dan3f67ddf2017-12-13 20:04:53 +00006817
larrybr8f09f4b2021-11-02 00:18:11 +00006818 shellPreparePrintf(pAr->db, &rc, &pTest, zSel, pAr->zSrcTable);
drhb376b3d2018-01-10 13:11:51 +00006819 j = sqlite3_bind_parameter_index(pTest, "$name");
dan3f67ddf2017-12-13 20:04:53 +00006820 for(i=0; i<pAr->nArg && rc==SQLITE_OK; i++){
6821 char *z = pAr->azArg[i];
drhaf2770f2018-01-05 14:55:43 +00006822 int n = strlen30(z);
dan3f67ddf2017-12-13 20:04:53 +00006823 int bOk = 0;
6824 while( n>0 && z[n-1]=='/' ) n--;
6825 z[n] = '\0';
drhb376b3d2018-01-10 13:11:51 +00006826 sqlite3_bind_text(pTest, j, z, -1, SQLITE_STATIC);
dan3f67ddf2017-12-13 20:04:53 +00006827 if( SQLITE_ROW==sqlite3_step(pTest) ){
6828 bOk = 1;
6829 }
6830 shellReset(&rc, pTest);
6831 if( rc==SQLITE_OK && bOk==0 ){
drhb376b3d2018-01-10 13:11:51 +00006832 utf8_printf(stderr, "not found in archive: %s\n", z);
dan3f67ddf2017-12-13 20:04:53 +00006833 rc = SQLITE_ERROR;
6834 }
6835 }
6836 shellFinalize(&rc, pTest);
6837 }
dan3f67ddf2017-12-13 20:04:53 +00006838 return rc;
6839}
6840
6841/*
6842** Format a WHERE clause that can be used against the "sqlar" table to
6843** identify all archive members that match the command arguments held
6844** in (*pAr). Leave this WHERE clause in (*pzWhere) before returning.
6845** The caller is responsible for eventually calling sqlite3_free() on
larrybr8f09f4b2021-11-02 00:18:11 +00006846** any non-NULL (*pzWhere) value. Here, "match" means strict equality
6847** when pAr->bGlob is false and GLOB match when pAr->bGlob is true.
dan3f67ddf2017-12-13 20:04:53 +00006848*/
6849static void arWhereClause(
6850 int *pRc,
larrybr8f09f4b2021-11-02 00:18:11 +00006851 ArCommand *pAr,
danac15e2d2017-12-14 19:15:07 +00006852 char **pzWhere /* OUT: New WHERE clause */
dan3f67ddf2017-12-13 20:04:53 +00006853){
6854 char *zWhere = 0;
larrybr8f09f4b2021-11-02 00:18:11 +00006855 const char *zSameOp = (pAr->bGlob)? "GLOB" : "=";
dan3f67ddf2017-12-13 20:04:53 +00006856 if( *pRc==SQLITE_OK ){
danac15e2d2017-12-14 19:15:07 +00006857 if( pAr->nArg==0 ){
6858 zWhere = sqlite3_mprintf("1");
6859 }else{
6860 int i;
6861 const char *zSep = "";
6862 for(i=0; i<pAr->nArg; i++){
6863 const char *z = pAr->azArg[i];
6864 zWhere = sqlite3_mprintf(
larrybr8f09f4b2021-11-02 00:18:11 +00006865 "%z%s name %s '%q' OR substr(name,1,%d) %s '%q/'",
6866 zWhere, zSep, zSameOp, z, strlen30(z)+1, zSameOp, z
drhb376b3d2018-01-10 13:11:51 +00006867 );
danac15e2d2017-12-14 19:15:07 +00006868 if( zWhere==0 ){
6869 *pRc = SQLITE_NOMEM;
6870 break;
6871 }
6872 zSep = " OR ";
dan3f67ddf2017-12-13 20:04:53 +00006873 }
dan3f67ddf2017-12-13 20:04:53 +00006874 }
6875 }
6876 *pzWhere = zWhere;
6877}
6878
6879/*
dan88be0202017-12-09 17:58:02 +00006880** Implementation of .ar "lisT" command.
6881*/
drhb376b3d2018-01-10 13:11:51 +00006882static int arListCommand(ArCommand *pAr){
danb5090e42017-12-27 21:13:21 +00006883 const char *zSql = "SELECT %s FROM %s WHERE %s";
danb5090e42017-12-27 21:13:21 +00006884 const char *azCols[] = {
6885 "name",
drh410cad92018-01-10 17:19:16 +00006886 "lsmode(mode), sz, datetime(mtime, 'unixepoch'), name"
danb5090e42017-12-27 21:13:21 +00006887 };
dan5a78b812017-12-27 18:54:11 +00006888
dan3f67ddf2017-12-13 20:04:53 +00006889 char *zWhere = 0;
6890 sqlite3_stmt *pSql = 0;
6891 int rc;
6892
drhb376b3d2018-01-10 13:11:51 +00006893 rc = arCheckEntries(pAr);
dan3f67ddf2017-12-13 20:04:53 +00006894 arWhereClause(&rc, pAr, &zWhere);
6895
drhb376b3d2018-01-10 13:11:51 +00006896 shellPreparePrintf(pAr->db, &rc, &pSql, zSql, azCols[pAr->bVerbose],
6897 pAr->zSrcTable, zWhere);
drhb376b3d2018-01-10 13:11:51 +00006898 if( pAr->bDryRun ){
6899 utf8_printf(pAr->p->out, "%s\n", sqlite3_sql(pSql));
6900 }else{
6901 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){
6902 if( pAr->bVerbose ){
drh410cad92018-01-10 17:19:16 +00006903 utf8_printf(pAr->p->out, "%s % 10d %s %s\n",
6904 sqlite3_column_text(pSql, 0),
drhb376b3d2018-01-10 13:11:51 +00006905 sqlite3_column_int(pSql, 1),
6906 sqlite3_column_text(pSql, 2),
6907 sqlite3_column_text(pSql, 3)
6908 );
6909 }else{
6910 utf8_printf(pAr->p->out, "%s\n", sqlite3_column_text(pSql, 0));
6911 }
danb5090e42017-12-27 21:13:21 +00006912 }
dan3f67ddf2017-12-13 20:04:53 +00006913 }
dan5a78b812017-12-27 18:54:11 +00006914 shellFinalize(&rc, pSql);
drhd0f9cdc2018-05-17 14:09:06 +00006915 sqlite3_free(zWhere);
dan3f67ddf2017-12-13 20:04:53 +00006916 return rc;
dan88be0202017-12-09 17:58:02 +00006917}
6918
6919
danfd0245d2017-12-07 15:44:29 +00006920/*
larrybr47061b92021-11-01 17:22:52 +00006921** Implementation of .ar "Remove" command.
6922*/
6923static int arRemoveCommand(ArCommand *pAr){
larrybr7774fc02021-11-01 22:30:24 +00006924 int rc = 0;
larrybr47061b92021-11-01 17:22:52 +00006925 char *zSql = 0;
6926 char *zWhere = 0;
6927
6928 if( pAr->nArg ){
6929 /* Verify that args actually exist within the archive before proceeding.
6930 ** And formulate a WHERE clause to match them. */
6931 rc = arCheckEntries(pAr);
6932 arWhereClause(&rc, pAr, &zWhere);
6933 }
6934 if( rc==SQLITE_OK ){
6935 zSql = sqlite3_mprintf("DELETE FROM %s WHERE %s;",
6936 pAr->zSrcTable, zWhere);
6937 if( pAr->bDryRun ){
6938 utf8_printf(pAr->p->out, "%s\n", zSql);
6939 }else{
6940 char *zErr = 0;
6941 rc = sqlite3_exec(pAr->db, "SAVEPOINT ar;", 0, 0, 0);
6942 if( rc==SQLITE_OK ){
6943 rc = sqlite3_exec(pAr->db, zSql, 0, 0, &zErr);
6944 if( rc!=SQLITE_OK ){
6945 sqlite3_exec(pAr->db, "ROLLBACK TO ar; RELEASE ar;", 0, 0, 0);
6946 }else{
6947 rc = sqlite3_exec(pAr->db, "RELEASE ar;", 0, 0, 0);
6948 }
6949 }
6950 if( zErr ){
6951 utf8_printf(stdout, "ERROR: %s\n", zErr);
6952 sqlite3_free(zErr);
6953 }
6954 }
6955 }
6956 sqlite3_free(zWhere);
6957 sqlite3_free(zSql);
6958 return rc;
6959}
6960
6961/*
danfd0245d2017-12-07 15:44:29 +00006962** Implementation of .ar "eXtract" command.
6963*/
drhb376b3d2018-01-10 13:11:51 +00006964static int arExtractCommand(ArCommand *pAr){
dan25c12182017-12-07 21:03:33 +00006965 const char *zSql1 =
dand1b51d42017-12-16 19:11:26 +00006966 "SELECT "
drhb376b3d2018-01-10 13:11:51 +00006967 " ($dir || name),"
6968 " writefile(($dir || name), %s, mode, mtime) "
drh0cfd46a2018-06-06 01:18:01 +00006969 "FROM %s WHERE (%s) AND (data IS NULL OR $dirOnly = 0)"
6970 " AND name NOT GLOB '*..[/\\]*'";
dan5a78b812017-12-27 18:54:11 +00006971
6972 const char *azExtraArg[] = {
6973 "sqlar_uncompress(data, sz)",
dan7c15ac12018-01-08 19:59:59 +00006974 "data"
dan5a78b812017-12-27 18:54:11 +00006975 };
dan5a78b812017-12-27 18:54:11 +00006976
danfd0245d2017-12-07 15:44:29 +00006977 sqlite3_stmt *pSql = 0;
6978 int rc = SQLITE_OK;
dan2ad09492017-12-09 18:28:22 +00006979 char *zDir = 0;
dan3f67ddf2017-12-13 20:04:53 +00006980 char *zWhere = 0;
drhb376b3d2018-01-10 13:11:51 +00006981 int i, j;
dan2ad09492017-12-09 18:28:22 +00006982
dan3f67ddf2017-12-13 20:04:53 +00006983 /* If arguments are specified, check that they actually exist within
6984 ** the archive before proceeding. And formulate a WHERE clause to
6985 ** match them. */
drhb376b3d2018-01-10 13:11:51 +00006986 rc = arCheckEntries(pAr);
dan3f67ddf2017-12-13 20:04:53 +00006987 arWhereClause(&rc, pAr, &zWhere);
6988
6989 if( rc==SQLITE_OK ){
6990 if( pAr->zDir ){
6991 zDir = sqlite3_mprintf("%s/", pAr->zDir);
6992 }else{
6993 zDir = sqlite3_mprintf("");
6994 }
6995 if( zDir==0 ) rc = SQLITE_NOMEM;
dan2ad09492017-12-09 18:28:22 +00006996 }
danfd0245d2017-12-07 15:44:29 +00006997
drhb376b3d2018-01-10 13:11:51 +00006998 shellPreparePrintf(pAr->db, &rc, &pSql, zSql1,
6999 azExtraArg[pAr->bZip], pAr->zSrcTable, zWhere
dan5a78b812017-12-27 18:54:11 +00007000 );
7001
dan2ad09492017-12-09 18:28:22 +00007002 if( rc==SQLITE_OK ){
drhb376b3d2018-01-10 13:11:51 +00007003 j = sqlite3_bind_parameter_index(pSql, "$dir");
7004 sqlite3_bind_text(pSql, j, zDir, -1, SQLITE_STATIC);
dan25c12182017-12-07 21:03:33 +00007005
danac15e2d2017-12-14 19:15:07 +00007006 /* Run the SELECT statement twice. The first time, writefile() is called
7007 ** for all archive members that should be extracted. The second time,
7008 ** only for the directories. This is because the timestamps for
7009 ** extracted directories must be reset after they are populated (as
7010 ** populating them changes the timestamp). */
7011 for(i=0; i<2; i++){
drhb376b3d2018-01-10 13:11:51 +00007012 j = sqlite3_bind_parameter_index(pSql, "$dirOnly");
7013 sqlite3_bind_int(pSql, j, i);
7014 if( pAr->bDryRun ){
7015 utf8_printf(pAr->p->out, "%s\n", sqlite3_sql(pSql));
7016 }else{
7017 while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){
7018 if( i==0 && pAr->bVerbose ){
7019 utf8_printf(pAr->p->out, "%s\n", sqlite3_column_text(pSql, 0));
7020 }
danac15e2d2017-12-14 19:15:07 +00007021 }
7022 }
7023 shellReset(&rc, pSql);
dan25c12182017-12-07 21:03:33 +00007024 }
danac15e2d2017-12-14 19:15:07 +00007025 shellFinalize(&rc, pSql);
dan25c12182017-12-07 21:03:33 +00007026 }
dan25c12182017-12-07 21:03:33 +00007027
dan2ad09492017-12-09 18:28:22 +00007028 sqlite3_free(zDir);
dan3f67ddf2017-12-13 20:04:53 +00007029 sqlite3_free(zWhere);
danfd0245d2017-12-07 15:44:29 +00007030 return rc;
7031}
7032
drhb376b3d2018-01-10 13:11:51 +00007033/*
7034** Run the SQL statement in zSql. Or if doing a --dryrun, merely print it out.
7035*/
7036static int arExecSql(ArCommand *pAr, const char *zSql){
7037 int rc;
7038 if( pAr->bDryRun ){
7039 utf8_printf(pAr->p->out, "%s\n", zSql);
7040 rc = SQLITE_OK;
7041 }else{
drh410cad92018-01-10 17:19:16 +00007042 char *zErr = 0;
7043 rc = sqlite3_exec(pAr->db, zSql, 0, 0, &zErr);
7044 if( zErr ){
7045 utf8_printf(stdout, "ERROR: %s\n", zErr);
7046 sqlite3_free(zErr);
7047 }
drhb376b3d2018-01-10 13:11:51 +00007048 }
7049 return rc;
7050}
7051
dan1ad3f612017-12-11 20:22:02 +00007052
danfd0245d2017-12-07 15:44:29 +00007053/*
drhb17ea912019-03-25 14:24:19 +00007054** Implementation of .ar "create", "insert", and "update" commands.
7055**
7056** create -> Create a new SQL archive
7057** insert -> Insert or reinsert all files listed
7058** update -> Insert files that have changed or that were not
7059** previously in the archive
danfd0245d2017-12-07 15:44:29 +00007060**
7061** Create the "sqlar" table in the database if it does not already exist.
7062** Then add each file in the azFile[] array to the archive. Directories
7063** are added recursively. If argument bVerbose is non-zero, a message is
7064** printed on stdout for each file archived.
dan06741a32017-12-13 20:17:18 +00007065**
7066** The create command is the same as update, except that it drops
drhb17ea912019-03-25 14:24:19 +00007067** any existing "sqlar" table before beginning. The "insert" command
7068** always overwrites every file named on the command-line, where as
7069** "update" only overwrites if the size or mtime or mode has changed.
danfd0245d2017-12-07 15:44:29 +00007070*/
drhb376b3d2018-01-10 13:11:51 +00007071static int arCreateOrUpdateCommand(
dan06741a32017-12-13 20:17:18 +00007072 ArCommand *pAr, /* Command arguments and options */
drhb17ea912019-03-25 14:24:19 +00007073 int bUpdate, /* true for a --create. */
7074 int bOnlyIfChanged /* Only update if file has changed */
danfd0245d2017-12-07 15:44:29 +00007075){
dand4b56e52017-12-12 20:04:59 +00007076 const char *zCreate =
drhafba1802018-01-06 15:49:57 +00007077 "CREATE TABLE IF NOT EXISTS sqlar(\n"
7078 " name TEXT PRIMARY KEY, -- name of the file\n"
7079 " mode INT, -- access permissions\n"
7080 " mtime INT, -- last modification time\n"
7081 " sz INT, -- original file size\n"
7082 " data BLOB -- compressed content\n"
7083 ")";
dand4b56e52017-12-12 20:04:59 +00007084 const char *zDrop = "DROP TABLE IF EXISTS sqlar";
drh1bf208c2018-03-09 21:54:01 +00007085 const char *zInsertFmt[2] = {
7086 "REPLACE INTO %s(name,mode,mtime,sz,data)\n"
drh634c70f2018-01-10 16:50:18 +00007087 " SELECT\n"
7088 " %s,\n"
7089 " mode,\n"
7090 " mtime,\n"
drh410cad92018-01-10 17:19:16 +00007091 " CASE substr(lsmode(mode),1,1)\n"
7092 " WHEN '-' THEN length(data)\n"
7093 " WHEN 'd' THEN 0\n"
drh634c70f2018-01-10 16:50:18 +00007094 " ELSE -1 END,\n"
drh69d2d352018-03-09 22:18:53 +00007095 " sqlar_compress(data)\n"
drhb17ea912019-03-25 14:24:19 +00007096 " FROM fsdir(%Q,%Q) AS disk\n"
7097 " WHERE lsmode(mode) NOT LIKE '?%%'%s;"
7098 ,
drh1bf208c2018-03-09 21:54:01 +00007099 "REPLACE INTO %s(name,mode,mtime,data)\n"
7100 " SELECT\n"
7101 " %s,\n"
7102 " mode,\n"
7103 " mtime,\n"
7104 " data\n"
drhb17ea912019-03-25 14:24:19 +00007105 " FROM fsdir(%Q,%Q) AS disk\n"
7106 " WHERE lsmode(mode) NOT LIKE '?%%'%s;"
drh1bf208c2018-03-09 21:54:01 +00007107 };
danfd0245d2017-12-07 15:44:29 +00007108 int i; /* For iterating through azFile[] */
7109 int rc; /* Return code */
drh1bf208c2018-03-09 21:54:01 +00007110 const char *zTab = 0; /* SQL table into which to insert */
7111 char *zSql;
7112 char zTemp[50];
drhb17ea912019-03-25 14:24:19 +00007113 char *zExists = 0;
danfd0245d2017-12-07 15:44:29 +00007114
drh1bf208c2018-03-09 21:54:01 +00007115 arExecSql(pAr, "PRAGMA page_size=512");
drhb376b3d2018-01-10 13:11:51 +00007116 rc = arExecSql(pAr, "SAVEPOINT ar;");
danfd0245d2017-12-07 15:44:29 +00007117 if( rc!=SQLITE_OK ) return rc;
drh1bf208c2018-03-09 21:54:01 +00007118 zTemp[0] = 0;
7119 if( pAr->bZip ){
7120 /* Initialize the zipfile virtual table, if necessary */
7121 if( pAr->zFile ){
7122 sqlite3_uint64 r;
7123 sqlite3_randomness(sizeof(r),&r);
7124 sqlite3_snprintf(sizeof(zTemp),zTemp,"zip%016llx",r);
7125 zTab = zTemp;
7126 zSql = sqlite3_mprintf(
7127 "CREATE VIRTUAL TABLE temp.%s USING zipfile(%Q)",
7128 zTab, pAr->zFile
7129 );
7130 rc = arExecSql(pAr, zSql);
7131 sqlite3_free(zSql);
7132 }else{
7133 zTab = "zip";
7134 }
7135 }else{
7136 /* Initialize the table for an SQLAR */
7137 zTab = "sqlar";
7138 if( bUpdate==0 ){
7139 rc = arExecSql(pAr, zDrop);
7140 if( rc!=SQLITE_OK ) goto end_ar_transaction;
7141 }
7142 rc = arExecSql(pAr, zCreate);
dan06741a32017-12-13 20:17:18 +00007143 }
drhb17ea912019-03-25 14:24:19 +00007144 if( bOnlyIfChanged ){
7145 zExists = sqlite3_mprintf(
7146 " AND NOT EXISTS("
7147 "SELECT 1 FROM %s AS mem"
7148 " WHERE mem.name=disk.name"
7149 " AND mem.mtime=disk.mtime"
7150 " AND mem.mode=disk.mode)", zTab);
7151 }else{
7152 zExists = sqlite3_mprintf("");
7153 }
7154 if( zExists==0 ) rc = SQLITE_NOMEM;
dan88be0202017-12-09 17:58:02 +00007155 for(i=0; i<pAr->nArg && rc==SQLITE_OK; i++){
mistachkince2052b2018-03-23 00:31:53 +00007156 char *zSql2 = sqlite3_mprintf(zInsertFmt[pAr->bZip], zTab,
drh634c70f2018-01-10 16:50:18 +00007157 pAr->bVerbose ? "shell_putsnl(name)" : "name",
drhb17ea912019-03-25 14:24:19 +00007158 pAr->azArg[i], pAr->zDir, zExists);
mistachkince2052b2018-03-23 00:31:53 +00007159 rc = arExecSql(pAr, zSql2);
7160 sqlite3_free(zSql2);
danfd0245d2017-12-07 15:44:29 +00007161 }
drh1bf208c2018-03-09 21:54:01 +00007162end_ar_transaction:
danfd0245d2017-12-07 15:44:29 +00007163 if( rc!=SQLITE_OK ){
drh2bd207f2019-01-11 17:19:59 +00007164 sqlite3_exec(pAr->db, "ROLLBACK TO ar; RELEASE ar;", 0, 0, 0);
danfd0245d2017-12-07 15:44:29 +00007165 }else{
drhb376b3d2018-01-10 13:11:51 +00007166 rc = arExecSql(pAr, "RELEASE ar;");
drh1bf208c2018-03-09 21:54:01 +00007167 if( pAr->bZip && pAr->zFile ){
7168 zSql = sqlite3_mprintf("DROP TABLE %s", zTemp);
7169 arExecSql(pAr, zSql);
7170 sqlite3_free(zSql);
7171 }
danfd0245d2017-12-07 15:44:29 +00007172 }
drhb17ea912019-03-25 14:24:19 +00007173 sqlite3_free(zExists);
danfd0245d2017-12-07 15:44:29 +00007174 return rc;
7175}
7176
7177/*
7178** Implementation of ".ar" dot command.
7179*/
7180static int arDotCommand(
drhe2754c12019-08-26 12:50:01 +00007181 ShellState *pState, /* Current shell tool state */
7182 int fromCmdLine, /* True if -A command-line option, not .ar cmd */
7183 char **azArg, /* Array of arguments passed to dot command */
7184 int nArg /* Number of entries in azArg[] */
danfd0245d2017-12-07 15:44:29 +00007185){
dan88be0202017-12-09 17:58:02 +00007186 ArCommand cmd;
7187 int rc;
drh34660642018-01-10 17:39:54 +00007188 memset(&cmd, 0, sizeof(cmd));
drhd0f9cdc2018-05-17 14:09:06 +00007189 cmd.fromCmdLine = fromCmdLine;
dan88be0202017-12-09 17:58:02 +00007190 rc = arParseCommand(azArg, nArg, &cmd);
7191 if( rc==SQLITE_OK ){
drha5676c42018-01-10 15:17:34 +00007192 int eDbType = SHELL_OPEN_UNSPEC;
drhb376b3d2018-01-10 13:11:51 +00007193 cmd.p = pState;
7194 cmd.db = pState->db;
drha5676c42018-01-10 15:17:34 +00007195 if( cmd.zFile ){
drh1bf208c2018-03-09 21:54:01 +00007196 eDbType = deduceDatabaseType(cmd.zFile, 1);
drha5676c42018-01-10 15:17:34 +00007197 }else{
7198 eDbType = pState->openMode;
7199 }
7200 if( eDbType==SHELL_OPEN_ZIPFILE ){
drh1bf208c2018-03-09 21:54:01 +00007201 if( cmd.eCmd==AR_CMD_EXTRACT || cmd.eCmd==AR_CMD_LIST ){
7202 if( cmd.zFile==0 ){
7203 cmd.zSrcTable = sqlite3_mprintf("zip");
7204 }else{
7205 cmd.zSrcTable = sqlite3_mprintf("zipfile(%Q)", cmd.zFile);
7206 }
dan5a78b812017-12-27 18:54:11 +00007207 }
drha5676c42018-01-10 15:17:34 +00007208 cmd.bZip = 1;
dan5a78b812017-12-27 18:54:11 +00007209 }else if( cmd.zFile ){
dand4b56e52017-12-12 20:04:59 +00007210 int flags;
drha5676c42018-01-10 15:17:34 +00007211 if( cmd.bAppend ) eDbType = SHELL_OPEN_APPENDVFS;
drhb17ea912019-03-25 14:24:19 +00007212 if( cmd.eCmd==AR_CMD_CREATE || cmd.eCmd==AR_CMD_INSERT
larrybr47061b92021-11-01 17:22:52 +00007213 || cmd.eCmd==AR_CMD_REMOVE || cmd.eCmd==AR_CMD_UPDATE ){
dand4b56e52017-12-12 20:04:59 +00007214 flags = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE;
7215 }else{
7216 flags = SQLITE_OPEN_READONLY;
7217 }
drha82c95b2018-01-10 14:00:00 +00007218 cmd.db = 0;
drha5676c42018-01-10 15:17:34 +00007219 if( cmd.bDryRun ){
7220 utf8_printf(pState->out, "-- open database '%s'%s\n", cmd.zFile,
7221 eDbType==SHELL_OPEN_APPENDVFS ? " using 'apndvfs'" : "");
7222 }
7223 rc = sqlite3_open_v2(cmd.zFile, &cmd.db, flags,
7224 eDbType==SHELL_OPEN_APPENDVFS ? "apndvfs" : 0);
dand4b56e52017-12-12 20:04:59 +00007225 if( rc!=SQLITE_OK ){
drhb376b3d2018-01-10 13:11:51 +00007226 utf8_printf(stderr, "cannot open file: %s (%s)\n",
7227 cmd.zFile, sqlite3_errmsg(cmd.db)
dand4b56e52017-12-12 20:04:59 +00007228 );
drha5676c42018-01-10 15:17:34 +00007229 goto end_ar_command;
dand4b56e52017-12-12 20:04:59 +00007230 }
drhb376b3d2018-01-10 13:11:51 +00007231 sqlite3_fileio_init(cmd.db, 0, 0);
drhb376b3d2018-01-10 13:11:51 +00007232 sqlite3_sqlar_init(cmd.db, 0, 0);
drh34660642018-01-10 17:39:54 +00007233 sqlite3_create_function(cmd.db, "shell_putsnl", 1, SQLITE_UTF8, cmd.p,
7234 shellPutsFunc, 0, 0);
7235
dand4b56e52017-12-12 20:04:59 +00007236 }
drhd0f9cdc2018-05-17 14:09:06 +00007237 if( cmd.zSrcTable==0 && cmd.bZip==0 && cmd.eCmd!=AR_CMD_HELP ){
drh634c70f2018-01-10 16:50:18 +00007238 if( cmd.eCmd!=AR_CMD_CREATE
7239 && sqlite3_table_column_metadata(cmd.db,0,"sqlar","name",0,0,0,0,0)
7240 ){
drha5676c42018-01-10 15:17:34 +00007241 utf8_printf(stderr, "database does not contain an 'sqlar' table\n");
7242 rc = SQLITE_ERROR;
7243 goto end_ar_command;
7244 }
7245 cmd.zSrcTable = sqlite3_mprintf("sqlar");
7246 }
dand4b56e52017-12-12 20:04:59 +00007247
dan88be0202017-12-09 17:58:02 +00007248 switch( cmd.eCmd ){
7249 case AR_CMD_CREATE:
drhb17ea912019-03-25 14:24:19 +00007250 rc = arCreateOrUpdateCommand(&cmd, 0, 0);
dan88be0202017-12-09 17:58:02 +00007251 break;
danfd0245d2017-12-07 15:44:29 +00007252
dan88be0202017-12-09 17:58:02 +00007253 case AR_CMD_EXTRACT:
drhb376b3d2018-01-10 13:11:51 +00007254 rc = arExtractCommand(&cmd);
dan88be0202017-12-09 17:58:02 +00007255 break;
7256
7257 case AR_CMD_LIST:
drhb376b3d2018-01-10 13:11:51 +00007258 rc = arListCommand(&cmd);
dan88be0202017-12-09 17:58:02 +00007259 break;
7260
dan0d0547f2017-12-14 15:40:42 +00007261 case AR_CMD_HELP:
7262 arUsage(pState->out);
7263 break;
7264
drhb17ea912019-03-25 14:24:19 +00007265 case AR_CMD_INSERT:
7266 rc = arCreateOrUpdateCommand(&cmd, 1, 0);
7267 break;
7268
larrybr47061b92021-11-01 17:22:52 +00007269 case AR_CMD_REMOVE:
7270 rc = arRemoveCommand(&cmd);
7271 break;
7272
dan88be0202017-12-09 17:58:02 +00007273 default:
7274 assert( cmd.eCmd==AR_CMD_UPDATE );
drhb17ea912019-03-25 14:24:19 +00007275 rc = arCreateOrUpdateCommand(&cmd, 1, 1);
dan88be0202017-12-09 17:58:02 +00007276 break;
danfd0245d2017-12-07 15:44:29 +00007277 }
7278 }
drha5676c42018-01-10 15:17:34 +00007279end_ar_command:
7280 if( cmd.db!=pState->db ){
drh9e804032018-05-18 17:11:50 +00007281 close_db(cmd.db);
drha5676c42018-01-10 15:17:34 +00007282 }
7283 sqlite3_free(cmd.zSrcTable);
danfd0245d2017-12-07 15:44:29 +00007284
dan88be0202017-12-09 17:58:02 +00007285 return rc;
danfd0245d2017-12-07 15:44:29 +00007286}
drhe37c0e12018-01-06 19:19:50 +00007287/* End of the ".archive" or ".ar" command logic
drhe2754c12019-08-26 12:50:01 +00007288*******************************************************************************/
drhe37c0e12018-01-06 19:19:50 +00007289#endif /* !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB) */
danfd0245d2017-12-07 15:44:29 +00007290
stephan3d420832022-10-27 03:56:01 +00007291#if SQLITE_SHELL_HAVE_RECOVER
dan68cb86e2019-04-20 20:57:28 +00007292
dan42ebb012019-04-27 18:47:03 +00007293/*
dan9a27d652022-09-08 19:22:29 +00007294** This function is used as a callback by the recover extension. Simply
7295** print the supplied SQL statement to stdout.
dan42ebb012019-04-27 18:47:03 +00007296*/
dan9a27d652022-09-08 19:22:29 +00007297static int recoverSqlCb(void *pCtx, const char *zSql){
7298 ShellState *pState = (ShellState*)pCtx;
dan80b1f6f2022-09-23 11:40:43 +00007299 utf8_printf(pState->out, "%s;\n", zSql);
dan9a27d652022-09-08 19:22:29 +00007300 return SQLITE_OK;
dan68cb86e2019-04-20 20:57:28 +00007301}
7302
7303/*
7304** This function is called to recover data from the database. A script
7305** to construct a new database containing all recovered data is output
7306** on stream pState->out.
7307*/
danb9b71db2019-04-25 16:20:40 +00007308static int recoverDatabaseCmd(ShellState *pState, int nArg, char **azArg){
dan68cb86e2019-04-20 20:57:28 +00007309 int rc = SQLITE_OK;
drh2cdcc7f2022-11-02 14:08:26 +00007310 const char *zRecoveryDb = ""; /* Name of "recovery" database. Debug only */
dan9a27d652022-09-08 19:22:29 +00007311 const char *zLAF = "lost_and_found";
danf7fea5b2022-10-27 18:19:45 +00007312 int bFreelist = 1; /* 0 if --ignore-freelist is specified */
dan8cce6b82019-09-14 16:44:51 +00007313 int bRowids = 1; /* 0 if --no-rowids */
dan9a27d652022-09-08 19:22:29 +00007314 sqlite3_recover *p = 0;
7315 int i = 0;
7316
dan9c014f82019-04-25 19:23:15 +00007317 for(i=1; i<nArg; i++){
7318 char *z = azArg[i];
7319 int n;
7320 if( z[0]=='-' && z[1]=='-' ) z++;
drh4245e042019-06-13 13:52:46 +00007321 n = strlen30(z);
danf7fea5b2022-10-27 18:19:45 +00007322 if( n<=17 && memcmp("-ignore-freelist", z, n)==0 ){
dan9c014f82019-04-25 19:23:15 +00007323 bFreelist = 0;
dan42ebb012019-04-27 18:47:03 +00007324 }else
danc0b42432019-04-26 15:14:53 +00007325 if( n<=12 && memcmp("-recovery-db", z, n)==0 && i<(nArg-1) ){
drh2cdcc7f2022-11-02 14:08:26 +00007326 /* This option determines the name of the ATTACH-ed database used
7327 ** internally by the recovery extension. The default is "" which
7328 ** means to use a temporary database that is automatically deleted
7329 ** when closed. This option is undocumented and might disappear at
7330 ** any moment. */
danc0b42432019-04-26 15:14:53 +00007331 i++;
7332 zRecoveryDb = azArg[i];
dan42ebb012019-04-27 18:47:03 +00007333 }else
7334 if( n<=15 && memcmp("-lost-and-found", z, n)==0 && i<(nArg-1) ){
7335 i++;
dan9a27d652022-09-08 19:22:29 +00007336 zLAF = azArg[i];
dan8cce6b82019-09-14 16:44:51 +00007337 }else
7338 if( n<=10 && memcmp("-no-rowids", z, n)==0 ){
7339 bRowids = 0;
danc0b42432019-04-26 15:14:53 +00007340 }
dan9c014f82019-04-25 19:23:15 +00007341 else{
drhe2754c12019-08-26 12:50:01 +00007342 utf8_printf(stderr, "unexpected option: %s\n", azArg[i]);
7343 showHelp(pState->out, azArg[0]);
dan9c014f82019-04-25 19:23:15 +00007344 return 1;
7345 }
7346 }
dan68cb86e2019-04-20 20:57:28 +00007347
dan9a27d652022-09-08 19:22:29 +00007348 p = sqlite3_recover_init_sql(
7349 pState->db, "main", recoverSqlCb, (void*)pState
dan9c014f82019-04-25 19:23:15 +00007350 );
7351
drh2cdcc7f2022-11-02 14:08:26 +00007352 sqlite3_recover_config(p, 789, (void*)zRecoveryDb); /* Debug use only */
dan9a27d652022-09-08 19:22:29 +00007353 sqlite3_recover_config(p, SQLITE_RECOVER_LOST_AND_FOUND, (void*)zLAF);
7354 sqlite3_recover_config(p, SQLITE_RECOVER_ROWIDS, (void*)&bRowids);
7355 sqlite3_recover_config(p, SQLITE_RECOVER_FREELIST_CORRUPT,(void*)&bFreelist);
7356
dan46d43982022-09-08 21:43:18 +00007357 sqlite3_recover_run(p);
dan9a27d652022-09-08 19:22:29 +00007358 if( sqlite3_recover_errcode(p)!=SQLITE_OK ){
7359 const char *zErr = sqlite3_recover_errmsg(p);
7360 int errCode = sqlite3_recover_errcode(p);
7361 raw_printf(stderr, "sql error: %s (%d)\n", zErr, errCode);
dan9c014f82019-04-25 19:23:15 +00007362 }
dan9a27d652022-09-08 19:22:29 +00007363 rc = sqlite3_recover_finish(p);
dan68cb86e2019-04-20 20:57:28 +00007364 return rc;
7365}
stephan3d420832022-10-27 03:56:01 +00007366#endif /* SQLITE_SHELL_HAVE_RECOVER */
dan68cb86e2019-04-20 20:57:28 +00007367
larrybr42de1c52022-02-13 22:18:22 +00007368
larrybr2d27d362022-04-16 17:53:25 +00007369/*
larrybr42de1c52022-02-13 22:18:22 +00007370 * zAutoColumn(zCol, &db, ?) => Maybe init db, add column zCol to it.
7371 * zAutoColumn(0, &db, ?) => (db!=0) Form columns spec for CREATE TABLE,
7372 * close db and set it to 0, and return the columns spec, to later
7373 * be sqlite3_free()'ed by the caller.
7374 * The return is 0 when either:
7375 * (a) The db was not initialized and zCol==0 (There are no columns.)
7376 * (b) zCol!=0 (Column was added, db initialized as needed.)
7377 * The 3rd argument, pRenamed, references an out parameter. If the
larrybr33633862022-02-14 01:12:46 +00007378 * pointer is non-zero, its referent will be set to a summary of renames
7379 * done if renaming was necessary, or set to 0 if none was done. The out
7380 * string (if any) must be sqlite3_free()'ed by the caller.
larrybr42de1c52022-02-13 22:18:22 +00007381 */
7382#ifdef SHELL_DEBUG
7383#define rc_err_oom_die(rc) \
7384 if( rc==SQLITE_NOMEM ) shell_check_oom(0); \
7385 else if(!(rc==SQLITE_OK||rc==SQLITE_DONE)) \
7386 fprintf(stderr,"E:%d\n",rc), assert(0)
7387#else
7388static void rc_err_oom_die(int rc){
7389 if( rc==SQLITE_NOMEM ) shell_check_oom(0);
7390 assert(rc==SQLITE_OK||rc==SQLITE_DONE);
7391}
7392#endif
7393
7394#ifdef SHELL_COLFIX_DB /* If this is set, the DB can be in a file. */
7395static char zCOL_DB[] = SHELL_STRINGIFY(SHELL_COLFIX_DB);
7396#else /* Otherwise, memory is faster/better for the transient DB. */
7397static const char *zCOL_DB = ":memory:";
7398#endif
7399
7400/* Define character (as C string) to separate generated column ordinal
7401 * from protected part of incoming column names. This defaults to "_"
7402 * so that incoming column identifiers that did not need not be quoted
7403 * remain usable without being quoted. It must be one character.
7404 */
7405#ifndef SHELL_AUTOCOLUMN_SEP
7406# define AUTOCOLUMN_SEP "_"
7407#else
7408# define AUTOCOLUMN_SEP SHELL_STRINGIFY(SHELL_AUTOCOLUMN_SEP)
7409#endif
7410
larrybr33633862022-02-14 01:12:46 +00007411static char *zAutoColumn(const char *zColNew, sqlite3 **pDb, char **pzRenamed){
larrybr42de1c52022-02-13 22:18:22 +00007412 /* Queries and D{D,M}L used here */
7413 static const char * const zTabMake = "\
7414CREATE TABLE ColNames(\
7415 cpos INTEGER PRIMARY KEY,\
larrybr33633862022-02-14 01:12:46 +00007416 name TEXT, nlen INT, chop INT, reps INT, suff TEXT);\
7417CREATE VIEW RepeatedNames AS \
7418SELECT DISTINCT t.name FROM ColNames t \
7419WHERE t.name COLLATE NOCASE IN (\
7420 SELECT o.name FROM ColNames o WHERE o.cpos<>t.cpos\
7421);\
larrybr42de1c52022-02-13 22:18:22 +00007422";
7423 static const char * const zTabFill = "\
7424INSERT INTO ColNames(name,nlen,chop,reps,suff)\
7425 VALUES(iif(length(?1)>0,?1,'?'),max(length(?1),1),0,0,'')\
7426";
7427 static const char * const zHasDupes = "\
7428SELECT count(DISTINCT (substring(name,1,nlen-chop)||suff) COLLATE NOCASE)\
7429 <count(name) FROM ColNames\
7430";
larrybr33633862022-02-14 01:12:46 +00007431#ifdef SHELL_COLUMN_RENAME_CLEAN
larrybr42de1c52022-02-13 22:18:22 +00007432 static const char * const zDedoctor = "\
7433UPDATE ColNames SET chop=iif(\
7434 (substring(name,nlen,1) BETWEEN '0' AND '9')\
7435 AND (rtrim(name,'0123456790') glob '*"AUTOCOLUMN_SEP"'),\
7436 nlen-length(rtrim(name, '"AUTOCOLUMN_SEP"0123456789')),\
7437 0\
7438)\
7439";
larrybr33633862022-02-14 01:12:46 +00007440#endif
larrybr42de1c52022-02-13 22:18:22 +00007441 static const char * const zSetReps = "\
7442UPDATE ColNames AS t SET reps=\
7443(SELECT count(*) FROM ColNames d \
7444 WHERE substring(t.name,1,t.nlen-t.chop)=substring(d.name,1,d.nlen-d.chop)\
7445 COLLATE NOCASE\
7446)\
7447";
7448#ifdef SQLITE_ENABLE_MATH_FUNCTIONS
7449 static const char * const zColDigits = "\
7450SELECT CAST(ceil(log(count(*)+0.5)) AS INT) FROM ColNames \
7451";
larrybr2d27d362022-04-16 17:53:25 +00007452#else
7453 /* Counting on SQLITE_MAX_COLUMN < 100,000 here. (32767 is the hard limit.) */
7454 static const char * const zColDigits = "\
7455SELECT CASE WHEN (nc < 10) THEN 1 WHEN (nc < 100) THEN 2 \
7456 WHEN (nc < 1000) THEN 3 WHEN (nc < 10000) THEN 4 \
7457 ELSE 5 FROM (SELECT count(*) AS nc FROM ColNames) \
7458";
larrybr42de1c52022-02-13 22:18:22 +00007459#endif
7460 static const char * const zRenameRank =
larrybr33633862022-02-14 01:12:46 +00007461#ifdef SHELL_COLUMN_RENAME_CLEAN
larrybr42de1c52022-02-13 22:18:22 +00007462 "UPDATE ColNames AS t SET suff="
7463 "iif(reps>1, printf('%c%0*d', '"AUTOCOLUMN_SEP"', $1, cpos), '')"
larrybr33633862022-02-14 01:12:46 +00007464#else /* ...RENAME_MINIMAL_ONE_PASS */
7465"WITH Lzn(nlz) AS (" /* Find minimum extraneous leading 0's for uniqueness */
7466" SELECT 0 AS nlz"
7467" UNION"
7468" SELECT nlz+1 AS nlz FROM Lzn"
7469" WHERE EXISTS("
7470" SELECT 1"
7471" FROM ColNames t, ColNames o"
7472" WHERE"
7473" iif(t.name IN (SELECT * FROM RepeatedNames),"
7474" printf('%s"AUTOCOLUMN_SEP"%s',"
7475" t.name, substring(printf('%.*c%0.*d',nlz+1,'0',$1,t.cpos),2)),"
7476" t.name"
7477" )"
7478" ="
7479" iif(o.name IN (SELECT * FROM RepeatedNames),"
7480" printf('%s"AUTOCOLUMN_SEP"%s',"
7481" o.name, substring(printf('%.*c%0.*d',nlz+1,'0',$1,o.cpos),2)),"
7482" o.name"
7483" )"
7484" COLLATE NOCASE"
7485" AND o.cpos<>t.cpos"
7486" GROUP BY t.cpos"
7487" )"
7488") UPDATE Colnames AS t SET"
7489" chop = 0," /* No chopping, never touch incoming names. */
7490" suff = iif(name IN (SELECT * FROM RepeatedNames),"
7491" printf('"AUTOCOLUMN_SEP"%s', substring("
7492" printf('%.*c%0.*d',(SELECT max(nlz) FROM Lzn)+1,'0',1,t.cpos),2)),"
7493" ''"
7494" )"
larrybr42de1c52022-02-13 22:18:22 +00007495#endif
7496 ;
7497 static const char * const zCollectVar = "\
7498SELECT\
7499 '('||x'0a'\
7500 || group_concat(\
7501 cname||' TEXT',\
7502 ','||iif((cpos-1)%4>0, ' ', x'0a'||' '))\
7503 ||')' AS ColsSpec \
7504FROM (\
larrybr039132b2022-04-09 18:51:49 +00007505 SELECT cpos, printf('\"%w\"',printf('%!.*s%s', nlen-chop,name,suff)) AS cname \
larrybr42de1c52022-02-13 22:18:22 +00007506 FROM ColNames ORDER BY cpos\
7507)";
larrybr33633862022-02-14 01:12:46 +00007508 static const char * const zRenamesDone =
7509 "SELECT group_concat("
larrybr039132b2022-04-09 18:51:49 +00007510 " printf('\"%w\" to \"%w\"',name,printf('%!.*s%s', nlen-chop, name, suff)),"
larrybr33633862022-02-14 01:12:46 +00007511 " ','||x'0a')"
7512 "FROM ColNames WHERE suff<>'' OR chop!=0"
7513 ;
larrybr42de1c52022-02-13 22:18:22 +00007514 int rc;
7515 sqlite3_stmt *pStmt = 0;
7516 assert(pDb!=0);
7517 if( zColNew ){
7518 /* Add initial or additional column. Init db if necessary. */
7519 if( *pDb==0 ){
7520 if( SQLITE_OK!=sqlite3_open(zCOL_DB, pDb) ) return 0;
7521#ifdef SHELL_COLFIX_DB
7522 if(*zCOL_DB!=':')
larrybr33633862022-02-14 01:12:46 +00007523 sqlite3_exec(*pDb,"drop table if exists ColNames;"
7524 "drop view if exists RepeatedNames;",0,0,0);
larrybr42de1c52022-02-13 22:18:22 +00007525#endif
7526 rc = sqlite3_exec(*pDb, zTabMake, 0, 0, 0);
7527 rc_err_oom_die(rc);
7528 }
7529 assert(*pDb!=0);
7530 rc = sqlite3_prepare_v2(*pDb, zTabFill, -1, &pStmt, 0);
7531 rc_err_oom_die(rc);
7532 rc = sqlite3_bind_text(pStmt, 1, zColNew, -1, 0);
7533 rc_err_oom_die(rc);
7534 rc = sqlite3_step(pStmt);
7535 rc_err_oom_die(rc);
7536 sqlite3_finalize(pStmt);
7537 return 0;
7538 }else if( *pDb==0 ){
7539 return 0;
7540 }else{
7541 /* Formulate the columns spec, close the DB, zero *pDb. */
7542 char *zColsSpec = 0;
7543 int hasDupes = db_int(*pDb, zHasDupes);
larrybr42de1c52022-02-13 22:18:22 +00007544 int nDigits = (hasDupes)? db_int(*pDb, zColDigits) : 0;
larrybr42de1c52022-02-13 22:18:22 +00007545 if( hasDupes ){
larrybr33633862022-02-14 01:12:46 +00007546#ifdef SHELL_COLUMN_RENAME_CLEAN
larrybr42de1c52022-02-13 22:18:22 +00007547 rc = sqlite3_exec(*pDb, zDedoctor, 0, 0, 0);
7548 rc_err_oom_die(rc);
larrybr33633862022-02-14 01:12:46 +00007549#endif
larrybr42de1c52022-02-13 22:18:22 +00007550 rc = sqlite3_exec(*pDb, zSetReps, 0, 0, 0);
7551 rc_err_oom_die(rc);
7552 rc = sqlite3_prepare_v2(*pDb, zRenameRank, -1, &pStmt, 0);
7553 rc_err_oom_die(rc);
7554 sqlite3_bind_int(pStmt, 1, nDigits);
7555 rc = sqlite3_step(pStmt);
7556 sqlite3_finalize(pStmt);
7557 assert(rc==SQLITE_DONE);
7558 }
7559 assert(db_int(*pDb, zHasDupes)==0); /* Consider: remove this */
7560 rc = sqlite3_prepare_v2(*pDb, zCollectVar, -1, &pStmt, 0);
7561 rc_err_oom_die(rc);
7562 rc = sqlite3_step(pStmt);
7563 if( rc==SQLITE_ROW ){
7564 zColsSpec = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 0));
7565 }else{
7566 zColsSpec = 0;
7567 }
larrybr33633862022-02-14 01:12:46 +00007568 if( pzRenamed!=0 ){
7569 if( !hasDupes ) *pzRenamed = 0;
7570 else{
7571 sqlite3_finalize(pStmt);
7572 if( SQLITE_OK==sqlite3_prepare_v2(*pDb, zRenamesDone, -1, &pStmt, 0)
7573 && SQLITE_ROW==sqlite3_step(pStmt) ){
7574 *pzRenamed = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 0));
7575 }else
7576 *pzRenamed = 0;
7577 }
7578 }
larrybr42de1c52022-02-13 22:18:22 +00007579 sqlite3_finalize(pStmt);
7580 sqlite3_close(*pDb);
7581 *pDb = 0;
7582 return zColsSpec;
7583 }
7584}
7585
drh2ce15c32017-07-11 13:34:40 +00007586/*
7587** If an input line begins with "." then invoke this routine to
7588** process that line.
7589**
7590** Return 1 on error, 2 to exit, and 0 otherwise.
7591*/
7592static int do_meta_command(char *zLine, ShellState *p){
7593 int h = 1;
7594 int nArg = 0;
7595 int n, c;
7596 int rc = 0;
drh5df84282019-08-17 19:45:25 +00007597 char *azArg[52];
drh2ce15c32017-07-11 13:34:40 +00007598
dan6b046be2018-01-09 15:25:55 +00007599#ifndef SQLITE_OMIT_VIRTUALTABLE
dan43efc182017-12-19 17:42:13 +00007600 if( p->expert.pExpert ){
7601 expertFinish(p, 1, 0);
7602 }
dan6b046be2018-01-09 15:25:55 +00007603#endif
dan43efc182017-12-19 17:42:13 +00007604
drh2ce15c32017-07-11 13:34:40 +00007605 /* Parse the input line into tokens.
7606 */
drh5df84282019-08-17 19:45:25 +00007607 while( zLine[h] && nArg<ArraySize(azArg)-1 ){
drh2ce15c32017-07-11 13:34:40 +00007608 while( IsSpace(zLine[h]) ){ h++; }
7609 if( zLine[h]==0 ) break;
7610 if( zLine[h]=='\'' || zLine[h]=='"' ){
7611 int delim = zLine[h++];
7612 azArg[nArg++] = &zLine[h];
7613 while( zLine[h] && zLine[h]!=delim ){
7614 if( zLine[h]=='\\' && delim=='"' && zLine[h+1]!=0 ) h++;
7615 h++;
7616 }
7617 if( zLine[h]==delim ){
7618 zLine[h++] = 0;
7619 }
7620 if( delim=='"' ) resolve_backslashes(azArg[nArg-1]);
7621 }else{
7622 azArg[nArg++] = &zLine[h];
7623 while( zLine[h] && !IsSpace(zLine[h]) ){ h++; }
7624 if( zLine[h] ) zLine[h++] = 0;
7625 resolve_backslashes(azArg[nArg-1]);
7626 }
7627 }
drh5df84282019-08-17 19:45:25 +00007628 azArg[nArg] = 0;
drh2ce15c32017-07-11 13:34:40 +00007629
7630 /* Process the input line.
7631 */
7632 if( nArg==0 ) return 0; /* no tokens, no error */
7633 n = strlen30(azArg[0]);
7634 c = azArg[0][0];
drh13c20932018-01-10 21:41:55 +00007635 clearTempFile(p);
drh2ce15c32017-07-11 13:34:40 +00007636
7637#ifndef SQLITE_OMIT_AUTHORIZATION
drhbf70f1b2022-10-19 18:04:42 +00007638 if( c=='a' && cli_strncmp(azArg[0], "auth", n)==0 ){
drh2ce15c32017-07-11 13:34:40 +00007639 if( nArg!=2 ){
7640 raw_printf(stderr, "Usage: .auth ON|OFF\n");
7641 rc = 1;
7642 goto meta_command_exit;
7643 }
7644 open_db(p, 0);
7645 if( booleanValue(azArg[1]) ){
7646 sqlite3_set_authorizer(p->db, shellAuth, p);
drhb97e2ad2021-08-26 18:31:39 +00007647 }else if( p->bSafeModePersist ){
7648 sqlite3_set_authorizer(p->db, safeModeAuth, p);
drh2ce15c32017-07-11 13:34:40 +00007649 }else{
7650 sqlite3_set_authorizer(p->db, 0, 0);
7651 }
7652 }else
7653#endif
7654
stephan02520cc2022-05-18 22:58:34 +00007655#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB) \
stephan4413ec72022-07-12 15:53:02 +00007656 && !defined(SQLITE_SHELL_FIDDLE)
drhbf70f1b2022-10-19 18:04:42 +00007657 if( c=='a' && cli_strncmp(azArg[0], "archive", n)==0 ){
danfd0245d2017-12-07 15:44:29 +00007658 open_db(p, 0);
drhb97e2ad2021-08-26 18:31:39 +00007659 failIfSafeMode(p, "cannot run .archive in safe mode");
drhd0f9cdc2018-05-17 14:09:06 +00007660 rc = arDotCommand(p, 0, azArg, nArg);
danfd0245d2017-12-07 15:44:29 +00007661 }else
7662#endif
7663
stephan4413ec72022-07-12 15:53:02 +00007664#ifndef SQLITE_SHELL_FIDDLE
drhbf70f1b2022-10-19 18:04:42 +00007665 if( (c=='b' && n>=3 && cli_strncmp(azArg[0], "backup", n)==0)
7666 || (c=='s' && n>=3 && cli_strncmp(azArg[0], "save", n)==0)
drh2ce15c32017-07-11 13:34:40 +00007667 ){
7668 const char *zDestFile = 0;
7669 const char *zDb = 0;
7670 sqlite3 *pDest;
7671 sqlite3_backup *pBackup;
7672 int j;
drha50bffb2018-12-08 01:09:14 +00007673 int bAsync = 0;
drh69ed38a2018-05-14 00:23:08 +00007674 const char *zVfs = 0;
drhb97e2ad2021-08-26 18:31:39 +00007675 failIfSafeMode(p, "cannot run .%s in safe mode", azArg[0]);
drh2ce15c32017-07-11 13:34:40 +00007676 for(j=1; j<nArg; j++){
7677 const char *z = azArg[j];
7678 if( z[0]=='-' ){
drh69ed38a2018-05-14 00:23:08 +00007679 if( z[1]=='-' ) z++;
drhbf70f1b2022-10-19 18:04:42 +00007680 if( cli_strcmp(z, "-append")==0 ){
drh69ed38a2018-05-14 00:23:08 +00007681 zVfs = "apndvfs";
7682 }else
drhbf70f1b2022-10-19 18:04:42 +00007683 if( cli_strcmp(z, "-async")==0 ){
drha50bffb2018-12-08 01:09:14 +00007684 bAsync = 1;
7685 }else
drh2ce15c32017-07-11 13:34:40 +00007686 {
7687 utf8_printf(stderr, "unknown option: %s\n", azArg[j]);
7688 return 1;
7689 }
7690 }else if( zDestFile==0 ){
7691 zDestFile = azArg[j];
7692 }else if( zDb==0 ){
7693 zDb = zDestFile;
7694 zDestFile = azArg[j];
7695 }else{
drha50bffb2018-12-08 01:09:14 +00007696 raw_printf(stderr, "Usage: .backup ?DB? ?OPTIONS? FILENAME\n");
drh2ce15c32017-07-11 13:34:40 +00007697 return 1;
7698 }
7699 }
7700 if( zDestFile==0 ){
7701 raw_printf(stderr, "missing FILENAME argument on .backup\n");
7702 return 1;
7703 }
7704 if( zDb==0 ) zDb = "main";
drh69ed38a2018-05-14 00:23:08 +00007705 rc = sqlite3_open_v2(zDestFile, &pDest,
7706 SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE, zVfs);
drh2ce15c32017-07-11 13:34:40 +00007707 if( rc!=SQLITE_OK ){
7708 utf8_printf(stderr, "Error: cannot open \"%s\"\n", zDestFile);
drh9e804032018-05-18 17:11:50 +00007709 close_db(pDest);
drh2ce15c32017-07-11 13:34:40 +00007710 return 1;
7711 }
drha50bffb2018-12-08 01:09:14 +00007712 if( bAsync ){
7713 sqlite3_exec(pDest, "PRAGMA synchronous=OFF; PRAGMA journal_mode=OFF;",
7714 0, 0, 0);
7715 }
drh2ce15c32017-07-11 13:34:40 +00007716 open_db(p, 0);
7717 pBackup = sqlite3_backup_init(pDest, "main", p->db, zDb);
7718 if( pBackup==0 ){
7719 utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(pDest));
drh9e804032018-05-18 17:11:50 +00007720 close_db(pDest);
drh2ce15c32017-07-11 13:34:40 +00007721 return 1;
7722 }
7723 while( (rc = sqlite3_backup_step(pBackup,100))==SQLITE_OK ){}
7724 sqlite3_backup_finish(pBackup);
7725 if( rc==SQLITE_DONE ){
7726 rc = 0;
7727 }else{
7728 utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(pDest));
7729 rc = 1;
7730 }
drh9e804032018-05-18 17:11:50 +00007731 close_db(pDest);
drh2ce15c32017-07-11 13:34:40 +00007732 }else
stephan4413ec72022-07-12 15:53:02 +00007733#endif /* !defined(SQLITE_SHELL_FIDDLE) */
drh2ce15c32017-07-11 13:34:40 +00007734
drhbf70f1b2022-10-19 18:04:42 +00007735 if( c=='b' && n>=3 && cli_strncmp(azArg[0], "bail", n)==0 ){
drh2ce15c32017-07-11 13:34:40 +00007736 if( nArg==2 ){
7737 bail_on_error = booleanValue(azArg[1]);
7738 }else{
7739 raw_printf(stderr, "Usage: .bail on|off\n");
7740 rc = 1;
7741 }
7742 }else
7743
drhbf70f1b2022-10-19 18:04:42 +00007744 if( c=='b' && n>=3 && cli_strncmp(azArg[0], "binary", n)==0 ){
drh2ce15c32017-07-11 13:34:40 +00007745 if( nArg==2 ){
7746 if( booleanValue(azArg[1]) ){
7747 setBinaryMode(p->out, 1);
7748 }else{
7749 setTextMode(p->out, 1);
7750 }
7751 }else{
7752 raw_printf(stderr, "Usage: .binary on|off\n");
7753 rc = 1;
7754 }
7755 }else
7756
drh37407122021-07-23 18:43:58 +00007757 /* The undocumented ".breakpoint" command causes a call to the no-op
7758 ** routine named test_breakpoint().
7759 */
drhbf70f1b2022-10-19 18:04:42 +00007760 if( c=='b' && n>=3 && cli_strncmp(azArg[0], "breakpoint", n)==0 ){
drh37407122021-07-23 18:43:58 +00007761 test_breakpoint();
7762 }else
7763
stephan4413ec72022-07-12 15:53:02 +00007764#ifndef SQLITE_SHELL_FIDDLE
drhbf70f1b2022-10-19 18:04:42 +00007765 if( c=='c' && cli_strcmp(azArg[0],"cd")==0 ){
drhb97e2ad2021-08-26 18:31:39 +00007766 failIfSafeMode(p, "cannot run .cd in safe mode");
drh2ce15c32017-07-11 13:34:40 +00007767 if( nArg==2 ){
7768#if defined(_WIN32) || defined(WIN32)
7769 wchar_t *z = sqlite3_win32_utf8_to_unicode(azArg[1]);
7770 rc = !SetCurrentDirectoryW(z);
7771 sqlite3_free(z);
7772#else
7773 rc = chdir(azArg[1]);
7774#endif
7775 if( rc ){
7776 utf8_printf(stderr, "Cannot change to directory \"%s\"\n", azArg[1]);
7777 rc = 1;
7778 }
7779 }else{
7780 raw_printf(stderr, "Usage: .cd DIRECTORY\n");
7781 rc = 1;
7782 }
7783 }else
stephan4413ec72022-07-12 15:53:02 +00007784#endif /* !defined(SQLITE_SHELL_FIDDLE) */
drh2ce15c32017-07-11 13:34:40 +00007785
drhbf70f1b2022-10-19 18:04:42 +00007786 if( c=='c' && n>=3 && cli_strncmp(azArg[0], "changes", n)==0 ){
drh2ce15c32017-07-11 13:34:40 +00007787 if( nArg==2 ){
7788 setOrClearFlag(p, SHFLG_CountChanges, azArg[1]);
7789 }else{
7790 raw_printf(stderr, "Usage: .changes on|off\n");
7791 rc = 1;
7792 }
7793 }else
7794
stephan4413ec72022-07-12 15:53:02 +00007795#ifndef SQLITE_SHELL_FIDDLE
drh2ce15c32017-07-11 13:34:40 +00007796 /* Cancel output redirection, if it is currently set (by .testcase)
7797 ** Then read the content of the testcase-out.txt file and compare against
7798 ** azArg[1]. If there are differences, report an error and exit.
7799 */
drhbf70f1b2022-10-19 18:04:42 +00007800 if( c=='c' && n>=3 && cli_strncmp(azArg[0], "check", n)==0 ){
drh2ce15c32017-07-11 13:34:40 +00007801 char *zRes = 0;
7802 output_reset(p);
7803 if( nArg!=2 ){
7804 raw_printf(stderr, "Usage: .check GLOB-PATTERN\n");
7805 rc = 2;
7806 }else if( (zRes = readFile("testcase-out.txt", 0))==0 ){
7807 raw_printf(stderr, "Error: cannot read 'testcase-out.txt'\n");
7808 rc = 2;
7809 }else if( testcase_glob(azArg[1],zRes)==0 ){
7810 utf8_printf(stderr,
7811 "testcase-%s FAILED\n Expected: [%s]\n Got: [%s]\n",
7812 p->zTestcase, azArg[1], zRes);
drhf30d3452017-10-17 13:44:46 +00007813 rc = 1;
drh2ce15c32017-07-11 13:34:40 +00007814 }else{
7815 utf8_printf(stdout, "testcase-%s ok\n", p->zTestcase);
7816 p->nCheck++;
7817 }
7818 sqlite3_free(zRes);
7819 }else
stephan4413ec72022-07-12 15:53:02 +00007820#endif /* !defined(SQLITE_SHELL_FIDDLE) */
drh2ce15c32017-07-11 13:34:40 +00007821
stephan4413ec72022-07-12 15:53:02 +00007822#ifndef SQLITE_SHELL_FIDDLE
drhbf70f1b2022-10-19 18:04:42 +00007823 if( c=='c' && cli_strncmp(azArg[0], "clone", n)==0 ){
drhb97e2ad2021-08-26 18:31:39 +00007824 failIfSafeMode(p, "cannot run .clone in safe mode");
drh2ce15c32017-07-11 13:34:40 +00007825 if( nArg==2 ){
7826 tryToClone(p, azArg[1]);
7827 }else{
7828 raw_printf(stderr, "Usage: .clone FILENAME\n");
7829 rc = 1;
7830 }
7831 }else
stephan4413ec72022-07-12 15:53:02 +00007832#endif /* !defined(SQLITE_SHELL_FIDDLE) */
drh2ce15c32017-07-11 13:34:40 +00007833
drhbf70f1b2022-10-19 18:04:42 +00007834 if( c=='c' && cli_strncmp(azArg[0], "connection", n)==0 ){
drh37407122021-07-23 18:43:58 +00007835 if( nArg==1 ){
7836 /* List available connections */
7837 int i;
7838 for(i=0; i<ArraySize(p->aAuxDb); i++){
7839 const char *zFile = p->aAuxDb[i].zDbFilename;
7840 if( p->aAuxDb[i].db==0 && p->pAuxDb!=&p->aAuxDb[i] ){
7841 zFile = "(not open)";
7842 }else if( zFile==0 ){
7843 zFile = "(memory)";
7844 }else if( zFile[0]==0 ){
7845 zFile = "(temporary-file)";
7846 }
7847 if( p->pAuxDb == &p->aAuxDb[i] ){
7848 utf8_printf(stdout, "ACTIVE %d: %s\n", i, zFile);
7849 }else if( p->aAuxDb[i].db!=0 ){
7850 utf8_printf(stdout, " %d: %s\n", i, zFile);
7851 }
7852 }
7853 }else if( nArg==2 && IsDigit(azArg[1][0]) && azArg[1][1]==0 ){
7854 int i = azArg[1][0] - '0';
7855 if( p->pAuxDb != &p->aAuxDb[i] && i>=0 && i<ArraySize(p->aAuxDb) ){
7856 p->pAuxDb->db = p->db;
7857 p->pAuxDb = &p->aAuxDb[i];
7858 globalDb = p->db = p->pAuxDb->db;
7859 p->pAuxDb->db = 0;
7860 }
drhbf70f1b2022-10-19 18:04:42 +00007861 }else if( nArg==3 && cli_strcmp(azArg[1], "close")==0
drh37407122021-07-23 18:43:58 +00007862 && IsDigit(azArg[2][0]) && azArg[2][1]==0 ){
7863 int i = azArg[2][0] - '0';
7864 if( i<0 || i>=ArraySize(p->aAuxDb) ){
7865 /* No-op */
7866 }else if( p->pAuxDb == &p->aAuxDb[i] ){
7867 raw_printf(stderr, "cannot close the active database connection\n");
7868 rc = 1;
7869 }else if( p->aAuxDb[i].db ){
7870 session_close_all(p, i);
7871 close_db(p->aAuxDb[i].db);
7872 p->aAuxDb[i].db = 0;
7873 }
7874 }else{
7875 raw_printf(stderr, "Usage: .connection [close] [CONNECTION-NUMBER]\n");
7876 rc = 1;
7877 }
7878 }else
7879
drhbf70f1b2022-10-19 18:04:42 +00007880 if( c=='d' && n>1 && cli_strncmp(azArg[0], "databases", n)==0 ){
drh60081a02020-08-26 19:07:18 +00007881 char **azName = 0;
7882 int nName = 0;
7883 sqlite3_stmt *pStmt;
drh60081a02020-08-26 19:07:18 +00007884 int i;
drh2ce15c32017-07-11 13:34:40 +00007885 open_db(p, 0);
drh60081a02020-08-26 19:07:18 +00007886 rc = sqlite3_prepare_v2(p->db, "PRAGMA database_list", -1, &pStmt, 0);
7887 if( rc ){
7888 utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
drh2ce15c32017-07-11 13:34:40 +00007889 rc = 1;
drh60081a02020-08-26 19:07:18 +00007890 }else{
7891 while( sqlite3_step(pStmt)==SQLITE_ROW ){
7892 const char *zSchema = (const char *)sqlite3_column_text(pStmt,1);
7893 const char *zFile = (const char*)sqlite3_column_text(pStmt,2);
drh621a5e02021-12-16 17:35:27 +00007894 if( zSchema==0 || zFile==0 ) continue;
drh60081a02020-08-26 19:07:18 +00007895 azName = sqlite3_realloc(azName, (nName+1)*2*sizeof(char*));
drhe3e25652021-12-16 13:29:28 +00007896 shell_check_oom(azName);
drh60081a02020-08-26 19:07:18 +00007897 azName[nName*2] = strdup(zSchema);
7898 azName[nName*2+1] = strdup(zFile);
7899 nName++;
7900 }
drh2ce15c32017-07-11 13:34:40 +00007901 }
drh60081a02020-08-26 19:07:18 +00007902 sqlite3_finalize(pStmt);
7903 for(i=0; i<nName; i++){
7904 int eTxn = sqlite3_txn_state(p->db, azName[i*2]);
7905 int bRdonly = sqlite3_db_readonly(p->db, azName[i*2]);
7906 const char *z = azName[i*2+1];
7907 utf8_printf(p->out, "%s: %s %s%s\n",
7908 azName[i*2],
7909 z && z[0] ? z : "\"\"",
7910 bRdonly ? "r/o" : "r/w",
7911 eTxn==SQLITE_TXN_NONE ? "" :
7912 eTxn==SQLITE_TXN_READ ? " read-txn" : " write-txn");
7913 free(azName[i*2]);
7914 free(azName[i*2+1]);
7915 }
7916 sqlite3_free(azName);
drh2ce15c32017-07-11 13:34:40 +00007917 }else
7918
drhbf70f1b2022-10-19 18:04:42 +00007919 if( c=='d' && n>=3 && cli_strncmp(azArg[0], "dbconfig", n)==0 ){
drheb7f2a02018-09-26 18:02:32 +00007920 static const struct DbConfigChoices {
7921 const char *zName;
7922 int op;
7923 } aDbConfig[] = {
drhb945bcd2019-12-31 22:52:10 +00007924 { "defensive", SQLITE_DBCONFIG_DEFENSIVE },
7925 { "dqs_ddl", SQLITE_DBCONFIG_DQS_DDL },
7926 { "dqs_dml", SQLITE_DBCONFIG_DQS_DML },
drh0a6873b2019-06-14 21:25:25 +00007927 { "enable_fkey", SQLITE_DBCONFIG_ENABLE_FKEY },
drhb945bcd2019-12-31 22:52:10 +00007928 { "enable_qpsg", SQLITE_DBCONFIG_ENABLE_QPSG },
drh0a6873b2019-06-14 21:25:25 +00007929 { "enable_trigger", SQLITE_DBCONFIG_ENABLE_TRIGGER },
drh11d88e62019-08-15 21:27:20 +00007930 { "enable_view", SQLITE_DBCONFIG_ENABLE_VIEW },
drh0a6873b2019-06-14 21:25:25 +00007931 { "fts3_tokenizer", SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER },
drhb945bcd2019-12-31 22:52:10 +00007932 { "legacy_alter_table", SQLITE_DBCONFIG_LEGACY_ALTER_TABLE },
7933 { "legacy_file_format", SQLITE_DBCONFIG_LEGACY_FILE_FORMAT },
drh0a6873b2019-06-14 21:25:25 +00007934 { "load_extension", SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION },
7935 { "no_ckpt_on_close", SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE },
drh0a6873b2019-06-14 21:25:25 +00007936 { "reset_database", SQLITE_DBCONFIG_RESET_DATABASE },
drhb945bcd2019-12-31 22:52:10 +00007937 { "trigger_eqp", SQLITE_DBCONFIG_TRIGGER_EQP },
drhb77da372020-01-07 16:09:11 +00007938 { "trusted_schema", SQLITE_DBCONFIG_TRUSTED_SCHEMA },
dan07312a62019-06-21 14:05:27 +00007939 { "writable_schema", SQLITE_DBCONFIG_WRITABLE_SCHEMA },
drh7df01192018-04-28 12:43:16 +00007940 };
7941 int ii, v;
7942 open_db(p, 0);
7943 for(ii=0; ii<ArraySize(aDbConfig); ii++){
drhbf70f1b2022-10-19 18:04:42 +00007944 if( nArg>1 && cli_strcmp(azArg[1], aDbConfig[ii].zName)!=0 ) continue;
drh7df01192018-04-28 12:43:16 +00007945 if( nArg>=3 ){
7946 sqlite3_db_config(p->db, aDbConfig[ii].op, booleanValue(azArg[2]), 0);
7947 }
7948 sqlite3_db_config(p->db, aDbConfig[ii].op, -1, &v);
drhb945bcd2019-12-31 22:52:10 +00007949 utf8_printf(p->out, "%19s %s\n", aDbConfig[ii].zName, v ? "on" : "off");
drh7df01192018-04-28 12:43:16 +00007950 if( nArg>1 ) break;
7951 }
7952 if( nArg>1 && ii==ArraySize(aDbConfig) ){
7953 utf8_printf(stderr, "Error: unknown dbconfig \"%s\"\n", azArg[1]);
7954 utf8_printf(stderr, "Enter \".dbconfig\" with no arguments for a list\n");
7955 }
7956 }else
7957
stephan3d420832022-10-27 03:56:01 +00007958#if SQLITE_SHELL_HAVE_RECOVER
drhbf70f1b2022-10-19 18:04:42 +00007959 if( c=='d' && n>=3 && cli_strncmp(azArg[0], "dbinfo", n)==0 ){
drh2ce15c32017-07-11 13:34:40 +00007960 rc = shell_dbinfo_command(p, nArg, azArg);
7961 }else
7962
drhbf70f1b2022-10-19 18:04:42 +00007963 if( c=='r' && cli_strncmp(azArg[0], "recover", n)==0 ){
dan68cb86e2019-04-20 20:57:28 +00007964 open_db(p, 0);
danb9b71db2019-04-25 16:20:40 +00007965 rc = recoverDatabaseCmd(p, nArg, azArg);
dan68cb86e2019-04-20 20:57:28 +00007966 }else
stephan3d420832022-10-27 03:56:01 +00007967#endif /* SQLITE_SHELL_HAVE_RECOVER */
dan68cb86e2019-04-20 20:57:28 +00007968
drhbf70f1b2022-10-19 18:04:42 +00007969 if( c=='d' && cli_strncmp(azArg[0], "dump", n)==0 ){
drh8e9297f2020-03-25 12:50:13 +00007970 char *zLike = 0;
7971 char *zSql;
drh2ce15c32017-07-11 13:34:40 +00007972 int i;
7973 int savedShowHeader = p->showHeader;
drhf213b332018-07-05 17:35:46 +00007974 int savedShellFlags = p->shellFlgs;
larrybr527c39d2022-05-10 14:55:45 +00007975 ShellClearFlag(p,
drhc1962192020-10-12 16:54:28 +00007976 SHFLG_PreserveRowid|SHFLG_Newlines|SHFLG_Echo
7977 |SHFLG_DumpDataOnly|SHFLG_DumpNoSys);
drh2ce15c32017-07-11 13:34:40 +00007978 for(i=1; i<nArg; i++){
7979 if( azArg[i][0]=='-' ){
7980 const char *z = azArg[i]+1;
7981 if( z[0]=='-' ) z++;
drhbf70f1b2022-10-19 18:04:42 +00007982 if( cli_strcmp(z,"preserve-rowids")==0 ){
drh2ce15c32017-07-11 13:34:40 +00007983#ifdef SQLITE_OMIT_VIRTUALTABLE
7984 raw_printf(stderr, "The --preserve-rowids option is not compatible"
7985 " with SQLITE_OMIT_VIRTUALTABLE\n");
7986 rc = 1;
drh1d29fd82020-05-29 19:03:03 +00007987 sqlite3_free(zLike);
drh2ce15c32017-07-11 13:34:40 +00007988 goto meta_command_exit;
7989#else
7990 ShellSetFlag(p, SHFLG_PreserveRowid);
7991#endif
7992 }else
drhbf70f1b2022-10-19 18:04:42 +00007993 if( cli_strcmp(z,"newlines")==0 ){
drh2ce15c32017-07-11 13:34:40 +00007994 ShellSetFlag(p, SHFLG_Newlines);
7995 }else
drhbf70f1b2022-10-19 18:04:42 +00007996 if( cli_strcmp(z,"data-only")==0 ){
drhc1962192020-10-12 16:54:28 +00007997 ShellSetFlag(p, SHFLG_DumpDataOnly);
7998 }else
drhbf70f1b2022-10-19 18:04:42 +00007999 if( cli_strcmp(z,"nosys")==0 ){
drhc1962192020-10-12 16:54:28 +00008000 ShellSetFlag(p, SHFLG_DumpNoSys);
8001 }else
drh2ce15c32017-07-11 13:34:40 +00008002 {
8003 raw_printf(stderr, "Unknown option \"%s\" on \".dump\"\n", azArg[i]);
8004 rc = 1;
drh1d29fd82020-05-29 19:03:03 +00008005 sqlite3_free(zLike);
drh2ce15c32017-07-11 13:34:40 +00008006 goto meta_command_exit;
8007 }
drh2ce15c32017-07-11 13:34:40 +00008008 }else{
dan78a9d752021-05-25 11:39:14 +00008009 /* azArg[i] contains a LIKE pattern. This ".dump" request should
8010 ** only dump data for tables for which either the table name matches
8011 ** the LIKE pattern, or the table appears to be a shadow table of
8012 ** a virtual table for which the name matches the LIKE pattern.
8013 */
8014 char *zExpr = sqlite3_mprintf(
8015 "name LIKE %Q ESCAPE '\\' OR EXISTS ("
8016 " SELECT 1 FROM sqlite_schema WHERE "
8017 " name LIKE %Q ESCAPE '\\' AND"
8018 " sql LIKE 'CREATE VIRTUAL TABLE%%' AND"
8019 " substr(o.name, 1, length(name)+1) == (name||'_')"
8020 ")", azArg[i], azArg[i]
8021 );
8022
8023 if( zLike ){
8024 zLike = sqlite3_mprintf("%z OR %z", zLike, zExpr);
8025 }else{
8026 zLike = zExpr;
8027 }
drh2ce15c32017-07-11 13:34:40 +00008028 }
8029 }
dan68cb86e2019-04-20 20:57:28 +00008030
drh2ce15c32017-07-11 13:34:40 +00008031 open_db(p, 0);
dan68cb86e2019-04-20 20:57:28 +00008032
drhc1962192020-10-12 16:54:28 +00008033 if( (p->shellFlgs & SHFLG_DumpDataOnly)==0 ){
8034 /* When playing back a "dump", the content might appear in an order
8035 ** which causes immediate foreign key constraints to be violated.
8036 ** So disable foreign-key constraint enforcement to prevent problems. */
8037 raw_printf(p->out, "PRAGMA foreign_keys=OFF;\n");
8038 raw_printf(p->out, "BEGIN TRANSACTION;\n");
8039 }
drh2ce15c32017-07-11 13:34:40 +00008040 p->writableSchema = 0;
8041 p->showHeader = 0;
8042 /* Set writable_schema=ON since doing so forces SQLite to initialize
drh067b92b2020-06-19 15:24:12 +00008043 ** as much of the schema as it can even if the sqlite_schema table is
drh2ce15c32017-07-11 13:34:40 +00008044 ** corrupt. */
8045 sqlite3_exec(p->db, "SAVEPOINT dump; PRAGMA writable_schema=ON", 0, 0, 0);
8046 p->nErr = 0;
drh8e9297f2020-03-25 12:50:13 +00008047 if( zLike==0 ) zLike = sqlite3_mprintf("true");
8048 zSql = sqlite3_mprintf(
dan78a9d752021-05-25 11:39:14 +00008049 "SELECT name, type, sql FROM sqlite_schema AS o "
drh8e9297f2020-03-25 12:50:13 +00008050 "WHERE (%s) AND type=='table'"
8051 " AND sql NOT NULL"
8052 " ORDER BY tbl_name='sqlite_sequence', rowid",
8053 zLike
8054 );
8055 run_schema_dump_query(p,zSql);
8056 sqlite3_free(zSql);
drhc1962192020-10-12 16:54:28 +00008057 if( (p->shellFlgs & SHFLG_DumpDataOnly)==0 ){
8058 zSql = sqlite3_mprintf(
dan78a9d752021-05-25 11:39:14 +00008059 "SELECT sql FROM sqlite_schema AS o "
drhc1962192020-10-12 16:54:28 +00008060 "WHERE (%s) AND sql NOT NULL"
8061 " AND type IN ('index','trigger','view')",
8062 zLike
8063 );
8064 run_table_dump_query(p, zSql);
8065 sqlite3_free(zSql);
8066 }
drh8e9297f2020-03-25 12:50:13 +00008067 sqlite3_free(zLike);
drh2ce15c32017-07-11 13:34:40 +00008068 if( p->writableSchema ){
8069 raw_printf(p->out, "PRAGMA writable_schema=OFF;\n");
8070 p->writableSchema = 0;
8071 }
8072 sqlite3_exec(p->db, "PRAGMA writable_schema=OFF;", 0, 0, 0);
8073 sqlite3_exec(p->db, "RELEASE dump;", 0, 0, 0);
drhc1962192020-10-12 16:54:28 +00008074 if( (p->shellFlgs & SHFLG_DumpDataOnly)==0 ){
8075 raw_printf(p->out, p->nErr?"ROLLBACK; -- due to errors\n":"COMMIT;\n");
8076 }
drh2ce15c32017-07-11 13:34:40 +00008077 p->showHeader = savedShowHeader;
drhf213b332018-07-05 17:35:46 +00008078 p->shellFlgs = savedShellFlags;
drh2ce15c32017-07-11 13:34:40 +00008079 }else
8080
drhbf70f1b2022-10-19 18:04:42 +00008081 if( c=='e' && cli_strncmp(azArg[0], "echo", n)==0 ){
drh2ce15c32017-07-11 13:34:40 +00008082 if( nArg==2 ){
8083 setOrClearFlag(p, SHFLG_Echo, azArg[1]);
8084 }else{
8085 raw_printf(stderr, "Usage: .echo on|off\n");
8086 rc = 1;
8087 }
8088 }else
8089
drhbf70f1b2022-10-19 18:04:42 +00008090 if( c=='e' && cli_strncmp(azArg[0], "eqp", n)==0 ){
drh2ce15c32017-07-11 13:34:40 +00008091 if( nArg==2 ){
drhe2ca99c2018-05-02 00:33:43 +00008092 p->autoEQPtest = 0;
drhb4e50392019-01-26 15:40:04 +00008093 if( p->autoEQPtrace ){
8094 if( p->db ) sqlite3_exec(p->db, "PRAGMA vdbe_trace=OFF;", 0, 0, 0);
8095 p->autoEQPtrace = 0;
8096 }
drhbf70f1b2022-10-19 18:04:42 +00008097 if( cli_strcmp(azArg[1],"full")==0 ){
drhada70452017-12-21 21:02:27 +00008098 p->autoEQP = AUTOEQP_full;
drhbf70f1b2022-10-19 18:04:42 +00008099 }else if( cli_strcmp(azArg[1],"trigger")==0 ){
drhada70452017-12-21 21:02:27 +00008100 p->autoEQP = AUTOEQP_trigger;
drhb4e50392019-01-26 15:40:04 +00008101#ifdef SQLITE_DEBUG
drhbf70f1b2022-10-19 18:04:42 +00008102 }else if( cli_strcmp(azArg[1],"test")==0 ){
drhe2ca99c2018-05-02 00:33:43 +00008103 p->autoEQP = AUTOEQP_on;
8104 p->autoEQPtest = 1;
drhbf70f1b2022-10-19 18:04:42 +00008105 }else if( cli_strcmp(azArg[1],"trace")==0 ){
drhb4e50392019-01-26 15:40:04 +00008106 p->autoEQP = AUTOEQP_full;
8107 p->autoEQPtrace = 1;
8108 open_db(p, 0);
drh067b92b2020-06-19 15:24:12 +00008109 sqlite3_exec(p->db, "SELECT name FROM sqlite_schema LIMIT 1", 0, 0, 0);
drhb4e50392019-01-26 15:40:04 +00008110 sqlite3_exec(p->db, "PRAGMA vdbe_trace=ON;", 0, 0, 0);
8111#endif
drh2ce15c32017-07-11 13:34:40 +00008112 }else{
mistachkinb71aa092018-01-23 00:05:18 +00008113 p->autoEQP = (u8)booleanValue(azArg[1]);
drh2ce15c32017-07-11 13:34:40 +00008114 }
8115 }else{
drhb4e50392019-01-26 15:40:04 +00008116 raw_printf(stderr, "Usage: .eqp off|on|trace|trigger|full\n");
drh2ce15c32017-07-11 13:34:40 +00008117 rc = 1;
8118 }
8119 }else
8120
stephan4413ec72022-07-12 15:53:02 +00008121#ifndef SQLITE_SHELL_FIDDLE
drhbf70f1b2022-10-19 18:04:42 +00008122 if( c=='e' && cli_strncmp(azArg[0], "exit", n)==0 ){
drh2ce15c32017-07-11 13:34:40 +00008123 if( nArg>1 && (rc = (int)integerValue(azArg[1]))!=0 ) exit(rc);
8124 rc = 2;
8125 }else
stephan02520cc2022-05-18 22:58:34 +00008126#endif
drh2ce15c32017-07-11 13:34:40 +00008127
8128 /* The ".explain" command is automatic now. It is largely pointless. It
8129 ** retained purely for backwards compatibility */
drhbf70f1b2022-10-19 18:04:42 +00008130 if( c=='e' && cli_strncmp(azArg[0], "explain", n)==0 ){
drh2ce15c32017-07-11 13:34:40 +00008131 int val = 1;
8132 if( nArg>=2 ){
drhbf70f1b2022-10-19 18:04:42 +00008133 if( cli_strcmp(azArg[1],"auto")==0 ){
drh2ce15c32017-07-11 13:34:40 +00008134 val = 99;
8135 }else{
8136 val = booleanValue(azArg[1]);
8137 }
8138 }
8139 if( val==1 && p->mode!=MODE_Explain ){
8140 p->normalMode = p->mode;
8141 p->mode = MODE_Explain;
8142 p->autoExplain = 0;
8143 }else if( val==0 ){
8144 if( p->mode==MODE_Explain ) p->mode = p->normalMode;
8145 p->autoExplain = 0;
8146 }else if( val==99 ){
8147 if( p->mode==MODE_Explain ) p->mode = p->normalMode;
8148 p->autoExplain = 1;
8149 }
8150 }else
8151
dan6b046be2018-01-09 15:25:55 +00008152#ifndef SQLITE_OMIT_VIRTUALTABLE
drhbf70f1b2022-10-19 18:04:42 +00008153 if( c=='e' && cli_strncmp(azArg[0], "expert", n)==0 ){
drhfe463172021-12-16 17:57:21 +00008154 if( p->bSafeMode ){
8155 raw_printf(stderr,
8156 "Cannot run experimental commands such as \"%s\" in safe mode\n",
8157 azArg[0]);
8158 rc = 1;
8159 }else{
8160 open_db(p, 0);
8161 expertDotCommand(p, azArg, nArg);
8162 }
dan43efc182017-12-19 17:42:13 +00008163 }else
dan6b046be2018-01-09 15:25:55 +00008164#endif
dan43efc182017-12-19 17:42:13 +00008165
drhbf70f1b2022-10-19 18:04:42 +00008166 if( c=='f' && cli_strncmp(azArg[0], "filectrl", n)==0 ){
drhd985f722019-06-05 14:29:53 +00008167 static const struct {
8168 const char *zCtrlName; /* Name of a test-control option */
8169 int ctrlCode; /* Integer code for that option */
8170 const char *zUsage; /* Usage notes */
8171 } aCtrl[] = {
drhd985f722019-06-05 14:29:53 +00008172 { "chunk_size", SQLITE_FCNTL_CHUNK_SIZE, "SIZE" },
drh18a4bbd2020-12-17 15:17:42 +00008173 { "data_version", SQLITE_FCNTL_DATA_VERSION, "" },
drhd985f722019-06-05 14:29:53 +00008174 { "has_moved", SQLITE_FCNTL_HAS_MOVED, "" },
8175 { "lock_timeout", SQLITE_FCNTL_LOCK_TIMEOUT, "MILLISEC" },
drh18a4bbd2020-12-17 15:17:42 +00008176 { "persist_wal", SQLITE_FCNTL_PERSIST_WAL, "[BOOLEAN]" },
8177 /* { "pragma", SQLITE_FCNTL_PRAGMA, "NAME ARG" },*/
8178 { "psow", SQLITE_FCNTL_POWERSAFE_OVERWRITE, "[BOOLEAN]" },
drh541ef2c2020-04-20 16:21:30 +00008179 { "reserve_bytes", SQLITE_FCNTL_RESERVE_BYTES, "[N]" },
drh18a4bbd2020-12-17 15:17:42 +00008180 { "size_limit", SQLITE_FCNTL_SIZE_LIMIT, "[LIMIT]" },
8181 { "tempfilename", SQLITE_FCNTL_TEMPFILENAME, "" },
8182 /* { "win32_av_retry", SQLITE_FCNTL_WIN32_AV_RETRY, "COUNT DELAY" },*/
drhd985f722019-06-05 14:29:53 +00008183 };
8184 int filectrl = -1;
8185 int iCtrl = -1;
drh4245e042019-06-13 13:52:46 +00008186 sqlite3_int64 iRes = 0; /* Integer result to display if rc2==1 */
8187 int isOk = 0; /* 0: usage 1: %lld 2: no-result */
drhd985f722019-06-05 14:29:53 +00008188 int n2, i;
8189 const char *zCmd = 0;
drh541ef2c2020-04-20 16:21:30 +00008190 const char *zSchema = 0;
drhd985f722019-06-05 14:29:53 +00008191
8192 open_db(p, 0);
8193 zCmd = nArg>=2 ? azArg[1] : "help";
8194
drh541ef2c2020-04-20 16:21:30 +00008195 if( zCmd[0]=='-'
drhbf70f1b2022-10-19 18:04:42 +00008196 && (cli_strcmp(zCmd,"--schema")==0 || cli_strcmp(zCmd,"-schema")==0)
drh541ef2c2020-04-20 16:21:30 +00008197 && nArg>=4
8198 ){
8199 zSchema = azArg[2];
8200 for(i=3; i<nArg; i++) azArg[i-2] = azArg[i];
8201 nArg -= 2;
8202 zCmd = azArg[1];
8203 }
8204
drhd985f722019-06-05 14:29:53 +00008205 /* The argument can optionally begin with "-" or "--" */
8206 if( zCmd[0]=='-' && zCmd[1] ){
8207 zCmd++;
8208 if( zCmd[0]=='-' && zCmd[1] ) zCmd++;
8209 }
8210
8211 /* --help lists all file-controls */
drhbf70f1b2022-10-19 18:04:42 +00008212 if( cli_strcmp(zCmd,"help")==0 ){
drhd985f722019-06-05 14:29:53 +00008213 utf8_printf(p->out, "Available file-controls:\n");
8214 for(i=0; i<ArraySize(aCtrl); i++){
8215 utf8_printf(p->out, " .filectrl %s %s\n",
8216 aCtrl[i].zCtrlName, aCtrl[i].zUsage);
8217 }
8218 rc = 1;
8219 goto meta_command_exit;
8220 }
8221
8222 /* convert filectrl text option to value. allow any unique prefix
8223 ** of the option name, or a numerical value. */
8224 n2 = strlen30(zCmd);
8225 for(i=0; i<ArraySize(aCtrl); i++){
drhbf70f1b2022-10-19 18:04:42 +00008226 if( cli_strncmp(zCmd, aCtrl[i].zCtrlName, n2)==0 ){
drhd985f722019-06-05 14:29:53 +00008227 if( filectrl<0 ){
8228 filectrl = aCtrl[i].ctrlCode;
8229 iCtrl = i;
8230 }else{
8231 utf8_printf(stderr, "Error: ambiguous file-control: \"%s\"\n"
8232 "Use \".filectrl --help\" for help\n", zCmd);
8233 rc = 1;
8234 goto meta_command_exit;
8235 }
8236 }
8237 }
8238 if( filectrl<0 ){
8239 utf8_printf(stderr,"Error: unknown file-control: %s\n"
8240 "Use \".filectrl --help\" for help\n", zCmd);
8241 }else{
8242 switch(filectrl){
8243 case SQLITE_FCNTL_SIZE_LIMIT: {
8244 if( nArg!=2 && nArg!=3 ) break;
8245 iRes = nArg==3 ? integerValue(azArg[2]) : -1;
drh541ef2c2020-04-20 16:21:30 +00008246 sqlite3_file_control(p->db, zSchema, SQLITE_FCNTL_SIZE_LIMIT, &iRes);
drhd985f722019-06-05 14:29:53 +00008247 isOk = 1;
8248 break;
8249 }
8250 case SQLITE_FCNTL_LOCK_TIMEOUT:
8251 case SQLITE_FCNTL_CHUNK_SIZE: {
8252 int x;
8253 if( nArg!=3 ) break;
8254 x = (int)integerValue(azArg[2]);
drh541ef2c2020-04-20 16:21:30 +00008255 sqlite3_file_control(p->db, zSchema, filectrl, &x);
drhd985f722019-06-05 14:29:53 +00008256 isOk = 2;
8257 break;
8258 }
8259 case SQLITE_FCNTL_PERSIST_WAL:
8260 case SQLITE_FCNTL_POWERSAFE_OVERWRITE: {
8261 int x;
8262 if( nArg!=2 && nArg!=3 ) break;
8263 x = nArg==3 ? booleanValue(azArg[2]) : -1;
drh541ef2c2020-04-20 16:21:30 +00008264 sqlite3_file_control(p->db, zSchema, filectrl, &x);
drhd985f722019-06-05 14:29:53 +00008265 iRes = x;
8266 isOk = 1;
8267 break;
8268 }
drh18a4bbd2020-12-17 15:17:42 +00008269 case SQLITE_FCNTL_DATA_VERSION:
drhd985f722019-06-05 14:29:53 +00008270 case SQLITE_FCNTL_HAS_MOVED: {
8271 int x;
8272 if( nArg!=2 ) break;
drh541ef2c2020-04-20 16:21:30 +00008273 sqlite3_file_control(p->db, zSchema, filectrl, &x);
drhd985f722019-06-05 14:29:53 +00008274 iRes = x;
8275 isOk = 1;
8276 break;
8277 }
8278 case SQLITE_FCNTL_TEMPFILENAME: {
8279 char *z = 0;
8280 if( nArg!=2 ) break;
drh541ef2c2020-04-20 16:21:30 +00008281 sqlite3_file_control(p->db, zSchema, filectrl, &z);
drhd985f722019-06-05 14:29:53 +00008282 if( z ){
8283 utf8_printf(p->out, "%s\n", z);
8284 sqlite3_free(z);
8285 }
8286 isOk = 2;
8287 break;
8288 }
drh541ef2c2020-04-20 16:21:30 +00008289 case SQLITE_FCNTL_RESERVE_BYTES: {
8290 int x;
8291 if( nArg>=3 ){
8292 x = atoi(azArg[2]);
8293 sqlite3_file_control(p->db, zSchema, filectrl, &x);
8294 }
8295 x = -1;
8296 sqlite3_file_control(p->db, zSchema, filectrl, &x);
8297 utf8_printf(p->out,"%d\n", x);
8298 isOk = 2;
8299 break;
8300 }
drhd985f722019-06-05 14:29:53 +00008301 }
8302 }
8303 if( isOk==0 && iCtrl>=0 ){
8304 utf8_printf(p->out, "Usage: .filectrl %s %s\n", zCmd,aCtrl[iCtrl].zUsage);
8305 rc = 1;
8306 }else if( isOk==1 ){
drhe2500762019-06-13 14:07:41 +00008307 char zBuf[100];
8308 sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld", iRes);
8309 raw_printf(p->out, "%s\n", zBuf);
drhd985f722019-06-05 14:29:53 +00008310 }
8311 }else
8312
drhbf70f1b2022-10-19 18:04:42 +00008313 if( c=='f' && cli_strncmp(azArg[0], "fullschema", n)==0 ){
drh2ce15c32017-07-11 13:34:40 +00008314 ShellState data;
drh2ce15c32017-07-11 13:34:40 +00008315 int doStats = 0;
8316 memcpy(&data, p, sizeof(data));
8317 data.showHeader = 0;
8318 data.cMode = data.mode = MODE_Semi;
8319 if( nArg==2 && optionMatch(azArg[1], "indent") ){
8320 data.cMode = data.mode = MODE_Pretty;
8321 nArg = 1;
8322 }
8323 if( nArg!=1 ){
8324 raw_printf(stderr, "Usage: .fullschema ?--indent?\n");
8325 rc = 1;
8326 goto meta_command_exit;
8327 }
8328 open_db(p, 0);
8329 rc = sqlite3_exec(p->db,
8330 "SELECT sql FROM"
8331 " (SELECT sql sql, type type, tbl_name tbl_name, name name, rowid x"
drh067b92b2020-06-19 15:24:12 +00008332 " FROM sqlite_schema UNION ALL"
8333 " SELECT sql, type, tbl_name, name, rowid FROM sqlite_temp_schema) "
drh2ce15c32017-07-11 13:34:40 +00008334 "WHERE type!='meta' AND sql NOTNULL AND name NOT LIKE 'sqlite_%' "
drh69935c02021-06-25 11:14:10 +00008335 "ORDER BY x",
drhf83d5012021-05-03 13:35:00 +00008336 callback, &data, 0
drh2ce15c32017-07-11 13:34:40 +00008337 );
8338 if( rc==SQLITE_OK ){
8339 sqlite3_stmt *pStmt;
8340 rc = sqlite3_prepare_v2(p->db,
drh067b92b2020-06-19 15:24:12 +00008341 "SELECT rowid FROM sqlite_schema"
drh2ce15c32017-07-11 13:34:40 +00008342 " WHERE name GLOB 'sqlite_stat[134]'",
8343 -1, &pStmt, 0);
8344 doStats = sqlite3_step(pStmt)==SQLITE_ROW;
8345 sqlite3_finalize(pStmt);
8346 }
8347 if( doStats==0 ){
8348 raw_printf(p->out, "/* No STAT tables available */\n");
8349 }else{
drh067b92b2020-06-19 15:24:12 +00008350 raw_printf(p->out, "ANALYZE sqlite_schema;\n");
drh2ce15c32017-07-11 13:34:40 +00008351 data.cMode = data.mode = MODE_Insert;
8352 data.zDestTable = "sqlite_stat1";
drhf83d5012021-05-03 13:35:00 +00008353 shell_exec(&data, "SELECT * FROM sqlite_stat1", 0);
drh2ce15c32017-07-11 13:34:40 +00008354 data.zDestTable = "sqlite_stat4";
drhf83d5012021-05-03 13:35:00 +00008355 shell_exec(&data, "SELECT * FROM sqlite_stat4", 0);
drh067b92b2020-06-19 15:24:12 +00008356 raw_printf(p->out, "ANALYZE sqlite_schema;\n");
drh2ce15c32017-07-11 13:34:40 +00008357 }
8358 }else
8359
drhbf70f1b2022-10-19 18:04:42 +00008360 if( c=='h' && cli_strncmp(azArg[0], "headers", n)==0 ){
drh2ce15c32017-07-11 13:34:40 +00008361 if( nArg==2 ){
8362 p->showHeader = booleanValue(azArg[1]);
drhc0605082020-06-05 00:54:27 +00008363 p->shellFlgs |= SHFLG_HeaderSet;
drh2ce15c32017-07-11 13:34:40 +00008364 }else{
8365 raw_printf(stderr, "Usage: .headers on|off\n");
8366 rc = 1;
8367 }
8368 }else
8369
drhbf70f1b2022-10-19 18:04:42 +00008370 if( c=='h' && cli_strncmp(azArg[0], "help", n)==0 ){
drh98aa2ab2018-09-26 16:53:51 +00008371 if( nArg>=2 ){
drhe93f8262018-10-11 16:53:37 +00008372 n = showHelp(p->out, azArg[1]);
drh98aa2ab2018-09-26 16:53:51 +00008373 if( n==0 ){
8374 utf8_printf(p->out, "Nothing matches '%s'\n", azArg[1]);
8375 }
8376 }else{
8377 showHelp(p->out, 0);
8378 }
drh2ce15c32017-07-11 13:34:40 +00008379 }else
8380
stephan4413ec72022-07-12 15:53:02 +00008381#ifndef SQLITE_SHELL_FIDDLE
drhbf70f1b2022-10-19 18:04:42 +00008382 if( c=='i' && cli_strncmp(azArg[0], "import", n)==0 ){
drhccb37812020-03-09 15:39:39 +00008383 char *zTable = 0; /* Insert data into this table */
larrybr53e11862022-03-06 23:41:21 +00008384 char *zSchema = 0; /* within this schema (may default to "main") */
drhccb37812020-03-09 15:39:39 +00008385 char *zFile = 0; /* Name of file to extra content from */
drh2ce15c32017-07-11 13:34:40 +00008386 sqlite3_stmt *pStmt = NULL; /* A statement */
8387 int nCol; /* Number of columns in the table */
8388 int nByte; /* Number of bytes in an SQL string */
8389 int i, j; /* Loop counters */
8390 int needCommit; /* True to COMMIT or ROLLBACK at end */
8391 int nSep; /* Number of bytes in p->colSeparator[] */
8392 char *zSql; /* An SQL statement */
larrybr41f46702022-03-07 00:14:52 +00008393 char *zFullTabName; /* Table name with schema if applicable */
drh2ce15c32017-07-11 13:34:40 +00008394 ImportCtx sCtx; /* Reader context */
8395 char *(SQLITE_CDECL *xRead)(ImportCtx*); /* Func to read one value */
drhccb37812020-03-09 15:39:39 +00008396 int eVerbose = 0; /* Larger for more console output */
8397 int nSkip = 0; /* Initial lines to skip */
8398 int useOutputMode = 1; /* Use output mode to determine separators */
drhe684ac62022-03-08 13:59:46 +00008399 char *zCreate = 0; /* CREATE TABLE statement text */
drh2ce15c32017-07-11 13:34:40 +00008400
drhb97e2ad2021-08-26 18:31:39 +00008401 failIfSafeMode(p, "cannot run .import in safe mode");
drhccb37812020-03-09 15:39:39 +00008402 memset(&sCtx, 0, sizeof(sCtx));
8403 if( p->mode==MODE_Ascii ){
8404 xRead = ascii_read_one_field;
8405 }else{
8406 xRead = csv_read_one_field;
8407 }
larrybr2f5f6742022-05-09 12:29:47 +00008408 rc = 1;
drhccb37812020-03-09 15:39:39 +00008409 for(i=1; i<nArg; i++){
8410 char *z = azArg[i];
8411 if( z[0]=='-' && z[1]=='-' ) z++;
8412 if( z[0]!='-' ){
8413 if( zFile==0 ){
8414 zFile = z;
8415 }else if( zTable==0 ){
8416 zTable = z;
8417 }else{
8418 utf8_printf(p->out, "ERROR: extra argument: \"%s\". Usage:\n", z);
8419 showHelp(p->out, "import");
drhccb37812020-03-09 15:39:39 +00008420 goto meta_command_exit;
8421 }
drhbf70f1b2022-10-19 18:04:42 +00008422 }else if( cli_strcmp(z,"-v")==0 ){
drhccb37812020-03-09 15:39:39 +00008423 eVerbose++;
drhbf70f1b2022-10-19 18:04:42 +00008424 }else if( cli_strcmp(z,"-schema")==0 && i<nArg-1 ){
larrybr738d7b92022-01-13 21:22:54 +00008425 zSchema = azArg[++i];
drhbf70f1b2022-10-19 18:04:42 +00008426 }else if( cli_strcmp(z,"-skip")==0 && i<nArg-1 ){
drhccb37812020-03-09 15:39:39 +00008427 nSkip = integerValue(azArg[++i]);
drhbf70f1b2022-10-19 18:04:42 +00008428 }else if( cli_strcmp(z,"-ascii")==0 ){
drhccb37812020-03-09 15:39:39 +00008429 sCtx.cColSep = SEP_Unit[0];
8430 sCtx.cRowSep = SEP_Record[0];
8431 xRead = ascii_read_one_field;
8432 useOutputMode = 0;
drhbf70f1b2022-10-19 18:04:42 +00008433 }else if( cli_strcmp(z,"-csv")==0 ){
drhccb37812020-03-09 15:39:39 +00008434 sCtx.cColSep = ',';
8435 sCtx.cRowSep = '\n';
8436 xRead = csv_read_one_field;
8437 useOutputMode = 0;
8438 }else{
8439 utf8_printf(p->out, "ERROR: unknown option: \"%s\". Usage:\n", z);
8440 showHelp(p->out, "import");
drhccb37812020-03-09 15:39:39 +00008441 goto meta_command_exit;
8442 }
8443 }
8444 if( zTable==0 ){
8445 utf8_printf(p->out, "ERROR: missing %s argument. Usage:\n",
8446 zFile==0 ? "FILE" : "TABLE");
8447 showHelp(p->out, "import");
drh2ce15c32017-07-11 13:34:40 +00008448 goto meta_command_exit;
8449 }
drh2ce15c32017-07-11 13:34:40 +00008450 seenInterrupt = 0;
drh2ce15c32017-07-11 13:34:40 +00008451 open_db(p, 0);
drhccb37812020-03-09 15:39:39 +00008452 if( useOutputMode ){
8453 /* If neither the --csv or --ascii options are specified, then set
8454 ** the column and row separator characters from the output mode. */
8455 nSep = strlen30(p->colSeparator);
8456 if( nSep==0 ){
8457 raw_printf(stderr,
8458 "Error: non-null column separator required for import\n");
drhccb37812020-03-09 15:39:39 +00008459 goto meta_command_exit;
8460 }
8461 if( nSep>1 ){
larrybr2f5f6742022-05-09 12:29:47 +00008462 raw_printf(stderr,
drhccb37812020-03-09 15:39:39 +00008463 "Error: multi-character column separators not allowed"
8464 " for import\n");
drhccb37812020-03-09 15:39:39 +00008465 goto meta_command_exit;
8466 }
drh2ce15c32017-07-11 13:34:40 +00008467 nSep = strlen30(p->rowSeparator);
drhccb37812020-03-09 15:39:39 +00008468 if( nSep==0 ){
8469 raw_printf(stderr,
8470 "Error: non-null row separator required for import\n");
drhccb37812020-03-09 15:39:39 +00008471 goto meta_command_exit;
8472 }
drhbf70f1b2022-10-19 18:04:42 +00008473 if( nSep==2 && p->mode==MODE_Csv
8474 && cli_strcmp(p->rowSeparator,SEP_CrLf)==0
8475 ){
drhccb37812020-03-09 15:39:39 +00008476 /* When importing CSV (only), if the row separator is set to the
8477 ** default output row separator, change it to the default input
8478 ** row separator. This avoids having to maintain different input
8479 ** and output row separators. */
8480 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
8481 nSep = strlen30(p->rowSeparator);
8482 }
8483 if( nSep>1 ){
8484 raw_printf(stderr, "Error: multi-character row separators not allowed"
8485 " for import\n");
drhccb37812020-03-09 15:39:39 +00008486 goto meta_command_exit;
8487 }
8488 sCtx.cColSep = p->colSeparator[0];
8489 sCtx.cRowSep = p->rowSeparator[0];
drh2ce15c32017-07-11 13:34:40 +00008490 }
8491 sCtx.zFile = zFile;
8492 sCtx.nLine = 1;
8493 if( sCtx.zFile[0]=='|' ){
8494#ifdef SQLITE_OMIT_POPEN
8495 raw_printf(stderr, "Error: pipes are not supported in this OS\n");
drhccb37812020-03-09 15:39:39 +00008496 goto meta_command_exit;
drh2ce15c32017-07-11 13:34:40 +00008497#else
8498 sCtx.in = popen(sCtx.zFile+1, "r");
8499 sCtx.zFile = "<pipe>";
drh97767842020-05-29 19:39:35 +00008500 sCtx.xCloser = pclose;
drh2ce15c32017-07-11 13:34:40 +00008501#endif
8502 }else{
8503 sCtx.in = fopen(sCtx.zFile, "rb");
drh97767842020-05-29 19:39:35 +00008504 sCtx.xCloser = fclose;
drh2ce15c32017-07-11 13:34:40 +00008505 }
drh2ce15c32017-07-11 13:34:40 +00008506 if( sCtx.in==0 ){
8507 utf8_printf(stderr, "Error: cannot open \"%s\"\n", zFile);
drhccb37812020-03-09 15:39:39 +00008508 goto meta_command_exit;
drh2ce15c32017-07-11 13:34:40 +00008509 }
drhccb37812020-03-09 15:39:39 +00008510 if( eVerbose>=2 || (eVerbose>=1 && useOutputMode) ){
8511 char zSep[2];
8512 zSep[1] = 0;
8513 zSep[0] = sCtx.cColSep;
8514 utf8_printf(p->out, "Column separator ");
8515 output_c_string(p->out, zSep);
8516 utf8_printf(p->out, ", row separator ");
8517 zSep[0] = sCtx.cRowSep;
8518 output_c_string(p->out, zSep);
8519 utf8_printf(p->out, "\n");
8520 }
larrybr2f5f6742022-05-09 12:29:47 +00008521 sCtx.z = sqlite3_malloc64(120);
8522 if( sCtx.z==0 ){
8523 import_cleanup(&sCtx);
8524 shell_out_of_memory();
8525 }
larrybr53e11862022-03-06 23:41:21 +00008526 /* Below, resources must be freed before exit. */
drhccb37812020-03-09 15:39:39 +00008527 while( (nSkip--)>0 ){
8528 while( xRead(&sCtx) && sCtx.cTerm==sCtx.cColSep ){}
drhccb37812020-03-09 15:39:39 +00008529 }
larrybr53e11862022-03-06 23:41:21 +00008530 if( zSchema!=0 ){
larrybr41f46702022-03-07 00:14:52 +00008531 zFullTabName = sqlite3_mprintf("\"%w\".\"%w\"", zSchema, zTable);
larrybr53e11862022-03-06 23:41:21 +00008532 }else{
larrybr41f46702022-03-07 00:14:52 +00008533 zFullTabName = sqlite3_mprintf("\"%w\"", zTable);
larrybr53e11862022-03-06 23:41:21 +00008534 }
larrybr41f46702022-03-07 00:14:52 +00008535 zSql = sqlite3_mprintf("SELECT * FROM %s", zFullTabName);
8536 if( zSql==0 || zFullTabName==0 ){
drh97767842020-05-29 19:39:35 +00008537 import_cleanup(&sCtx);
drh4b5345c2018-04-24 13:07:40 +00008538 shell_out_of_memory();
drh2ce15c32017-07-11 13:34:40 +00008539 }
8540 nByte = strlen30(zSql);
8541 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
8542 import_append_char(&sCtx, 0); /* To ensure sCtx.z is allocated */
8543 if( rc && sqlite3_strglob("no such table: *", sqlite3_errmsg(p->db))==0 ){
larrybr58a53d62022-02-10 03:21:48 +00008544 sqlite3 *dbCols = 0;
larrybr33633862022-02-14 01:12:46 +00008545 char *zRenames = 0;
larrybr58a53d62022-02-10 03:21:48 +00008546 char *zColDefs;
drhe684ac62022-03-08 13:59:46 +00008547 zCreate = sqlite3_mprintf("CREATE TABLE %s", zFullTabName);
drh2ce15c32017-07-11 13:34:40 +00008548 while( xRead(&sCtx) ){
larrybra0337272022-02-11 13:40:25 +00008549 zAutoColumn(sCtx.z, &dbCols, 0);
drh2ce15c32017-07-11 13:34:40 +00008550 if( sCtx.cTerm!=sCtx.cColSep ) break;
larrybr4c5c6212022-02-11 01:21:09 +00008551 }
larrybr33633862022-02-14 01:12:46 +00008552 zColDefs = zAutoColumn(0, &dbCols, &zRenames);
8553 if( zRenames!=0 ){
larrybra0337272022-02-11 13:40:25 +00008554 utf8_printf((stdin_is_interactive && p->in==stdin)? p->out : stderr,
larrybr33633862022-02-14 01:12:46 +00008555 "Columns renamed during .import %s due to duplicates:\n"
8556 "%s\n", sCtx.zFile, zRenames);
8557 sqlite3_free(zRenames);
larrybra0337272022-02-11 13:40:25 +00008558 }
larrybr58a53d62022-02-10 03:21:48 +00008559 assert(dbCols==0);
8560 if( zColDefs==0 ){
drh2ce15c32017-07-11 13:34:40 +00008561 utf8_printf(stderr,"%s: empty file\n", sCtx.zFile);
larrybr53e11862022-03-06 23:41:21 +00008562 import_fail:
8563 sqlite3_free(zCreate);
8564 sqlite3_free(zSql);
larrybr41f46702022-03-07 00:14:52 +00008565 sqlite3_free(zFullTabName);
larrybr53e11862022-03-06 23:41:21 +00008566 import_cleanup(&sCtx);
drhccb37812020-03-09 15:39:39 +00008567 rc = 1;
8568 goto meta_command_exit;
drh2ce15c32017-07-11 13:34:40 +00008569 }
larrybr58a53d62022-02-10 03:21:48 +00008570 zCreate = sqlite3_mprintf("%z%z\n", zCreate, zColDefs);
drhccb37812020-03-09 15:39:39 +00008571 if( eVerbose>=1 ){
8572 utf8_printf(p->out, "%s\n", zCreate);
8573 }
drh2ce15c32017-07-11 13:34:40 +00008574 rc = sqlite3_exec(p->db, zCreate, 0, 0, 0);
drh2ce15c32017-07-11 13:34:40 +00008575 if( rc ){
larrybrce0b5e42022-01-14 16:29:45 +00008576 utf8_printf(stderr, "%s failed:\n%s\n", zCreate, sqlite3_errmsg(p->db));
larrybr53e11862022-03-06 23:41:21 +00008577 goto import_fail;
drh2ce15c32017-07-11 13:34:40 +00008578 }
larrybrce0b5e42022-01-14 16:29:45 +00008579 sqlite3_free(zCreate);
larrybr53e11862022-03-06 23:41:21 +00008580 zCreate = 0;
drh2ce15c32017-07-11 13:34:40 +00008581 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
8582 }
drh2ce15c32017-07-11 13:34:40 +00008583 if( rc ){
8584 if (pStmt) sqlite3_finalize(pStmt);
8585 utf8_printf(stderr,"Error: %s\n", sqlite3_errmsg(p->db));
larrybr53e11862022-03-06 23:41:21 +00008586 goto import_fail;
drh2ce15c32017-07-11 13:34:40 +00008587 }
larrybr53e11862022-03-06 23:41:21 +00008588 sqlite3_free(zSql);
drh2ce15c32017-07-11 13:34:40 +00008589 nCol = sqlite3_column_count(pStmt);
8590 sqlite3_finalize(pStmt);
8591 pStmt = 0;
8592 if( nCol==0 ) return 0; /* no columns, no error */
8593 zSql = sqlite3_malloc64( nByte*2 + 20 + nCol*2 );
8594 if( zSql==0 ){
drh97767842020-05-29 19:39:35 +00008595 import_cleanup(&sCtx);
drh4b5345c2018-04-24 13:07:40 +00008596 shell_out_of_memory();
drh2ce15c32017-07-11 13:34:40 +00008597 }
larrybr41f46702022-03-07 00:14:52 +00008598 sqlite3_snprintf(nByte+20, zSql, "INSERT INTO %s VALUES(?", zFullTabName);
drh2ce15c32017-07-11 13:34:40 +00008599 j = strlen30(zSql);
8600 for(i=1; i<nCol; i++){
8601 zSql[j++] = ',';
8602 zSql[j++] = '?';
8603 }
8604 zSql[j++] = ')';
8605 zSql[j] = 0;
drhccb37812020-03-09 15:39:39 +00008606 if( eVerbose>=2 ){
8607 utf8_printf(p->out, "Insert using: %s\n", zSql);
8608 }
drh2ce15c32017-07-11 13:34:40 +00008609 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
drh2ce15c32017-07-11 13:34:40 +00008610 if( rc ){
8611 utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
8612 if (pStmt) sqlite3_finalize(pStmt);
larrybr53e11862022-03-06 23:41:21 +00008613 goto import_fail;
drh2ce15c32017-07-11 13:34:40 +00008614 }
larrybr53e11862022-03-06 23:41:21 +00008615 sqlite3_free(zSql);
larrybr41f46702022-03-07 00:14:52 +00008616 sqlite3_free(zFullTabName);
drh2ce15c32017-07-11 13:34:40 +00008617 needCommit = sqlite3_get_autocommit(p->db);
8618 if( needCommit ) sqlite3_exec(p->db, "BEGIN", 0, 0, 0);
8619 do{
8620 int startLine = sCtx.nLine;
8621 for(i=0; i<nCol; i++){
8622 char *z = xRead(&sCtx);
8623 /*
8624 ** Did we reach end-of-file before finding any columns?
8625 ** If so, stop instead of NULL filling the remaining columns.
8626 */
8627 if( z==0 && i==0 ) break;
8628 /*
8629 ** Did we reach end-of-file OR end-of-line before finding any
8630 ** columns in ASCII mode? If so, stop instead of NULL filling
8631 ** the remaining columns.
8632 */
8633 if( p->mode==MODE_Ascii && (z==0 || z[0]==0) && i==0 ) break;
8634 sqlite3_bind_text(pStmt, i+1, z, -1, SQLITE_TRANSIENT);
8635 if( i<nCol-1 && sCtx.cTerm!=sCtx.cColSep ){
8636 utf8_printf(stderr, "%s:%d: expected %d columns but found %d - "
8637 "filling the rest with NULL\n",
8638 sCtx.zFile, startLine, nCol, i+1);
8639 i += 2;
8640 while( i<=nCol ){ sqlite3_bind_null(pStmt, i); i++; }
8641 }
8642 }
8643 if( sCtx.cTerm==sCtx.cColSep ){
8644 do{
8645 xRead(&sCtx);
8646 i++;
8647 }while( sCtx.cTerm==sCtx.cColSep );
8648 utf8_printf(stderr, "%s:%d: expected %d columns but found %d - "
8649 "extras ignored\n",
8650 sCtx.zFile, startLine, nCol, i);
8651 }
8652 if( i>=nCol ){
8653 sqlite3_step(pStmt);
8654 rc = sqlite3_reset(pStmt);
8655 if( rc!=SQLITE_OK ){
8656 utf8_printf(stderr, "%s:%d: INSERT failed: %s\n", sCtx.zFile,
8657 startLine, sqlite3_errmsg(p->db));
drhccb37812020-03-09 15:39:39 +00008658 sCtx.nErr++;
8659 }else{
8660 sCtx.nRow++;
drh2ce15c32017-07-11 13:34:40 +00008661 }
8662 }
8663 }while( sCtx.cTerm!=EOF );
8664
drh97767842020-05-29 19:39:35 +00008665 import_cleanup(&sCtx);
drh2ce15c32017-07-11 13:34:40 +00008666 sqlite3_finalize(pStmt);
8667 if( needCommit ) sqlite3_exec(p->db, "COMMIT", 0, 0, 0);
drhccb37812020-03-09 15:39:39 +00008668 if( eVerbose>0 ){
8669 utf8_printf(p->out,
8670 "Added %d rows with %d errors using %d lines of input\n",
8671 sCtx.nRow, sCtx.nErr, sCtx.nLine-1);
8672 }
drh2ce15c32017-07-11 13:34:40 +00008673 }else
stephan4413ec72022-07-12 15:53:02 +00008674#endif /* !defined(SQLITE_SHELL_FIDDLE) */
drh2ce15c32017-07-11 13:34:40 +00008675
8676#ifndef SQLITE_UNTESTABLE
drhbf70f1b2022-10-19 18:04:42 +00008677 if( c=='i' && cli_strncmp(azArg[0], "imposter", n)==0 ){
drh2ce15c32017-07-11 13:34:40 +00008678 char *zSql;
8679 char *zCollist = 0;
8680 sqlite3_stmt *pStmt;
8681 int tnum = 0;
drh491c5be2019-10-18 15:58:50 +00008682 int isWO = 0; /* True if making an imposter of a WITHOUT ROWID table */
8683 int lenPK = 0; /* Length of the PRIMARY KEY string for isWO tables */
drh2ce15c32017-07-11 13:34:40 +00008684 int i;
drh48d219a2018-04-23 18:38:48 +00008685 if( !(nArg==3 || (nArg==2 && sqlite3_stricmp(azArg[1],"off")==0)) ){
8686 utf8_printf(stderr, "Usage: .imposter INDEX IMPOSTER\n"
8687 " .imposter off\n");
drh491c5be2019-10-18 15:58:50 +00008688 /* Also allowed, but not documented:
8689 **
8690 ** .imposter TABLE IMPOSTER
8691 **
8692 ** where TABLE is a WITHOUT ROWID table. In that case, the
8693 ** imposter is another WITHOUT ROWID table with the columns in
8694 ** storage order. */
drh2ce15c32017-07-11 13:34:40 +00008695 rc = 1;
8696 goto meta_command_exit;
8697 }
8698 open_db(p, 0);
drh48d219a2018-04-23 18:38:48 +00008699 if( nArg==2 ){
8700 sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 0, 1);
8701 goto meta_command_exit;
8702 }
drh491c5be2019-10-18 15:58:50 +00008703 zSql = sqlite3_mprintf(
drh067b92b2020-06-19 15:24:12 +00008704 "SELECT rootpage, 0 FROM sqlite_schema"
drh491c5be2019-10-18 15:58:50 +00008705 " WHERE name='%q' AND type='index'"
8706 "UNION ALL "
drh067b92b2020-06-19 15:24:12 +00008707 "SELECT rootpage, 1 FROM sqlite_schema"
drh491c5be2019-10-18 15:58:50 +00008708 " WHERE name='%q' AND type='table'"
8709 " AND sql LIKE '%%without%%rowid%%'",
8710 azArg[1], azArg[1]
8711 );
drh2ce15c32017-07-11 13:34:40 +00008712 sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
8713 sqlite3_free(zSql);
8714 if( sqlite3_step(pStmt)==SQLITE_ROW ){
8715 tnum = sqlite3_column_int(pStmt, 0);
drh491c5be2019-10-18 15:58:50 +00008716 isWO = sqlite3_column_int(pStmt, 1);
drh2ce15c32017-07-11 13:34:40 +00008717 }
8718 sqlite3_finalize(pStmt);
drh2ce15c32017-07-11 13:34:40 +00008719 zSql = sqlite3_mprintf("PRAGMA index_xinfo='%q'", azArg[1]);
8720 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
8721 sqlite3_free(zSql);
8722 i = 0;
drhe85e1da2021-10-01 21:01:07 +00008723 while( rc==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW ){
drh2ce15c32017-07-11 13:34:40 +00008724 char zLabel[20];
8725 const char *zCol = (const char*)sqlite3_column_text(pStmt,2);
8726 i++;
8727 if( zCol==0 ){
8728 if( sqlite3_column_int(pStmt,1)==-1 ){
8729 zCol = "_ROWID_";
8730 }else{
8731 sqlite3_snprintf(sizeof(zLabel),zLabel,"expr%d",i);
8732 zCol = zLabel;
8733 }
8734 }
drh491c5be2019-10-18 15:58:50 +00008735 if( isWO && lenPK==0 && sqlite3_column_int(pStmt,5)==0 && zCollist ){
8736 lenPK = (int)strlen(zCollist);
8737 }
drh2ce15c32017-07-11 13:34:40 +00008738 if( zCollist==0 ){
8739 zCollist = sqlite3_mprintf("\"%w\"", zCol);
8740 }else{
8741 zCollist = sqlite3_mprintf("%z,\"%w\"", zCollist, zCol);
8742 }
8743 }
8744 sqlite3_finalize(pStmt);
drh491c5be2019-10-18 15:58:50 +00008745 if( i==0 || tnum==0 ){
8746 utf8_printf(stderr, "no such index: \"%s\"\n", azArg[1]);
8747 rc = 1;
8748 sqlite3_free(zCollist);
8749 goto meta_command_exit;
8750 }
8751 if( lenPK==0 ) lenPK = 100000;
drh2ce15c32017-07-11 13:34:40 +00008752 zSql = sqlite3_mprintf(
drh491c5be2019-10-18 15:58:50 +00008753 "CREATE TABLE \"%w\"(%s,PRIMARY KEY(%.*s))WITHOUT ROWID",
8754 azArg[2], zCollist, lenPK, zCollist);
drh2ce15c32017-07-11 13:34:40 +00008755 sqlite3_free(zCollist);
8756 rc = sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 1, tnum);
8757 if( rc==SQLITE_OK ){
8758 rc = sqlite3_exec(p->db, zSql, 0, 0, 0);
8759 sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 0, 0);
8760 if( rc ){
8761 utf8_printf(stderr, "Error in [%s]: %s\n", zSql, sqlite3_errmsg(p->db));
8762 }else{
8763 utf8_printf(stdout, "%s;\n", zSql);
8764 raw_printf(stdout,
drh491c5be2019-10-18 15:58:50 +00008765 "WARNING: writing to an imposter table will corrupt the \"%s\" %s!\n",
8766 azArg[1], isWO ? "table" : "index"
drh2ce15c32017-07-11 13:34:40 +00008767 );
8768 }
8769 }else{
8770 raw_printf(stderr, "SQLITE_TESTCTRL_IMPOSTER returns %d\n", rc);
8771 rc = 1;
8772 }
8773 sqlite3_free(zSql);
8774 }else
8775#endif /* !defined(SQLITE_OMIT_TEST_CONTROL) */
8776
8777#ifdef SQLITE_ENABLE_IOTRACE
drhbf70f1b2022-10-19 18:04:42 +00008778 if( c=='i' && cli_strncmp(azArg[0], "iotrace", n)==0 ){
drh2ce15c32017-07-11 13:34:40 +00008779 SQLITE_API extern void (SQLITE_CDECL *sqlite3IoTrace)(const char*, ...);
8780 if( iotrace && iotrace!=stdout ) fclose(iotrace);
8781 iotrace = 0;
8782 if( nArg<2 ){
8783 sqlite3IoTrace = 0;
drhbf70f1b2022-10-19 18:04:42 +00008784 }else if( cli_strcmp(azArg[1], "-")==0 ){
drh2ce15c32017-07-11 13:34:40 +00008785 sqlite3IoTrace = iotracePrintf;
8786 iotrace = stdout;
8787 }else{
8788 iotrace = fopen(azArg[1], "w");
8789 if( iotrace==0 ){
8790 utf8_printf(stderr, "Error: cannot open \"%s\"\n", azArg[1]);
8791 sqlite3IoTrace = 0;
8792 rc = 1;
8793 }else{
8794 sqlite3IoTrace = iotracePrintf;
8795 }
8796 }
8797 }else
8798#endif
8799
drhbf70f1b2022-10-19 18:04:42 +00008800 if( c=='l' && n>=5 && cli_strncmp(azArg[0], "limits", n)==0 ){
drh2ce15c32017-07-11 13:34:40 +00008801 static const struct {
8802 const char *zLimitName; /* Name of a limit */
8803 int limitCode; /* Integer code for that limit */
8804 } aLimit[] = {
8805 { "length", SQLITE_LIMIT_LENGTH },
8806 { "sql_length", SQLITE_LIMIT_SQL_LENGTH },
8807 { "column", SQLITE_LIMIT_COLUMN },
8808 { "expr_depth", SQLITE_LIMIT_EXPR_DEPTH },
8809 { "compound_select", SQLITE_LIMIT_COMPOUND_SELECT },
8810 { "vdbe_op", SQLITE_LIMIT_VDBE_OP },
8811 { "function_arg", SQLITE_LIMIT_FUNCTION_ARG },
8812 { "attached", SQLITE_LIMIT_ATTACHED },
8813 { "like_pattern_length", SQLITE_LIMIT_LIKE_PATTERN_LENGTH },
8814 { "variable_number", SQLITE_LIMIT_VARIABLE_NUMBER },
8815 { "trigger_depth", SQLITE_LIMIT_TRIGGER_DEPTH },
8816 { "worker_threads", SQLITE_LIMIT_WORKER_THREADS },
8817 };
8818 int i, n2;
8819 open_db(p, 0);
8820 if( nArg==1 ){
8821 for(i=0; i<ArraySize(aLimit); i++){
8822 printf("%20s %d\n", aLimit[i].zLimitName,
8823 sqlite3_limit(p->db, aLimit[i].limitCode, -1));
8824 }
8825 }else if( nArg>3 ){
8826 raw_printf(stderr, "Usage: .limit NAME ?NEW-VALUE?\n");
8827 rc = 1;
8828 goto meta_command_exit;
8829 }else{
8830 int iLimit = -1;
8831 n2 = strlen30(azArg[1]);
8832 for(i=0; i<ArraySize(aLimit); i++){
8833 if( sqlite3_strnicmp(aLimit[i].zLimitName, azArg[1], n2)==0 ){
8834 if( iLimit<0 ){
8835 iLimit = i;
8836 }else{
8837 utf8_printf(stderr, "ambiguous limit: \"%s\"\n", azArg[1]);
8838 rc = 1;
8839 goto meta_command_exit;
8840 }
8841 }
8842 }
8843 if( iLimit<0 ){
8844 utf8_printf(stderr, "unknown limit: \"%s\"\n"
8845 "enter \".limits\" with no arguments for a list.\n",
8846 azArg[1]);
8847 rc = 1;
8848 goto meta_command_exit;
8849 }
8850 if( nArg==3 ){
8851 sqlite3_limit(p->db, aLimit[iLimit].limitCode,
8852 (int)integerValue(azArg[2]));
8853 }
8854 printf("%20s %d\n", aLimit[iLimit].zLimitName,
8855 sqlite3_limit(p->db, aLimit[iLimit].limitCode, -1));
8856 }
8857 }else
8858
drhbf70f1b2022-10-19 18:04:42 +00008859 if( c=='l' && n>2 && cli_strncmp(azArg[0], "lint", n)==0 ){
drh2ce15c32017-07-11 13:34:40 +00008860 open_db(p, 0);
8861 lintDotCommand(p, azArg, nArg);
8862 }else
8863
stephan4413ec72022-07-12 15:53:02 +00008864#if !defined(SQLITE_OMIT_LOAD_EXTENSION) && !defined(SQLITE_SHELL_FIDDLE)
drhbf70f1b2022-10-19 18:04:42 +00008865 if( c=='l' && cli_strncmp(azArg[0], "load", n)==0 ){
drh2ce15c32017-07-11 13:34:40 +00008866 const char *zFile, *zProc;
8867 char *zErrMsg = 0;
drhb97e2ad2021-08-26 18:31:39 +00008868 failIfSafeMode(p, "cannot run .load in safe mode");
drh2ce15c32017-07-11 13:34:40 +00008869 if( nArg<2 ){
8870 raw_printf(stderr, "Usage: .load FILE ?ENTRYPOINT?\n");
8871 rc = 1;
8872 goto meta_command_exit;
8873 }
8874 zFile = azArg[1];
8875 zProc = nArg>=3 ? azArg[2] : 0;
8876 open_db(p, 0);
8877 rc = sqlite3_load_extension(p->db, zFile, zProc, &zErrMsg);
8878 if( rc!=SQLITE_OK ){
8879 utf8_printf(stderr, "Error: %s\n", zErrMsg);
8880 sqlite3_free(zErrMsg);
8881 rc = 1;
8882 }
8883 }else
8884#endif
8885
stephan4413ec72022-07-12 15:53:02 +00008886#ifndef SQLITE_SHELL_FIDDLE
drhbf70f1b2022-10-19 18:04:42 +00008887 if( c=='l' && cli_strncmp(azArg[0], "log", n)==0 ){
drhb97e2ad2021-08-26 18:31:39 +00008888 failIfSafeMode(p, "cannot run .log in safe mode");
drh2ce15c32017-07-11 13:34:40 +00008889 if( nArg!=2 ){
8890 raw_printf(stderr, "Usage: .log FILENAME\n");
8891 rc = 1;
8892 }else{
8893 const char *zFile = azArg[1];
8894 output_file_close(p->pLog);
drha92a01a2018-01-10 22:15:37 +00008895 p->pLog = output_file_open(zFile, 0);
drh2ce15c32017-07-11 13:34:40 +00008896 }
8897 }else
stephan618a3752022-05-19 10:24:50 +00008898#endif
drh2ce15c32017-07-11 13:34:40 +00008899
drhbf70f1b2022-10-19 18:04:42 +00008900 if( c=='m' && cli_strncmp(azArg[0], "mode", n)==0 ){
drhe40f2862022-01-31 14:14:29 +00008901 const char *zMode = 0;
8902 const char *zTabname = 0;
8903 int i, n2;
larrybrcc4d55c2022-02-01 02:50:45 +00008904 ColModeOpts cmOpts = ColModeOpts_default;
drhe40f2862022-01-31 14:14:29 +00008905 for(i=1; i<nArg; i++){
8906 const char *z = azArg[i];
8907 if( optionMatch(z,"wrap") && i+1<nArg ){
larrybrcc4d55c2022-02-01 02:50:45 +00008908 cmOpts.iWrap = integerValue(azArg[++i]);
drhca1776b2022-02-01 12:28:17 +00008909 }else if( optionMatch(z,"ww") ){
8910 cmOpts.bWordWrap = 1;
larrybrcc4d55c2022-02-01 02:50:45 +00008911 }else if( optionMatch(z,"wordwrap") && i+1<nArg ){
8912 cmOpts.bWordWrap = (u8)booleanValue(azArg[++i]);
drhe40f2862022-01-31 14:14:29 +00008913 }else if( optionMatch(z,"quote") ){
larrybrcc4d55c2022-02-01 02:50:45 +00008914 cmOpts.bQuote = 1;
drhe40f2862022-01-31 14:14:29 +00008915 }else if( optionMatch(z,"noquote") ){
larrybrcc4d55c2022-02-01 02:50:45 +00008916 cmOpts.bQuote = 0;
drhe40f2862022-01-31 14:14:29 +00008917 }else if( zMode==0 ){
8918 zMode = z;
drh1f41a8c2022-10-24 11:10:40 +00008919 /* Apply defaults for qbox pseudo-mode. If that
larrybrcc4d55c2022-02-01 02:50:45 +00008920 * overwrites already-set values, user was informed of this.
8921 */
drhbf70f1b2022-10-19 18:04:42 +00008922 if( cli_strcmp(z, "qbox")==0 ){
larrybrcc4d55c2022-02-01 02:50:45 +00008923 ColModeOpts cmo = ColModeOpts_default_qbox;
8924 zMode = "box";
8925 cmOpts = cmo;
larrybrcc4d55c2022-02-01 02:50:45 +00008926 }
drhe40f2862022-01-31 14:14:29 +00008927 }else if( zTabname==0 ){
8928 zTabname = z;
8929 }else if( z[0]=='-' ){
8930 utf8_printf(stderr, "unknown option: %s\n", z);
8931 utf8_printf(stderr, "options:\n"
8932 " --noquote\n"
8933 " --quote\n"
larrybrcc4d55c2022-02-01 02:50:45 +00008934 " --wordwrap on/off\n"
drhca1776b2022-02-01 12:28:17 +00008935 " --wrap N\n"
8936 " --ww\n");
drhe40f2862022-01-31 14:14:29 +00008937 rc = 1;
8938 goto meta_command_exit;
8939 }else{
8940 utf8_printf(stderr, "extra argument: \"%s\"\n", z);
8941 rc = 1;
8942 goto meta_command_exit;
8943 }
8944 }
8945 if( zMode==0 ){
8946 if( p->mode==MODE_Column
8947 || (p->mode>=MODE_Markdown && p->mode<=MODE_Box)
8948 ){
larrybrcc4d55c2022-02-01 02:50:45 +00008949 raw_printf
8950 (p->out,
8951 "current output mode: %s --wrap %d --wordwrap %s --%squote\n",
8952 modeDescr[p->mode], p->cmOpts.iWrap,
8953 p->cmOpts.bWordWrap ? "on" : "off",
8954 p->cmOpts.bQuote ? "" : "no");
drhe40f2862022-01-31 14:14:29 +00008955 }else{
8956 raw_printf(p->out, "current output mode: %s\n", modeDescr[p->mode]);
8957 }
drhe40f2862022-01-31 14:14:29 +00008958 zMode = modeDescr[p->mode];
8959 }
8960 n2 = strlen30(zMode);
drhbf70f1b2022-10-19 18:04:42 +00008961 if( cli_strncmp(zMode,"lines",n2)==0 ){
drh2ce15c32017-07-11 13:34:40 +00008962 p->mode = MODE_Line;
8963 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
drhbf70f1b2022-10-19 18:04:42 +00008964 }else if( cli_strncmp(zMode,"columns",n2)==0 ){
drh2ce15c32017-07-11 13:34:40 +00008965 p->mode = MODE_Column;
drhc0605082020-06-05 00:54:27 +00008966 if( (p->shellFlgs & SHFLG_HeaderSet)==0 ){
8967 p->showHeader = 1;
8968 }
drh2ce15c32017-07-11 13:34:40 +00008969 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
larrybrcc4d55c2022-02-01 02:50:45 +00008970 p->cmOpts = cmOpts;
drhbf70f1b2022-10-19 18:04:42 +00008971 }else if( cli_strncmp(zMode,"list",n2)==0 ){
drh2ce15c32017-07-11 13:34:40 +00008972 p->mode = MODE_List;
8973 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Column);
8974 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
drhbf70f1b2022-10-19 18:04:42 +00008975 }else if( cli_strncmp(zMode,"html",n2)==0 ){
drh2ce15c32017-07-11 13:34:40 +00008976 p->mode = MODE_Html;
drhbf70f1b2022-10-19 18:04:42 +00008977 }else if( cli_strncmp(zMode,"tcl",n2)==0 ){
drh2ce15c32017-07-11 13:34:40 +00008978 p->mode = MODE_Tcl;
8979 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Space);
8980 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
drhbf70f1b2022-10-19 18:04:42 +00008981 }else if( cli_strncmp(zMode,"csv",n2)==0 ){
drh2ce15c32017-07-11 13:34:40 +00008982 p->mode = MODE_Csv;
8983 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Comma);
8984 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_CrLf);
drhbf70f1b2022-10-19 18:04:42 +00008985 }else if( cli_strncmp(zMode,"tabs",n2)==0 ){
drh2ce15c32017-07-11 13:34:40 +00008986 p->mode = MODE_List;
8987 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Tab);
drhbf70f1b2022-10-19 18:04:42 +00008988 }else if( cli_strncmp(zMode,"insert",n2)==0 ){
drh2ce15c32017-07-11 13:34:40 +00008989 p->mode = MODE_Insert;
drhe40f2862022-01-31 14:14:29 +00008990 set_table_name(p, zTabname ? zTabname : "table");
drhbf70f1b2022-10-19 18:04:42 +00008991 }else if( cli_strncmp(zMode,"quote",n2)==0 ){
drh2ce15c32017-07-11 13:34:40 +00008992 p->mode = MODE_Quote;
drhc6835732020-05-28 20:37:17 +00008993 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Comma);
8994 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
drhbf70f1b2022-10-19 18:04:42 +00008995 }else if( cli_strncmp(zMode,"ascii",n2)==0 ){
drh2ce15c32017-07-11 13:34:40 +00008996 p->mode = MODE_Ascii;
8997 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Unit);
8998 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Record);
drhbf70f1b2022-10-19 18:04:42 +00008999 }else if( cli_strncmp(zMode,"markdown",n2)==0 ){
drh30c54a02020-05-28 23:49:50 +00009000 p->mode = MODE_Markdown;
larrybrcc4d55c2022-02-01 02:50:45 +00009001 p->cmOpts = cmOpts;
drhbf70f1b2022-10-19 18:04:42 +00009002 }else if( cli_strncmp(zMode,"table",n2)==0 ){
drh30c54a02020-05-28 23:49:50 +00009003 p->mode = MODE_Table;
larrybrcc4d55c2022-02-01 02:50:45 +00009004 p->cmOpts = cmOpts;
drhbf70f1b2022-10-19 18:04:42 +00009005 }else if( cli_strncmp(zMode,"box",n2)==0 ){
drh0908e382020-06-04 18:05:39 +00009006 p->mode = MODE_Box;
larrybrcc4d55c2022-02-01 02:50:45 +00009007 p->cmOpts = cmOpts;
drhbf70f1b2022-10-19 18:04:42 +00009008 }else if( cli_strncmp(zMode,"count",n2)==0 ){
drh5d88be82021-12-09 16:17:43 +00009009 p->mode = MODE_Count;
drhbf70f1b2022-10-19 18:04:42 +00009010 }else if( cli_strncmp(zMode,"off",n2)==0 ){
drh5d88be82021-12-09 16:17:43 +00009011 p->mode = MODE_Off;
drhbf70f1b2022-10-19 18:04:42 +00009012 }else if( cli_strncmp(zMode,"json",n2)==0 ){
drh30c54a02020-05-28 23:49:50 +00009013 p->mode = MODE_Json;
drh2ce15c32017-07-11 13:34:40 +00009014 }else{
9015 raw_printf(stderr, "Error: mode should be one of: "
drh0908e382020-06-04 18:05:39 +00009016 "ascii box column csv html insert json line list markdown "
drhca1776b2022-02-01 12:28:17 +00009017 "qbox quote table tabs tcl\n");
drh2ce15c32017-07-11 13:34:40 +00009018 rc = 1;
9019 }
9020 p->cMode = p->mode;
9021 }else
9022
stephan4413ec72022-07-12 15:53:02 +00009023#ifndef SQLITE_SHELL_FIDDLE
drhbf70f1b2022-10-19 18:04:42 +00009024 if( c=='n' && cli_strcmp(azArg[0], "nonce")==0 ){
drhb97e2ad2021-08-26 18:31:39 +00009025 if( nArg!=2 ){
9026 raw_printf(stderr, "Usage: .nonce NONCE\n");
9027 rc = 1;
drhbf70f1b2022-10-19 18:04:42 +00009028 }else if( p->zNonce==0 || cli_strcmp(azArg[1],p->zNonce)!=0 ){
drhfe463172021-12-16 17:57:21 +00009029 raw_printf(stderr, "line %d: incorrect nonce: \"%s\"\n",
9030 p->lineno, azArg[1]);
drhb97e2ad2021-08-26 18:31:39 +00009031 exit(1);
drhe85e1da2021-10-01 21:01:07 +00009032 }else{
9033 p->bSafeMode = 0;
9034 return 0; /* Return immediately to bypass the safe mode reset
9035 ** at the end of this procedure */
drhb97e2ad2021-08-26 18:31:39 +00009036 }
drhb97e2ad2021-08-26 18:31:39 +00009037 }else
stephan4413ec72022-07-12 15:53:02 +00009038#endif /* !defined(SQLITE_SHELL_FIDDLE) */
drhb97e2ad2021-08-26 18:31:39 +00009039
drhbf70f1b2022-10-19 18:04:42 +00009040 if( c=='n' && cli_strncmp(azArg[0], "nullvalue", n)==0 ){
drh2ce15c32017-07-11 13:34:40 +00009041 if( nArg==2 ){
9042 sqlite3_snprintf(sizeof(p->nullValue), p->nullValue,
9043 "%.*s", (int)ArraySize(p->nullValue)-1, azArg[1]);
9044 }else{
9045 raw_printf(stderr, "Usage: .nullvalue STRING\n");
9046 rc = 1;
9047 }
9048 }else
9049
drhbf70f1b2022-10-19 18:04:42 +00009050 if( c=='o' && cli_strncmp(azArg[0], "open", n)==0 && n>=2 ){
drh61fd4b92021-12-16 14:59:25 +00009051 const char *zFN = 0; /* Pointer to constant filename */
drhf30bbce2020-12-02 18:27:48 +00009052 char *zNewFilename = 0; /* Name of the database file to open */
9053 int iName = 1; /* Index in azArg[] of the filename */
9054 int newFlag = 0; /* True to delete file before opening */
dan1872c5b2021-12-02 14:16:30 +00009055 int openMode = SHELL_OPEN_UNSPEC;
9056
drh2ce15c32017-07-11 13:34:40 +00009057 /* Check for command-line arguments */
drhf30bbce2020-12-02 18:27:48 +00009058 for(iName=1; iName<nArg; iName++){
drh2ce15c32017-07-11 13:34:40 +00009059 const char *z = azArg[iName];
stephan4413ec72022-07-12 15:53:02 +00009060#ifndef SQLITE_SHELL_FIDDLE
drh2ce15c32017-07-11 13:34:40 +00009061 if( optionMatch(z,"new") ){
9062 newFlag = 1;
drh3baed312018-03-08 18:14:41 +00009063#ifdef SQLITE_HAVE_ZLIB
drh1fa6d9f2018-01-06 21:46:01 +00009064 }else if( optionMatch(z, "zip") ){
dan1872c5b2021-12-02 14:16:30 +00009065 openMode = SHELL_OPEN_ZIPFILE;
drh1fa6d9f2018-01-06 21:46:01 +00009066#endif
9067 }else if( optionMatch(z, "append") ){
dan1872c5b2021-12-02 14:16:30 +00009068 openMode = SHELL_OPEN_APPENDVFS;
drhee269a62018-02-14 23:27:43 +00009069 }else if( optionMatch(z, "readonly") ){
dan1872c5b2021-12-02 14:16:30 +00009070 openMode = SHELL_OPEN_READONLY;
drh0933aad2019-11-18 17:46:38 +00009071 }else if( optionMatch(z, "nofollow") ){
9072 p->openFlags |= SQLITE_OPEN_NOFOLLOW;
drh8d889af2021-05-08 17:18:23 +00009073#ifndef SQLITE_OMIT_DESERIALIZE
drh60f34ae2018-10-30 13:19:49 +00009074 }else if( optionMatch(z, "deserialize") ){
dan1872c5b2021-12-02 14:16:30 +00009075 openMode = SHELL_OPEN_DESERIALIZE;
drh33746482018-12-13 15:06:26 +00009076 }else if( optionMatch(z, "hexdb") ){
dan1872c5b2021-12-02 14:16:30 +00009077 openMode = SHELL_OPEN_HEXDB;
drh6ca64482019-01-22 16:06:20 +00009078 }else if( optionMatch(z, "maxsize") && iName+1<nArg ){
9079 p->szMax = integerValue(azArg[++iName]);
drh8d889af2021-05-08 17:18:23 +00009080#endif /* SQLITE_OMIT_DESERIALIZE */
stephande1e02e2022-05-24 19:01:21 +00009081 }else
stephan4413ec72022-07-12 15:53:02 +00009082#endif /* !SQLITE_SHELL_FIDDLE */
stephande1e02e2022-05-24 19:01:21 +00009083 if( z[0]=='-' ){
drh2ce15c32017-07-11 13:34:40 +00009084 utf8_printf(stderr, "unknown option: %s\n", z);
9085 rc = 1;
9086 goto meta_command_exit;
drh61fd4b92021-12-16 14:59:25 +00009087 }else if( zFN ){
drhf30bbce2020-12-02 18:27:48 +00009088 utf8_printf(stderr, "extra argument: \"%s\"\n", z);
9089 rc = 1;
9090 goto meta_command_exit;
9091 }else{
drh61fd4b92021-12-16 14:59:25 +00009092 zFN = z;
drh2ce15c32017-07-11 13:34:40 +00009093 }
9094 }
dan1872c5b2021-12-02 14:16:30 +00009095
9096 /* Close the existing database */
9097 session_close_all(p, -1);
9098 close_db(p->db);
9099 p->db = 0;
9100 p->pAuxDb->zDbFilename = 0;
9101 sqlite3_free(p->pAuxDb->zFreeOnClose);
9102 p->pAuxDb->zFreeOnClose = 0;
9103 p->openMode = openMode;
9104 p->openFlags = 0;
9105 p->szMax = 0;
9106
drh2ce15c32017-07-11 13:34:40 +00009107 /* If a filename is specified, try to open it first */
drh61fd4b92021-12-16 14:59:25 +00009108 if( zFN || p->openMode==SHELL_OPEN_HEXDB ){
drhc320e062021-12-24 19:44:11 +00009109 if( newFlag && zFN && !p->bSafeMode ) shellDeleteFile(zFN);
stephan4413ec72022-07-12 15:53:02 +00009110#ifndef SQLITE_SHELL_FIDDLE
drhb97e2ad2021-08-26 18:31:39 +00009111 if( p->bSafeMode
9112 && p->openMode!=SHELL_OPEN_HEXDB
drhc320e062021-12-24 19:44:11 +00009113 && zFN
drhbf70f1b2022-10-19 18:04:42 +00009114 && cli_strcmp(zFN,":memory:")!=0
drhb97e2ad2021-08-26 18:31:39 +00009115 ){
9116 failIfSafeMode(p, "cannot open disk-based database files in safe mode");
9117 }
stephande1e02e2022-05-24 19:01:21 +00009118#else
9119 /* WASM mode has its own sandboxed pseudo-filesystem. */
9120#endif
drh61fd4b92021-12-16 14:59:25 +00009121 if( zFN ){
9122 zNewFilename = sqlite3_mprintf("%s", zFN);
9123 shell_check_oom(zNewFilename);
9124 }else{
9125 zNewFilename = 0;
9126 }
drh37407122021-07-23 18:43:58 +00009127 p->pAuxDb->zDbFilename = zNewFilename;
drhbe4ccb22018-05-17 20:04:24 +00009128 open_db(p, OPEN_DB_KEEPALIVE);
drh2ce15c32017-07-11 13:34:40 +00009129 if( p->db==0 ){
9130 utf8_printf(stderr, "Error: cannot open '%s'\n", zNewFilename);
9131 sqlite3_free(zNewFilename);
9132 }else{
drh37407122021-07-23 18:43:58 +00009133 p->pAuxDb->zFreeOnClose = zNewFilename;
drh2ce15c32017-07-11 13:34:40 +00009134 }
9135 }
9136 if( p->db==0 ){
9137 /* As a fall-back open a TEMP database */
drh37407122021-07-23 18:43:58 +00009138 p->pAuxDb->zDbFilename = 0;
drh2ce15c32017-07-11 13:34:40 +00009139 open_db(p, 0);
9140 }
9141 }else
9142
stephan4413ec72022-07-12 15:53:02 +00009143#ifndef SQLITE_SHELL_FIDDLE
drh13c20932018-01-10 21:41:55 +00009144 if( (c=='o'
drhbf70f1b2022-10-19 18:04:42 +00009145 && (cli_strncmp(azArg[0], "output", n)==0
9146 || cli_strncmp(azArg[0], "once", n)==0))
9147 || (c=='e' && n==5 && cli_strcmp(azArg[0],"excel")==0)
drh2ce15c32017-07-11 13:34:40 +00009148 ){
drh4b0229a2021-02-17 13:19:22 +00009149 char *zFile = 0;
drha92a01a2018-01-10 22:15:37 +00009150 int bTxtMode = 0;
drh7a431002020-04-18 14:12:00 +00009151 int i;
9152 int eMode = 0;
drh8ad3c432022-03-23 10:04:52 +00009153 int bOnce = 0; /* 0: .output, 1: .once, 2: .excel */
9154 unsigned char zBOM[4]; /* Byte-order mark to using if --bom is present */
drh7a431002020-04-18 14:12:00 +00009155
drh8ad3c432022-03-23 10:04:52 +00009156 zBOM[0] = 0;
drhb97e2ad2021-08-26 18:31:39 +00009157 failIfSafeMode(p, "cannot run .%s in safe mode", azArg[0]);
drh7a431002020-04-18 14:12:00 +00009158 if( c=='e' ){
9159 eMode = 'x';
9160 bOnce = 2;
drhbf70f1b2022-10-19 18:04:42 +00009161 }else if( cli_strncmp(azArg[0],"once",n)==0 ){
drh7a431002020-04-18 14:12:00 +00009162 bOnce = 1;
drh13c20932018-01-10 21:41:55 +00009163 }
drh7a431002020-04-18 14:12:00 +00009164 for(i=1; i<nArg; i++){
9165 char *z = azArg[i];
9166 if( z[0]=='-' ){
9167 if( z[1]=='-' ) z++;
drhbf70f1b2022-10-19 18:04:42 +00009168 if( cli_strcmp(z,"-bom")==0 ){
drh8ad3c432022-03-23 10:04:52 +00009169 zBOM[0] = 0xef;
9170 zBOM[1] = 0xbb;
9171 zBOM[2] = 0xbf;
9172 zBOM[3] = 0;
drhbf70f1b2022-10-19 18:04:42 +00009173 }else if( c!='e' && cli_strcmp(z,"-x")==0 ){
drh7a431002020-04-18 14:12:00 +00009174 eMode = 'x'; /* spreadsheet */
drhbf70f1b2022-10-19 18:04:42 +00009175 }else if( c!='e' && cli_strcmp(z,"-e")==0 ){
drh7a431002020-04-18 14:12:00 +00009176 eMode = 'e'; /* text editor */
9177 }else{
9178 utf8_printf(p->out, "ERROR: unknown option: \"%s\". Usage:\n",
9179 azArg[i]);
9180 showHelp(p->out, azArg[0]);
9181 rc = 1;
9182 goto meta_command_exit;
9183 }
drh4b0229a2021-02-17 13:19:22 +00009184 }else if( zFile==0 && eMode!='e' && eMode!='x' ){
9185 zFile = sqlite3_mprintf("%s", z);
drhe3e25652021-12-16 13:29:28 +00009186 if( zFile && zFile[0]=='|' ){
drh4b0229a2021-02-17 13:19:22 +00009187 while( i+1<nArg ) zFile = sqlite3_mprintf("%z %s", zFile, azArg[++i]);
9188 break;
9189 }
drh7a431002020-04-18 14:12:00 +00009190 }else{
9191 utf8_printf(p->out,"ERROR: extra parameter: \"%s\". Usage:\n",
9192 azArg[i]);
9193 showHelp(p->out, azArg[0]);
drh2ce15c32017-07-11 13:34:40 +00009194 rc = 1;
drh4b0229a2021-02-17 13:19:22 +00009195 sqlite3_free(zFile);
drh2ce15c32017-07-11 13:34:40 +00009196 goto meta_command_exit;
9197 }
drh7a431002020-04-18 14:12:00 +00009198 }
drhe3e25652021-12-16 13:29:28 +00009199 if( zFile==0 ){
9200 zFile = sqlite3_mprintf("stdout");
9201 }
drh7a431002020-04-18 14:12:00 +00009202 if( bOnce ){
drh2ce15c32017-07-11 13:34:40 +00009203 p->outCount = 2;
9204 }else{
9205 p->outCount = 0;
9206 }
9207 output_reset(p);
drh04a28c32018-01-31 01:38:44 +00009208#ifndef SQLITE_NOHAVE_SYSTEM
drh7a431002020-04-18 14:12:00 +00009209 if( eMode=='e' || eMode=='x' ){
drh3c484e82018-01-10 22:27:21 +00009210 p->doXdgOpen = 1;
9211 outputModePush(p);
drh7a431002020-04-18 14:12:00 +00009212 if( eMode=='x' ){
9213 /* spreadsheet mode. Output as CSV. */
drh13c20932018-01-10 21:41:55 +00009214 newTempFile(p, "csv");
drh7a431002020-04-18 14:12:00 +00009215 ShellClearFlag(p, SHFLG_Echo);
drh13c20932018-01-10 21:41:55 +00009216 p->mode = MODE_Csv;
9217 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Comma);
9218 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_CrLf);
9219 }else{
drh7a431002020-04-18 14:12:00 +00009220 /* text editor mode */
drh13c20932018-01-10 21:41:55 +00009221 newTempFile(p, "txt");
drha92a01a2018-01-10 22:15:37 +00009222 bTxtMode = 1;
drh13c20932018-01-10 21:41:55 +00009223 }
drh4b0229a2021-02-17 13:19:22 +00009224 sqlite3_free(zFile);
9225 zFile = sqlite3_mprintf("%s", p->zTempFile);
drh13c20932018-01-10 21:41:55 +00009226 }
drh04a28c32018-01-31 01:38:44 +00009227#endif /* SQLITE_NOHAVE_SYSTEM */
drhe3e25652021-12-16 13:29:28 +00009228 shell_check_oom(zFile);
drh2ce15c32017-07-11 13:34:40 +00009229 if( zFile[0]=='|' ){
9230#ifdef SQLITE_OMIT_POPEN
9231 raw_printf(stderr, "Error: pipes are not supported in this OS\n");
9232 rc = 1;
9233 p->out = stdout;
9234#else
9235 p->out = popen(zFile + 1, "w");
9236 if( p->out==0 ){
9237 utf8_printf(stderr,"Error: cannot open pipe \"%s\"\n", zFile + 1);
9238 p->out = stdout;
9239 rc = 1;
9240 }else{
drh8ad3c432022-03-23 10:04:52 +00009241 if( zBOM[0] ) fwrite(zBOM, 1, 3, p->out);
drh2ce15c32017-07-11 13:34:40 +00009242 sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", zFile);
9243 }
9244#endif
9245 }else{
drha92a01a2018-01-10 22:15:37 +00009246 p->out = output_file_open(zFile, bTxtMode);
drh2ce15c32017-07-11 13:34:40 +00009247 if( p->out==0 ){
drhbf70f1b2022-10-19 18:04:42 +00009248 if( cli_strcmp(zFile,"off")!=0 ){
drh2ce15c32017-07-11 13:34:40 +00009249 utf8_printf(stderr,"Error: cannot write to \"%s\"\n", zFile);
9250 }
9251 p->out = stdout;
9252 rc = 1;
9253 } else {
drh8ad3c432022-03-23 10:04:52 +00009254 if( zBOM[0] ) fwrite(zBOM, 1, 3, p->out);
drh2ce15c32017-07-11 13:34:40 +00009255 sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", zFile);
9256 }
9257 }
drh4b0229a2021-02-17 13:19:22 +00009258 sqlite3_free(zFile);
drh2ce15c32017-07-11 13:34:40 +00009259 }else
stephan4413ec72022-07-12 15:53:02 +00009260#endif /* !defined(SQLITE_SHELL_FIDDLE) */
drh2ce15c32017-07-11 13:34:40 +00009261
drhbf70f1b2022-10-19 18:04:42 +00009262 if( c=='p' && n>=3 && cli_strncmp(azArg[0], "parameter", n)==0 ){
drh9cb02642019-02-28 20:10:52 +00009263 open_db(p,0);
9264 if( nArg<=1 ) goto parameter_syntax_error;
9265
9266 /* .parameter clear
9267 ** Clear all bind parameters by dropping the TEMP table that holds them.
9268 */
drhbf70f1b2022-10-19 18:04:42 +00009269 if( nArg==2 && cli_strcmp(azArg[1],"clear")==0 ){
drh65c29fd2019-03-25 21:56:26 +00009270 sqlite3_exec(p->db, "DROP TABLE IF EXISTS temp.sqlite_parameters;",
drh9cb02642019-02-28 20:10:52 +00009271 0, 0, 0);
9272 }else
9273
9274 /* .parameter list
9275 ** List all bind parameters.
9276 */
drhbf70f1b2022-10-19 18:04:42 +00009277 if( nArg==2 && cli_strcmp(azArg[1],"list")==0 ){
drh9cb02642019-02-28 20:10:52 +00009278 sqlite3_stmt *pStmt = 0;
9279 int rx;
9280 int len = 0;
9281 rx = sqlite3_prepare_v2(p->db,
9282 "SELECT max(length(key)) "
drh65c29fd2019-03-25 21:56:26 +00009283 "FROM temp.sqlite_parameters;", -1, &pStmt, 0);
drh9cb02642019-02-28 20:10:52 +00009284 if( rx==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW ){
9285 len = sqlite3_column_int(pStmt, 0);
9286 if( len>40 ) len = 40;
9287 }
9288 sqlite3_finalize(pStmt);
9289 pStmt = 0;
9290 if( len ){
9291 rx = sqlite3_prepare_v2(p->db,
9292 "SELECT key, quote(value) "
drh65c29fd2019-03-25 21:56:26 +00009293 "FROM temp.sqlite_parameters;", -1, &pStmt, 0);
drhe85e1da2021-10-01 21:01:07 +00009294 while( rx==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW ){
drh9cb02642019-02-28 20:10:52 +00009295 utf8_printf(p->out, "%-*s %s\n", len, sqlite3_column_text(pStmt,0),
9296 sqlite3_column_text(pStmt,1));
9297 }
9298 sqlite3_finalize(pStmt);
9299 }
9300 }else
9301
9302 /* .parameter init
9303 ** Make sure the TEMP table used to hold bind parameters exists.
9304 ** Create it if necessary.
9305 */
drhbf70f1b2022-10-19 18:04:42 +00009306 if( nArg==2 && cli_strcmp(azArg[1],"init")==0 ){
drh9cb02642019-02-28 20:10:52 +00009307 bind_table_init(p);
9308 }else
9309
9310 /* .parameter set NAME VALUE
9311 ** Set or reset a bind parameter. NAME should be the full parameter
9312 ** name exactly as it appears in the query. (ex: $abc, @def). The
9313 ** VALUE can be in either SQL literal notation, or if not it will be
9314 ** understood to be a text string.
9315 */
drhbf70f1b2022-10-19 18:04:42 +00009316 if( nArg==4 && cli_strcmp(azArg[1],"set")==0 ){
drh9cb02642019-02-28 20:10:52 +00009317 int rx;
9318 char *zSql;
9319 sqlite3_stmt *pStmt;
9320 const char *zKey = azArg[2];
9321 const char *zValue = azArg[3];
9322 bind_table_init(p);
9323 zSql = sqlite3_mprintf(
drh65c29fd2019-03-25 21:56:26 +00009324 "REPLACE INTO temp.sqlite_parameters(key,value)"
drh9cb02642019-02-28 20:10:52 +00009325 "VALUES(%Q,%s);", zKey, zValue);
drhe3e25652021-12-16 13:29:28 +00009326 shell_check_oom(zSql);
drh9cb02642019-02-28 20:10:52 +00009327 pStmt = 0;
9328 rx = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
9329 sqlite3_free(zSql);
9330 if( rx!=SQLITE_OK ){
9331 sqlite3_finalize(pStmt);
9332 pStmt = 0;
9333 zSql = sqlite3_mprintf(
drh65c29fd2019-03-25 21:56:26 +00009334 "REPLACE INTO temp.sqlite_parameters(key,value)"
drh9cb02642019-02-28 20:10:52 +00009335 "VALUES(%Q,%Q);", zKey, zValue);
drhe3e25652021-12-16 13:29:28 +00009336 shell_check_oom(zSql);
drh9cb02642019-02-28 20:10:52 +00009337 rx = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
9338 sqlite3_free(zSql);
9339 if( rx!=SQLITE_OK ){
9340 utf8_printf(p->out, "Error: %s\n", sqlite3_errmsg(p->db));
9341 sqlite3_finalize(pStmt);
9342 pStmt = 0;
9343 rc = 1;
9344 }
9345 }
9346 sqlite3_step(pStmt);
9347 sqlite3_finalize(pStmt);
9348 }else
9349
9350 /* .parameter unset NAME
9351 ** Remove the NAME binding from the parameter binding table, if it
9352 ** exists.
9353 */
drhbf70f1b2022-10-19 18:04:42 +00009354 if( nArg==3 && cli_strcmp(azArg[1],"unset")==0 ){
drh9cb02642019-02-28 20:10:52 +00009355 char *zSql = sqlite3_mprintf(
drh65c29fd2019-03-25 21:56:26 +00009356 "DELETE FROM temp.sqlite_parameters WHERE key=%Q", azArg[2]);
drhe3e25652021-12-16 13:29:28 +00009357 shell_check_oom(zSql);
drh9cb02642019-02-28 20:10:52 +00009358 sqlite3_exec(p->db, zSql, 0, 0, 0);
9359 sqlite3_free(zSql);
9360 }else
9361 /* If no command name matches, show a syntax error */
9362 parameter_syntax_error:
9363 showHelp(p->out, "parameter");
9364 }else
9365
drhbf70f1b2022-10-19 18:04:42 +00009366 if( c=='p' && n>=3 && cli_strncmp(azArg[0], "print", n)==0 ){
drh2ce15c32017-07-11 13:34:40 +00009367 int i;
9368 for(i=1; i<nArg; i++){
9369 if( i>1 ) raw_printf(p->out, " ");
9370 utf8_printf(p->out, "%s", azArg[i]);
9371 }
9372 raw_printf(p->out, "\n");
9373 }else
9374
drh569b1d92019-02-05 20:51:41 +00009375#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
drhbf70f1b2022-10-19 18:04:42 +00009376 if( c=='p' && n>=3 && cli_strncmp(azArg[0], "progress", n)==0 ){
drh3f83f592019-02-04 14:53:18 +00009377 int i;
drhfc4eeef2019-02-05 19:48:46 +00009378 int nn = 0;
drh3f83f592019-02-04 14:53:18 +00009379 p->flgProgress = 0;
9380 p->mxProgress = 0;
9381 p->nProgress = 0;
9382 for(i=1; i<nArg; i++){
9383 const char *z = azArg[i];
9384 if( z[0]=='-' ){
9385 z++;
9386 if( z[0]=='-' ) z++;
drhbf70f1b2022-10-19 18:04:42 +00009387 if( cli_strcmp(z,"quiet")==0 || cli_strcmp(z,"q")==0 ){
drhfc4eeef2019-02-05 19:48:46 +00009388 p->flgProgress |= SHELL_PROGRESS_QUIET;
drh3f83f592019-02-04 14:53:18 +00009389 continue;
9390 }
drhbf70f1b2022-10-19 18:04:42 +00009391 if( cli_strcmp(z,"reset")==0 ){
drhfc4eeef2019-02-05 19:48:46 +00009392 p->flgProgress |= SHELL_PROGRESS_RESET;
drh3f83f592019-02-04 14:53:18 +00009393 continue;
9394 }
drhbf70f1b2022-10-19 18:04:42 +00009395 if( cli_strcmp(z,"once")==0 ){
drhfc4eeef2019-02-05 19:48:46 +00009396 p->flgProgress |= SHELL_PROGRESS_ONCE;
drh3f83f592019-02-04 14:53:18 +00009397 continue;
9398 }
drhbf70f1b2022-10-19 18:04:42 +00009399 if( cli_strcmp(z,"limit")==0 ){
drh3f83f592019-02-04 14:53:18 +00009400 if( i+1>=nArg ){
9401 utf8_printf(stderr, "Error: missing argument on --limit\n");
9402 rc = 1;
9403 goto meta_command_exit;
9404 }else{
9405 p->mxProgress = (int)integerValue(azArg[++i]);
9406 }
9407 continue;
9408 }
9409 utf8_printf(stderr, "Error: unknown option: \"%s\"\n", azArg[i]);
9410 rc = 1;
9411 goto meta_command_exit;
9412 }else{
drhfc4eeef2019-02-05 19:48:46 +00009413 nn = (int)integerValue(z);
drh3f83f592019-02-04 14:53:18 +00009414 }
9415 }
9416 open_db(p, 0);
drhfc4eeef2019-02-05 19:48:46 +00009417 sqlite3_progress_handler(p->db, nn, progress_handler, p);
drh3f83f592019-02-04 14:53:18 +00009418 }else
drh569b1d92019-02-05 20:51:41 +00009419#endif /* SQLITE_OMIT_PROGRESS_CALLBACK */
drh3f83f592019-02-04 14:53:18 +00009420
drhbf70f1b2022-10-19 18:04:42 +00009421 if( c=='p' && cli_strncmp(azArg[0], "prompt", n)==0 ){
drh2ce15c32017-07-11 13:34:40 +00009422 if( nArg >= 2) {
9423 strncpy(mainPrompt,azArg[1],(int)ArraySize(mainPrompt)-1);
9424 }
9425 if( nArg >= 3) {
9426 strncpy(continuePrompt,azArg[2],(int)ArraySize(continuePrompt)-1);
9427 }
9428 }else
9429
stephan4413ec72022-07-12 15:53:02 +00009430#ifndef SQLITE_SHELL_FIDDLE
drhbf70f1b2022-10-19 18:04:42 +00009431 if( c=='q' && cli_strncmp(azArg[0], "quit", n)==0 ){
drh2ce15c32017-07-11 13:34:40 +00009432 rc = 2;
9433 }else
stephan02520cc2022-05-18 22:58:34 +00009434#endif
drh2ce15c32017-07-11 13:34:40 +00009435
stephan4413ec72022-07-12 15:53:02 +00009436#ifndef SQLITE_SHELL_FIDDLE
drhbf70f1b2022-10-19 18:04:42 +00009437 if( c=='r' && n>=3 && cli_strncmp(azArg[0], "read", n)==0 ){
drh60379d42018-12-13 18:30:01 +00009438 FILE *inSaved = p->in;
drh2c8ee022018-12-13 18:59:30 +00009439 int savedLineno = p->lineno;
drhb97e2ad2021-08-26 18:31:39 +00009440 failIfSafeMode(p, "cannot run .read in safe mode");
drh2ce15c32017-07-11 13:34:40 +00009441 if( nArg!=2 ){
9442 raw_printf(stderr, "Usage: .read FILE\n");
9443 rc = 1;
9444 goto meta_command_exit;
9445 }
drh30497f42020-08-26 10:50:48 +00009446 if( azArg[1][0]=='|' ){
drh9d59e3b2021-03-12 01:49:08 +00009447#ifdef SQLITE_OMIT_POPEN
9448 raw_printf(stderr, "Error: pipes are not supported in this OS\n");
9449 rc = 1;
9450 p->out = stdout;
9451#else
drh30497f42020-08-26 10:50:48 +00009452 p->in = popen(azArg[1]+1, "r");
9453 if( p->in==0 ){
9454 utf8_printf(stderr, "Error: cannot open \"%s\"\n", azArg[1]);
9455 rc = 1;
9456 }else{
9457 rc = process_input(p);
9458 pclose(p->in);
9459 }
drh9d59e3b2021-03-12 01:49:08 +00009460#endif
larrybrd96bcc72021-09-17 21:12:47 +00009461 }else if( (p->in = openChrSource(azArg[1]))==0 ){
drh2ce15c32017-07-11 13:34:40 +00009462 utf8_printf(stderr,"Error: cannot open \"%s\"\n", azArg[1]);
9463 rc = 1;
9464 }else{
drh60379d42018-12-13 18:30:01 +00009465 rc = process_input(p);
9466 fclose(p->in);
drh2ce15c32017-07-11 13:34:40 +00009467 }
drh60379d42018-12-13 18:30:01 +00009468 p->in = inSaved;
drh2c8ee022018-12-13 18:59:30 +00009469 p->lineno = savedLineno;
drh2ce15c32017-07-11 13:34:40 +00009470 }else
stephan4413ec72022-07-12 15:53:02 +00009471#endif /* !defined(SQLITE_SHELL_FIDDLE) */
drh2ce15c32017-07-11 13:34:40 +00009472
stephan4413ec72022-07-12 15:53:02 +00009473#ifndef SQLITE_SHELL_FIDDLE
drhbf70f1b2022-10-19 18:04:42 +00009474 if( c=='r' && n>=3 && cli_strncmp(azArg[0], "restore", n)==0 ){
drh2ce15c32017-07-11 13:34:40 +00009475 const char *zSrcFile;
9476 const char *zDb;
9477 sqlite3 *pSrc;
9478 sqlite3_backup *pBackup;
9479 int nTimeout = 0;
9480
drhb97e2ad2021-08-26 18:31:39 +00009481 failIfSafeMode(p, "cannot run .restore in safe mode");
drh2ce15c32017-07-11 13:34:40 +00009482 if( nArg==2 ){
9483 zSrcFile = azArg[1];
9484 zDb = "main";
9485 }else if( nArg==3 ){
9486 zSrcFile = azArg[2];
9487 zDb = azArg[1];
9488 }else{
9489 raw_printf(stderr, "Usage: .restore ?DB? FILE\n");
9490 rc = 1;
9491 goto meta_command_exit;
9492 }
9493 rc = sqlite3_open(zSrcFile, &pSrc);
9494 if( rc!=SQLITE_OK ){
9495 utf8_printf(stderr, "Error: cannot open \"%s\"\n", zSrcFile);
drh9e804032018-05-18 17:11:50 +00009496 close_db(pSrc);
drh2ce15c32017-07-11 13:34:40 +00009497 return 1;
9498 }
9499 open_db(p, 0);
9500 pBackup = sqlite3_backup_init(p->db, zDb, pSrc, "main");
9501 if( pBackup==0 ){
9502 utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
drh9e804032018-05-18 17:11:50 +00009503 close_db(pSrc);
drh2ce15c32017-07-11 13:34:40 +00009504 return 1;
9505 }
9506 while( (rc = sqlite3_backup_step(pBackup,100))==SQLITE_OK
9507 || rc==SQLITE_BUSY ){
9508 if( rc==SQLITE_BUSY ){
9509 if( nTimeout++ >= 3 ) break;
9510 sqlite3_sleep(100);
9511 }
9512 }
9513 sqlite3_backup_finish(pBackup);
9514 if( rc==SQLITE_DONE ){
9515 rc = 0;
9516 }else if( rc==SQLITE_BUSY || rc==SQLITE_LOCKED ){
9517 raw_printf(stderr, "Error: source database is busy\n");
9518 rc = 1;
9519 }else{
9520 utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
9521 rc = 1;
9522 }
drh9e804032018-05-18 17:11:50 +00009523 close_db(pSrc);
drh2ce15c32017-07-11 13:34:40 +00009524 }else
stephan4413ec72022-07-12 15:53:02 +00009525#endif /* !defined(SQLITE_SHELL_FIDDLE) */
drh2ce15c32017-07-11 13:34:40 +00009526
drhbf70f1b2022-10-19 18:04:42 +00009527 if( c=='s' && cli_strncmp(azArg[0], "scanstats", n)==0 ){
drh2ce15c32017-07-11 13:34:40 +00009528 if( nArg==2 ){
mistachkinb71aa092018-01-23 00:05:18 +00009529 p->scanstatsOn = (u8)booleanValue(azArg[1]);
drh2ce15c32017-07-11 13:34:40 +00009530#ifndef SQLITE_ENABLE_STMT_SCANSTATUS
9531 raw_printf(stderr, "Warning: .scanstats not available in this build.\n");
9532#endif
9533 }else{
9534 raw_printf(stderr, "Usage: .scanstats on|off\n");
9535 rc = 1;
9536 }
9537 }else
9538
drhbf70f1b2022-10-19 18:04:42 +00009539 if( c=='s' && cli_strncmp(azArg[0], "schema", n)==0 ){
drh2ce15c32017-07-11 13:34:40 +00009540 ShellText sSelect;
9541 ShellState data;
9542 char *zErrMsg = 0;
drh667a2a22018-01-02 00:04:37 +00009543 const char *zDiv = "(";
drhceba7922018-01-01 21:28:25 +00009544 const char *zName = 0;
drh2ce15c32017-07-11 13:34:40 +00009545 int iSchema = 0;
drhceba7922018-01-01 21:28:25 +00009546 int bDebug = 0;
drhbbb29ec2020-10-12 14:56:47 +00009547 int bNoSystemTabs = 0;
drhceba7922018-01-01 21:28:25 +00009548 int ii;
drh2ce15c32017-07-11 13:34:40 +00009549
9550 open_db(p, 0);
9551 memcpy(&data, p, sizeof(data));
9552 data.showHeader = 0;
9553 data.cMode = data.mode = MODE_Semi;
9554 initText(&sSelect);
drhceba7922018-01-01 21:28:25 +00009555 for(ii=1; ii<nArg; ii++){
9556 if( optionMatch(azArg[ii],"indent") ){
9557 data.cMode = data.mode = MODE_Pretty;
9558 }else if( optionMatch(azArg[ii],"debug") ){
9559 bDebug = 1;
drhbbb29ec2020-10-12 14:56:47 +00009560 }else if( optionMatch(azArg[ii],"nosys") ){
9561 bNoSystemTabs = 1;
9562 }else if( azArg[ii][0]=='-' ){
9563 utf8_printf(stderr, "Unknown option: \"%s\"\n", azArg[ii]);
9564 rc = 1;
9565 goto meta_command_exit;
drhceba7922018-01-01 21:28:25 +00009566 }else if( zName==0 ){
9567 zName = azArg[ii];
drh2ce15c32017-07-11 13:34:40 +00009568 }else{
drhbbb29ec2020-10-12 14:56:47 +00009569 raw_printf(stderr, "Usage: .schema ?--indent? ?--nosys? ?LIKE-PATTERN?\n");
drhceba7922018-01-01 21:28:25 +00009570 rc = 1;
9571 goto meta_command_exit;
drh2ce15c32017-07-11 13:34:40 +00009572 }
drh2ce15c32017-07-11 13:34:40 +00009573 }
drhceba7922018-01-01 21:28:25 +00009574 if( zName!=0 ){
drh067b92b2020-06-19 15:24:12 +00009575 int isSchema = sqlite3_strlike(zName, "sqlite_master", '\\')==0
drh346a70c2020-06-15 20:27:35 +00009576 || sqlite3_strlike(zName, "sqlite_schema", '\\')==0
9577 || sqlite3_strlike(zName,"sqlite_temp_master", '\\')==0
9578 || sqlite3_strlike(zName,"sqlite_temp_schema", '\\')==0;
drh067b92b2020-06-19 15:24:12 +00009579 if( isSchema ){
drh2ce15c32017-07-11 13:34:40 +00009580 char *new_argv[2], *new_colv[2];
drhc22b7162018-01-01 20:11:23 +00009581 new_argv[0] = sqlite3_mprintf(
9582 "CREATE TABLE %s (\n"
drh2ce15c32017-07-11 13:34:40 +00009583 " type text,\n"
9584 " name text,\n"
9585 " tbl_name text,\n"
9586 " rootpage integer,\n"
9587 " sql text\n"
drh346a70c2020-06-15 20:27:35 +00009588 ")", zName);
drhe3e25652021-12-16 13:29:28 +00009589 shell_check_oom(new_argv[0]);
drh2ce15c32017-07-11 13:34:40 +00009590 new_argv[1] = 0;
9591 new_colv[0] = "sql";
9592 new_colv[1] = 0;
9593 callback(&data, 1, new_argv, new_colv);
drhc22b7162018-01-01 20:11:23 +00009594 sqlite3_free(new_argv[0]);
drh2ce15c32017-07-11 13:34:40 +00009595 }
drh2ce15c32017-07-11 13:34:40 +00009596 }
9597 if( zDiv ){
9598 sqlite3_stmt *pStmt = 0;
9599 rc = sqlite3_prepare_v2(p->db, "SELECT name FROM pragma_database_list",
9600 -1, &pStmt, 0);
9601 if( rc ){
9602 utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
9603 sqlite3_finalize(pStmt);
9604 rc = 1;
9605 goto meta_command_exit;
9606 }
9607 appendText(&sSelect, "SELECT sql FROM", 0);
9608 iSchema = 0;
9609 while( sqlite3_step(pStmt)==SQLITE_ROW ){
9610 const char *zDb = (const char*)sqlite3_column_text(pStmt, 0);
9611 char zScNum[30];
9612 sqlite3_snprintf(sizeof(zScNum), zScNum, "%d", ++iSchema);
9613 appendText(&sSelect, zDiv, 0);
9614 zDiv = " UNION ALL ";
drhceba7922018-01-01 21:28:25 +00009615 appendText(&sSelect, "SELECT shell_add_schema(sql,", 0);
9616 if( sqlite3_stricmp(zDb, "main")!=0 ){
drhea38f4f2019-07-13 17:21:47 +00009617 appendText(&sSelect, zDb, '\'');
drh2ce15c32017-07-11 13:34:40 +00009618 }else{
drhceba7922018-01-01 21:28:25 +00009619 appendText(&sSelect, "NULL", 0);
drh2ce15c32017-07-11 13:34:40 +00009620 }
drhceba7922018-01-01 21:28:25 +00009621 appendText(&sSelect, ",name) AS sql, type, tbl_name, name, rowid,", 0);
9622 appendText(&sSelect, zScNum, 0);
9623 appendText(&sSelect, " AS snum, ", 0);
9624 appendText(&sSelect, zDb, '\'');
9625 appendText(&sSelect, " AS sname FROM ", 0);
drhea38f4f2019-07-13 17:21:47 +00009626 appendText(&sSelect, zDb, quoteChar(zDb));
drh067b92b2020-06-19 15:24:12 +00009627 appendText(&sSelect, ".sqlite_schema", 0);
drh2ce15c32017-07-11 13:34:40 +00009628 }
9629 sqlite3_finalize(pStmt);
drhcc3f3d12019-08-17 15:27:58 +00009630#ifndef SQLITE_OMIT_INTROSPECTION_PRAGMAS
drh667a2a22018-01-02 00:04:37 +00009631 if( zName ){
9632 appendText(&sSelect,
9633 " UNION ALL SELECT shell_module_schema(name),"
drhe2754c12019-08-26 12:50:01 +00009634 " 'table', name, name, name, 9e+99, 'main' FROM pragma_module_list",
9635 0);
drh667a2a22018-01-02 00:04:37 +00009636 }
drhcde7b772018-01-02 12:50:40 +00009637#endif
drh2ce15c32017-07-11 13:34:40 +00009638 appendText(&sSelect, ") WHERE ", 0);
drhceba7922018-01-01 21:28:25 +00009639 if( zName ){
9640 char *zQarg = sqlite3_mprintf("%Q", zName);
mistachkinc158c072021-12-31 19:08:20 +00009641 int bGlob;
drhe3e25652021-12-16 13:29:28 +00009642 shell_check_oom(zQarg);
mistachkinc158c072021-12-31 19:08:20 +00009643 bGlob = strchr(zName, '*') != 0 || strchr(zName, '?') != 0 ||
9644 strchr(zName, '[') != 0;
drhceba7922018-01-01 21:28:25 +00009645 if( strchr(zName, '.') ){
drh2ce15c32017-07-11 13:34:40 +00009646 appendText(&sSelect, "lower(printf('%s.%s',sname,tbl_name))", 0);
9647 }else{
9648 appendText(&sSelect, "lower(tbl_name)", 0);
9649 }
mistachkin9d107262018-03-23 14:24:34 +00009650 appendText(&sSelect, bGlob ? " GLOB " : " LIKE ", 0);
drh2ce15c32017-07-11 13:34:40 +00009651 appendText(&sSelect, zQarg, 0);
mistachkin9d107262018-03-23 14:24:34 +00009652 if( !bGlob ){
9653 appendText(&sSelect, " ESCAPE '\\' ", 0);
9654 }
drh2ce15c32017-07-11 13:34:40 +00009655 appendText(&sSelect, " AND ", 0);
9656 sqlite3_free(zQarg);
9657 }
drhbbb29ec2020-10-12 14:56:47 +00009658 if( bNoSystemTabs ){
9659 appendText(&sSelect, "name NOT LIKE 'sqlite_%%' AND ", 0);
9660 }
9661 appendText(&sSelect, "sql IS NOT NULL"
drh2ce15c32017-07-11 13:34:40 +00009662 " ORDER BY snum, rowid", 0);
drhceba7922018-01-01 21:28:25 +00009663 if( bDebug ){
9664 utf8_printf(p->out, "SQL: %s;\n", sSelect.z);
9665 }else{
9666 rc = sqlite3_exec(p->db, sSelect.z, callback, &data, &zErrMsg);
9667 }
drh2ce15c32017-07-11 13:34:40 +00009668 freeText(&sSelect);
9669 }
9670 if( zErrMsg ){
9671 utf8_printf(stderr,"Error: %s\n", zErrMsg);
9672 sqlite3_free(zErrMsg);
9673 rc = 1;
9674 }else if( rc != SQLITE_OK ){
9675 raw_printf(stderr,"Error: querying schema information\n");
9676 rc = 1;
9677 }else{
9678 rc = 0;
9679 }
9680 }else
9681
drhbf70f1b2022-10-19 18:04:42 +00009682 if( (c=='s' && n==11 && cli_strncmp(azArg[0], "selecttrace", n)==0)
9683 || (c=='t' && n==9 && cli_strncmp(azArg[0], "treetrace", n)==0)
drh5e431be2022-04-06 11:08:38 +00009684 ){
drhfda8e492020-12-04 16:04:45 +00009685 unsigned int x = nArg>=2 ? (unsigned int)integerValue(azArg[1]) : 0xffffffff;
drhc0622a42020-12-04 01:17:57 +00009686 sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 1, &x);
drh2ce15c32017-07-11 13:34:40 +00009687 }else
drh2ce15c32017-07-11 13:34:40 +00009688
9689#if defined(SQLITE_ENABLE_SESSION)
drhbf70f1b2022-10-19 18:04:42 +00009690 if( c=='s' && cli_strncmp(azArg[0],"session",n)==0 && n>=3 ){
drh37407122021-07-23 18:43:58 +00009691 struct AuxDb *pAuxDb = p->pAuxDb;
9692 OpenSession *pSession = &pAuxDb->aSession[0];
drh2ce15c32017-07-11 13:34:40 +00009693 char **azCmd = &azArg[1];
9694 int iSes = 0;
9695 int nCmd = nArg - 1;
9696 int i;
9697 if( nArg<=1 ) goto session_syntax_error;
9698 open_db(p, 0);
9699 if( nArg>=3 ){
drh37407122021-07-23 18:43:58 +00009700 for(iSes=0; iSes<pAuxDb->nSession; iSes++){
drhbf70f1b2022-10-19 18:04:42 +00009701 if( cli_strcmp(pAuxDb->aSession[iSes].zName, azArg[1])==0 ) break;
drh2ce15c32017-07-11 13:34:40 +00009702 }
drh37407122021-07-23 18:43:58 +00009703 if( iSes<pAuxDb->nSession ){
9704 pSession = &pAuxDb->aSession[iSes];
drh2ce15c32017-07-11 13:34:40 +00009705 azCmd++;
9706 nCmd--;
9707 }else{
drh37407122021-07-23 18:43:58 +00009708 pSession = &pAuxDb->aSession[0];
drh2ce15c32017-07-11 13:34:40 +00009709 iSes = 0;
9710 }
9711 }
9712
9713 /* .session attach TABLE
9714 ** Invoke the sqlite3session_attach() interface to attach a particular
9715 ** table so that it is never filtered.
9716 */
drhbf70f1b2022-10-19 18:04:42 +00009717 if( cli_strcmp(azCmd[0],"attach")==0 ){
drh2ce15c32017-07-11 13:34:40 +00009718 if( nCmd!=2 ) goto session_syntax_error;
9719 if( pSession->p==0 ){
9720 session_not_open:
9721 raw_printf(stderr, "ERROR: No sessions are open\n");
9722 }else{
9723 rc = sqlite3session_attach(pSession->p, azCmd[1]);
9724 if( rc ){
9725 raw_printf(stderr, "ERROR: sqlite3session_attach() returns %d\n", rc);
9726 rc = 0;
9727 }
9728 }
9729 }else
9730
9731 /* .session changeset FILE
9732 ** .session patchset FILE
9733 ** Write a changeset or patchset into a file. The file is overwritten.
9734 */
drhbf70f1b2022-10-19 18:04:42 +00009735 if( cli_strcmp(azCmd[0],"changeset")==0
9736 || cli_strcmp(azCmd[0],"patchset")==0
9737 ){
drh2ce15c32017-07-11 13:34:40 +00009738 FILE *out = 0;
drhb97e2ad2021-08-26 18:31:39 +00009739 failIfSafeMode(p, "cannot run \".session %s\" in safe mode", azCmd[0]);
drh2ce15c32017-07-11 13:34:40 +00009740 if( nCmd!=2 ) goto session_syntax_error;
9741 if( pSession->p==0 ) goto session_not_open;
9742 out = fopen(azCmd[1], "wb");
9743 if( out==0 ){
drhe2754c12019-08-26 12:50:01 +00009744 utf8_printf(stderr, "ERROR: cannot open \"%s\" for writing\n",
9745 azCmd[1]);
drh2ce15c32017-07-11 13:34:40 +00009746 }else{
9747 int szChng;
9748 void *pChng;
9749 if( azCmd[0][0]=='c' ){
9750 rc = sqlite3session_changeset(pSession->p, &szChng, &pChng);
9751 }else{
9752 rc = sqlite3session_patchset(pSession->p, &szChng, &pChng);
9753 }
9754 if( rc ){
9755 printf("Error: error code %d\n", rc);
9756 rc = 0;
9757 }
9758 if( pChng
9759 && fwrite(pChng, szChng, 1, out)!=1 ){
9760 raw_printf(stderr, "ERROR: Failed to write entire %d-byte output\n",
9761 szChng);
9762 }
9763 sqlite3_free(pChng);
9764 fclose(out);
9765 }
9766 }else
9767
9768 /* .session close
9769 ** Close the identified session
9770 */
drhbf70f1b2022-10-19 18:04:42 +00009771 if( cli_strcmp(azCmd[0], "close")==0 ){
drh2ce15c32017-07-11 13:34:40 +00009772 if( nCmd!=1 ) goto session_syntax_error;
drh37407122021-07-23 18:43:58 +00009773 if( pAuxDb->nSession ){
drh2ce15c32017-07-11 13:34:40 +00009774 session_close(pSession);
drh37407122021-07-23 18:43:58 +00009775 pAuxDb->aSession[iSes] = pAuxDb->aSession[--pAuxDb->nSession];
drh2ce15c32017-07-11 13:34:40 +00009776 }
9777 }else
9778
9779 /* .session enable ?BOOLEAN?
9780 ** Query or set the enable flag
9781 */
drhbf70f1b2022-10-19 18:04:42 +00009782 if( cli_strcmp(azCmd[0], "enable")==0 ){
drh2ce15c32017-07-11 13:34:40 +00009783 int ii;
9784 if( nCmd>2 ) goto session_syntax_error;
9785 ii = nCmd==1 ? -1 : booleanValue(azCmd[1]);
drh37407122021-07-23 18:43:58 +00009786 if( pAuxDb->nSession ){
drh2ce15c32017-07-11 13:34:40 +00009787 ii = sqlite3session_enable(pSession->p, ii);
9788 utf8_printf(p->out, "session %s enable flag = %d\n",
9789 pSession->zName, ii);
9790 }
9791 }else
9792
9793 /* .session filter GLOB ....
9794 ** Set a list of GLOB patterns of table names to be excluded.
9795 */
drhbf70f1b2022-10-19 18:04:42 +00009796 if( cli_strcmp(azCmd[0], "filter")==0 ){
drh2ce15c32017-07-11 13:34:40 +00009797 int ii, nByte;
9798 if( nCmd<2 ) goto session_syntax_error;
drh37407122021-07-23 18:43:58 +00009799 if( pAuxDb->nSession ){
drh2ce15c32017-07-11 13:34:40 +00009800 for(ii=0; ii<pSession->nFilter; ii++){
9801 sqlite3_free(pSession->azFilter[ii]);
9802 }
9803 sqlite3_free(pSession->azFilter);
9804 nByte = sizeof(pSession->azFilter[0])*(nCmd-1);
9805 pSession->azFilter = sqlite3_malloc( nByte );
9806 if( pSession->azFilter==0 ){
9807 raw_printf(stderr, "Error: out or memory\n");
9808 exit(1);
9809 }
9810 for(ii=1; ii<nCmd; ii++){
drhe3e25652021-12-16 13:29:28 +00009811 char *x = pSession->azFilter[ii-1] = sqlite3_mprintf("%s", azCmd[ii]);
9812 shell_check_oom(x);
drh2ce15c32017-07-11 13:34:40 +00009813 }
9814 pSession->nFilter = ii-1;
9815 }
9816 }else
9817
9818 /* .session indirect ?BOOLEAN?
9819 ** Query or set the indirect flag
9820 */
drhbf70f1b2022-10-19 18:04:42 +00009821 if( cli_strcmp(azCmd[0], "indirect")==0 ){
drh2ce15c32017-07-11 13:34:40 +00009822 int ii;
9823 if( nCmd>2 ) goto session_syntax_error;
9824 ii = nCmd==1 ? -1 : booleanValue(azCmd[1]);
drh37407122021-07-23 18:43:58 +00009825 if( pAuxDb->nSession ){
drh2ce15c32017-07-11 13:34:40 +00009826 ii = sqlite3session_indirect(pSession->p, ii);
9827 utf8_printf(p->out, "session %s indirect flag = %d\n",
9828 pSession->zName, ii);
9829 }
9830 }else
9831
9832 /* .session isempty
9833 ** Determine if the session is empty
9834 */
drhbf70f1b2022-10-19 18:04:42 +00009835 if( cli_strcmp(azCmd[0], "isempty")==0 ){
drh2ce15c32017-07-11 13:34:40 +00009836 int ii;
9837 if( nCmd!=1 ) goto session_syntax_error;
drh37407122021-07-23 18:43:58 +00009838 if( pAuxDb->nSession ){
drh2ce15c32017-07-11 13:34:40 +00009839 ii = sqlite3session_isempty(pSession->p);
9840 utf8_printf(p->out, "session %s isempty flag = %d\n",
9841 pSession->zName, ii);
9842 }
9843 }else
9844
9845 /* .session list
9846 ** List all currently open sessions
9847 */
drhbf70f1b2022-10-19 18:04:42 +00009848 if( cli_strcmp(azCmd[0],"list")==0 ){
drh37407122021-07-23 18:43:58 +00009849 for(i=0; i<pAuxDb->nSession; i++){
9850 utf8_printf(p->out, "%d %s\n", i, pAuxDb->aSession[i].zName);
drh2ce15c32017-07-11 13:34:40 +00009851 }
9852 }else
9853
9854 /* .session open DB NAME
9855 ** Open a new session called NAME on the attached database DB.
9856 ** DB is normally "main".
9857 */
drhbf70f1b2022-10-19 18:04:42 +00009858 if( cli_strcmp(azCmd[0],"open")==0 ){
drh2ce15c32017-07-11 13:34:40 +00009859 char *zName;
9860 if( nCmd!=3 ) goto session_syntax_error;
9861 zName = azCmd[2];
9862 if( zName[0]==0 ) goto session_syntax_error;
drh37407122021-07-23 18:43:58 +00009863 for(i=0; i<pAuxDb->nSession; i++){
drhbf70f1b2022-10-19 18:04:42 +00009864 if( cli_strcmp(pAuxDb->aSession[i].zName,zName)==0 ){
drh2ce15c32017-07-11 13:34:40 +00009865 utf8_printf(stderr, "Session \"%s\" already exists\n", zName);
9866 goto meta_command_exit;
9867 }
9868 }
drh37407122021-07-23 18:43:58 +00009869 if( pAuxDb->nSession>=ArraySize(pAuxDb->aSession) ){
9870 raw_printf(stderr, "Maximum of %d sessions\n", ArraySize(pAuxDb->aSession));
drh2ce15c32017-07-11 13:34:40 +00009871 goto meta_command_exit;
9872 }
drh37407122021-07-23 18:43:58 +00009873 pSession = &pAuxDb->aSession[pAuxDb->nSession];
drh2ce15c32017-07-11 13:34:40 +00009874 rc = sqlite3session_create(p->db, azCmd[1], &pSession->p);
9875 if( rc ){
9876 raw_printf(stderr, "Cannot open session: error code=%d\n", rc);
9877 rc = 0;
9878 goto meta_command_exit;
9879 }
9880 pSession->nFilter = 0;
9881 sqlite3session_table_filter(pSession->p, session_filter, pSession);
drh37407122021-07-23 18:43:58 +00009882 pAuxDb->nSession++;
drh2ce15c32017-07-11 13:34:40 +00009883 pSession->zName = sqlite3_mprintf("%s", zName);
drhe3e25652021-12-16 13:29:28 +00009884 shell_check_oom(pSession->zName);
drh2ce15c32017-07-11 13:34:40 +00009885 }else
9886 /* If no command name matches, show a syntax error */
9887 session_syntax_error:
drheb7f2a02018-09-26 18:02:32 +00009888 showHelp(p->out, "session");
drh2ce15c32017-07-11 13:34:40 +00009889 }else
9890#endif
9891
9892#ifdef SQLITE_DEBUG
9893 /* Undocumented commands for internal testing. Subject to change
9894 ** without notice. */
drhbf70f1b2022-10-19 18:04:42 +00009895 if( c=='s' && n>=10 && cli_strncmp(azArg[0], "selftest-", 9)==0 ){
9896 if( cli_strncmp(azArg[0]+9, "boolean", n-9)==0 ){
drh2ce15c32017-07-11 13:34:40 +00009897 int i, v;
9898 for(i=1; i<nArg; i++){
9899 v = booleanValue(azArg[i]);
9900 utf8_printf(p->out, "%s: %d 0x%x\n", azArg[i], v, v);
9901 }
9902 }
drhbf70f1b2022-10-19 18:04:42 +00009903 if( cli_strncmp(azArg[0]+9, "integer", n-9)==0 ){
drh2ce15c32017-07-11 13:34:40 +00009904 int i; sqlite3_int64 v;
9905 for(i=1; i<nArg; i++){
9906 char zBuf[200];
9907 v = integerValue(azArg[i]);
9908 sqlite3_snprintf(sizeof(zBuf),zBuf,"%s: %lld 0x%llx\n", azArg[i],v,v);
9909 utf8_printf(p->out, "%s", zBuf);
9910 }
9911 }
9912 }else
9913#endif
9914
drhbf70f1b2022-10-19 18:04:42 +00009915 if( c=='s' && n>=4 && cli_strncmp(azArg[0],"selftest",n)==0 ){
drh2ce15c32017-07-11 13:34:40 +00009916 int bIsInit = 0; /* True to initialize the SELFTEST table */
9917 int bVerbose = 0; /* Verbose output */
9918 int bSelftestExists; /* True if SELFTEST already exists */
9919 int i, k; /* Loop counters */
9920 int nTest = 0; /* Number of tests runs */
9921 int nErr = 0; /* Number of errors seen */
9922 ShellText str; /* Answer for a query */
9923 sqlite3_stmt *pStmt = 0; /* Query against the SELFTEST table */
9924
9925 open_db(p,0);
9926 for(i=1; i<nArg; i++){
9927 const char *z = azArg[i];
9928 if( z[0]=='-' && z[1]=='-' ) z++;
drhbf70f1b2022-10-19 18:04:42 +00009929 if( cli_strcmp(z,"-init")==0 ){
drh2ce15c32017-07-11 13:34:40 +00009930 bIsInit = 1;
9931 }else
drhbf70f1b2022-10-19 18:04:42 +00009932 if( cli_strcmp(z,"-v")==0 ){
drh2ce15c32017-07-11 13:34:40 +00009933 bVerbose++;
9934 }else
9935 {
9936 utf8_printf(stderr, "Unknown option \"%s\" on \"%s\"\n",
9937 azArg[i], azArg[0]);
9938 raw_printf(stderr, "Should be one of: --init -v\n");
9939 rc = 1;
9940 goto meta_command_exit;
9941 }
9942 }
9943 if( sqlite3_table_column_metadata(p->db,"main","selftest",0,0,0,0,0,0)
9944 != SQLITE_OK ){
9945 bSelftestExists = 0;
9946 }else{
9947 bSelftestExists = 1;
9948 }
9949 if( bIsInit ){
9950 createSelftestTable(p);
9951 bSelftestExists = 1;
9952 }
9953 initText(&str);
9954 appendText(&str, "x", 0);
9955 for(k=bSelftestExists; k>=0; k--){
9956 if( k==1 ){
9957 rc = sqlite3_prepare_v2(p->db,
9958 "SELECT tno,op,cmd,ans FROM selftest ORDER BY tno",
9959 -1, &pStmt, 0);
9960 }else{
9961 rc = sqlite3_prepare_v2(p->db,
9962 "VALUES(0,'memo','Missing SELFTEST table - default checks only',''),"
9963 " (1,'run','PRAGMA integrity_check','ok')",
9964 -1, &pStmt, 0);
9965 }
9966 if( rc ){
9967 raw_printf(stderr, "Error querying the selftest table\n");
9968 rc = 1;
9969 sqlite3_finalize(pStmt);
9970 goto meta_command_exit;
9971 }
9972 for(i=1; sqlite3_step(pStmt)==SQLITE_ROW; i++){
9973 int tno = sqlite3_column_int(pStmt, 0);
9974 const char *zOp = (const char*)sqlite3_column_text(pStmt, 1);
9975 const char *zSql = (const char*)sqlite3_column_text(pStmt, 2);
9976 const char *zAns = (const char*)sqlite3_column_text(pStmt, 3);
9977
drh621a5e02021-12-16 17:35:27 +00009978 if( zOp==0 ) continue;
9979 if( zSql==0 ) continue;
9980 if( zAns==0 ) continue;
drh2ce15c32017-07-11 13:34:40 +00009981 k = 0;
9982 if( bVerbose>0 ){
drh2ce15c32017-07-11 13:34:40 +00009983 printf("%d: %s %s\n", tno, zOp, zSql);
drh2ce15c32017-07-11 13:34:40 +00009984 }
drhbf70f1b2022-10-19 18:04:42 +00009985 if( cli_strcmp(zOp,"memo")==0 ){
drh2ce15c32017-07-11 13:34:40 +00009986 utf8_printf(p->out, "%s\n", zSql);
9987 }else
drhbf70f1b2022-10-19 18:04:42 +00009988 if( cli_strcmp(zOp,"run")==0 ){
drh2ce15c32017-07-11 13:34:40 +00009989 char *zErrMsg = 0;
9990 str.n = 0;
9991 str.z[0] = 0;
9992 rc = sqlite3_exec(p->db, zSql, captureOutputCallback, &str, &zErrMsg);
9993 nTest++;
9994 if( bVerbose ){
9995 utf8_printf(p->out, "Result: %s\n", str.z);
9996 }
9997 if( rc || zErrMsg ){
9998 nErr++;
9999 rc = 1;
10000 utf8_printf(p->out, "%d: error-code-%d: %s\n", tno, rc, zErrMsg);
10001 sqlite3_free(zErrMsg);
drhbf70f1b2022-10-19 18:04:42 +000010002 }else if( cli_strcmp(zAns,str.z)!=0 ){
drh2ce15c32017-07-11 13:34:40 +000010003 nErr++;
10004 rc = 1;
10005 utf8_printf(p->out, "%d: Expected: [%s]\n", tno, zAns);
10006 utf8_printf(p->out, "%d: Got: [%s]\n", tno, str.z);
10007 }
10008 }else
10009 {
10010 utf8_printf(stderr,
10011 "Unknown operation \"%s\" on selftest line %d\n", zOp, tno);
10012 rc = 1;
10013 break;
10014 }
10015 } /* End loop over rows of content from SELFTEST */
10016 sqlite3_finalize(pStmt);
10017 } /* End loop over k */
10018 freeText(&str);
10019 utf8_printf(p->out, "%d errors out of %d tests\n", nErr, nTest);
10020 }else
10021
drhbf70f1b2022-10-19 18:04:42 +000010022 if( c=='s' && cli_strncmp(azArg[0], "separator", n)==0 ){
drh2ce15c32017-07-11 13:34:40 +000010023 if( nArg<2 || nArg>3 ){
10024 raw_printf(stderr, "Usage: .separator COL ?ROW?\n");
10025 rc = 1;
10026 }
10027 if( nArg>=2 ){
10028 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator,
10029 "%.*s", (int)ArraySize(p->colSeparator)-1, azArg[1]);
10030 }
10031 if( nArg>=3 ){
10032 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator,
10033 "%.*s", (int)ArraySize(p->rowSeparator)-1, azArg[2]);
10034 }
10035 }else
10036
drhbf70f1b2022-10-19 18:04:42 +000010037 if( c=='s' && n>=4 && cli_strncmp(azArg[0],"sha3sum",n)==0 ){
drh2ce15c32017-07-11 13:34:40 +000010038 const char *zLike = 0; /* Which table to checksum. 0 means everything */
10039 int i; /* Loop counter */
10040 int bSchema = 0; /* Also hash the schema */
10041 int bSeparate = 0; /* Hash each table separately */
10042 int iSize = 224; /* Hash algorithm to use */
10043 int bDebug = 0; /* Only show the query that would have run */
10044 sqlite3_stmt *pStmt; /* For querying tables names */
10045 char *zSql; /* SQL to be run */
10046 char *zSep; /* Separator */
10047 ShellText sSql; /* Complete SQL for the query to run the hash */
10048 ShellText sQuery; /* Set of queries used to read all content */
10049 open_db(p, 0);
10050 for(i=1; i<nArg; i++){
10051 const char *z = azArg[i];
10052 if( z[0]=='-' ){
10053 z++;
10054 if( z[0]=='-' ) z++;
drhbf70f1b2022-10-19 18:04:42 +000010055 if( cli_strcmp(z,"schema")==0 ){
drh2ce15c32017-07-11 13:34:40 +000010056 bSchema = 1;
10057 }else
drhbf70f1b2022-10-19 18:04:42 +000010058 if( cli_strcmp(z,"sha3-224")==0 || cli_strcmp(z,"sha3-256")==0
10059 || cli_strcmp(z,"sha3-384")==0 || cli_strcmp(z,"sha3-512")==0
drh2ce15c32017-07-11 13:34:40 +000010060 ){
10061 iSize = atoi(&z[5]);
10062 }else
drhbf70f1b2022-10-19 18:04:42 +000010063 if( cli_strcmp(z,"debug")==0 ){
drh2ce15c32017-07-11 13:34:40 +000010064 bDebug = 1;
10065 }else
10066 {
10067 utf8_printf(stderr, "Unknown option \"%s\" on \"%s\"\n",
10068 azArg[i], azArg[0]);
drhe2754c12019-08-26 12:50:01 +000010069 showHelp(p->out, azArg[0]);
drh2ce15c32017-07-11 13:34:40 +000010070 rc = 1;
10071 goto meta_command_exit;
10072 }
10073 }else if( zLike ){
10074 raw_printf(stderr, "Usage: .sha3sum ?OPTIONS? ?LIKE-PATTERN?\n");
10075 rc = 1;
10076 goto meta_command_exit;
10077 }else{
10078 zLike = z;
10079 bSeparate = 1;
drhcedfecf2018-03-23 12:59:10 +000010080 if( sqlite3_strlike("sqlite\\_%", zLike, '\\')==0 ) bSchema = 1;
drh2ce15c32017-07-11 13:34:40 +000010081 }
10082 }
10083 if( bSchema ){
drh067b92b2020-06-19 15:24:12 +000010084 zSql = "SELECT lower(name) FROM sqlite_schema"
drh2ce15c32017-07-11 13:34:40 +000010085 " WHERE type='table' AND coalesce(rootpage,0)>1"
drh067b92b2020-06-19 15:24:12 +000010086 " UNION ALL SELECT 'sqlite_schema'"
drh2ce15c32017-07-11 13:34:40 +000010087 " ORDER BY 1 collate nocase";
10088 }else{
drh067b92b2020-06-19 15:24:12 +000010089 zSql = "SELECT lower(name) FROM sqlite_schema"
drh2ce15c32017-07-11 13:34:40 +000010090 " WHERE type='table' AND coalesce(rootpage,0)>1"
10091 " AND name NOT LIKE 'sqlite_%'"
10092 " ORDER BY 1 collate nocase";
10093 }
10094 sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
10095 initText(&sQuery);
10096 initText(&sSql);
10097 appendText(&sSql, "WITH [sha3sum$query](a,b) AS(",0);
10098 zSep = "VALUES(";
10099 while( SQLITE_ROW==sqlite3_step(pStmt) ){
10100 const char *zTab = (const char*)sqlite3_column_text(pStmt,0);
drh621a5e02021-12-16 17:35:27 +000010101 if( zTab==0 ) continue;
drh2ce15c32017-07-11 13:34:40 +000010102 if( zLike && sqlite3_strlike(zLike, zTab, 0)!=0 ) continue;
drhbf70f1b2022-10-19 18:04:42 +000010103 if( cli_strncmp(zTab, "sqlite_",7)!=0 ){
drh2ce15c32017-07-11 13:34:40 +000010104 appendText(&sQuery,"SELECT * FROM ", 0);
10105 appendText(&sQuery,zTab,'"');
10106 appendText(&sQuery," NOT INDEXED;", 0);
drhbf70f1b2022-10-19 18:04:42 +000010107 }else if( cli_strcmp(zTab, "sqlite_schema")==0 ){
drh067b92b2020-06-19 15:24:12 +000010108 appendText(&sQuery,"SELECT type,name,tbl_name,sql FROM sqlite_schema"
drh2ce15c32017-07-11 13:34:40 +000010109 " ORDER BY name;", 0);
drhbf70f1b2022-10-19 18:04:42 +000010110 }else if( cli_strcmp(zTab, "sqlite_sequence")==0 ){
drh2ce15c32017-07-11 13:34:40 +000010111 appendText(&sQuery,"SELECT name,seq FROM sqlite_sequence"
10112 " ORDER BY name;", 0);
drhbf70f1b2022-10-19 18:04:42 +000010113 }else if( cli_strcmp(zTab, "sqlite_stat1")==0 ){
drh2ce15c32017-07-11 13:34:40 +000010114 appendText(&sQuery,"SELECT tbl,idx,stat FROM sqlite_stat1"
10115 " ORDER BY tbl,idx;", 0);
drhbf70f1b2022-10-19 18:04:42 +000010116 }else if( cli_strcmp(zTab, "sqlite_stat4")==0 ){
drh2ce15c32017-07-11 13:34:40 +000010117 appendText(&sQuery, "SELECT * FROM ", 0);
10118 appendText(&sQuery, zTab, 0);
10119 appendText(&sQuery, " ORDER BY tbl, idx, rowid;\n", 0);
10120 }
10121 appendText(&sSql, zSep, 0);
10122 appendText(&sSql, sQuery.z, '\'');
10123 sQuery.n = 0;
10124 appendText(&sSql, ",", 0);
10125 appendText(&sSql, zTab, '\'');
10126 zSep = "),(";
10127 }
10128 sqlite3_finalize(pStmt);
10129 if( bSeparate ){
10130 zSql = sqlite3_mprintf(
10131 "%s))"
10132 " SELECT lower(hex(sha3_query(a,%d))) AS hash, b AS label"
10133 " FROM [sha3sum$query]",
10134 sSql.z, iSize);
10135 }else{
10136 zSql = sqlite3_mprintf(
10137 "%s))"
10138 " SELECT lower(hex(sha3_query(group_concat(a,''),%d))) AS hash"
10139 " FROM [sha3sum$query]",
10140 sSql.z, iSize);
10141 }
drhe3e25652021-12-16 13:29:28 +000010142 shell_check_oom(zSql);
drh2ce15c32017-07-11 13:34:40 +000010143 freeText(&sQuery);
10144 freeText(&sSql);
10145 if( bDebug ){
10146 utf8_printf(p->out, "%s\n", zSql);
10147 }else{
drha10b9992018-03-09 15:24:33 +000010148 shell_exec(p, zSql, 0);
drh2ce15c32017-07-11 13:34:40 +000010149 }
10150 sqlite3_free(zSql);
10151 }else
10152
stephan4413ec72022-07-12 15:53:02 +000010153#if !defined(SQLITE_NOHAVE_SYSTEM) && !defined(SQLITE_SHELL_FIDDLE)
drh2ce15c32017-07-11 13:34:40 +000010154 if( c=='s'
drhbf70f1b2022-10-19 18:04:42 +000010155 && (cli_strncmp(azArg[0], "shell", n)==0
10156 || cli_strncmp(azArg[0],"system",n)==0)
drh2ce15c32017-07-11 13:34:40 +000010157 ){
10158 char *zCmd;
10159 int i, x;
drhb97e2ad2021-08-26 18:31:39 +000010160 failIfSafeMode(p, "cannot run .%s in safe mode", azArg[0]);
drh2ce15c32017-07-11 13:34:40 +000010161 if( nArg<2 ){
10162 raw_printf(stderr, "Usage: .system COMMAND\n");
10163 rc = 1;
10164 goto meta_command_exit;
10165 }
10166 zCmd = sqlite3_mprintf(strchr(azArg[1],' ')==0?"%s":"\"%s\"", azArg[1]);
drhe3e25652021-12-16 13:29:28 +000010167 for(i=2; i<nArg && zCmd!=0; i++){
drh2ce15c32017-07-11 13:34:40 +000010168 zCmd = sqlite3_mprintf(strchr(azArg[i],' ')==0?"%z %s":"%z \"%s\"",
10169 zCmd, azArg[i]);
10170 }
drhe3e25652021-12-16 13:29:28 +000010171 x = zCmd!=0 ? system(zCmd) : 1;
drh2ce15c32017-07-11 13:34:40 +000010172 sqlite3_free(zCmd);
10173 if( x ) raw_printf(stderr, "System command returns %d\n", x);
10174 }else
stephan4413ec72022-07-12 15:53:02 +000010175#endif /* !defined(SQLITE_NOHAVE_SYSTEM) && !defined(SQLITE_SHELL_FIDDLE) */
drh2ce15c32017-07-11 13:34:40 +000010176
drhbf70f1b2022-10-19 18:04:42 +000010177 if( c=='s' && cli_strncmp(azArg[0], "show", n)==0 ){
drhada70452017-12-21 21:02:27 +000010178 static const char *azBool[] = { "off", "on", "trigger", "full"};
drha6e6cf22021-01-09 19:10:04 +000010179 const char *zOut;
drh2ce15c32017-07-11 13:34:40 +000010180 int i;
10181 if( nArg!=1 ){
10182 raw_printf(stderr, "Usage: .show\n");
10183 rc = 1;
10184 goto meta_command_exit;
10185 }
10186 utf8_printf(p->out, "%12.12s: %s\n","echo",
larrybrf4874812022-05-11 19:59:31 +000010187 azBool[ShellHasFlag(p, SHFLG_Echo)]);
drh2ce15c32017-07-11 13:34:40 +000010188 utf8_printf(p->out, "%12.12s: %s\n","eqp", azBool[p->autoEQP&3]);
10189 utf8_printf(p->out, "%12.12s: %s\n","explain",
10190 p->mode==MODE_Explain ? "on" : p->autoExplain ? "auto" : "off");
10191 utf8_printf(p->out,"%12.12s: %s\n","headers", azBool[p->showHeader!=0]);
drhe40f2862022-01-31 14:14:29 +000010192 if( p->mode==MODE_Column
10193 || (p->mode>=MODE_Markdown && p->mode<=MODE_Box)
10194 ){
larrybrcc4d55c2022-02-01 02:50:45 +000010195 utf8_printf
10196 (p->out, "%12.12s: %s --wrap %d --wordwrap %s --%squote\n", "mode",
10197 modeDescr[p->mode], p->cmOpts.iWrap,
10198 p->cmOpts.bWordWrap ? "on" : "off",
10199 p->cmOpts.bQuote ? "" : "no");
drhe40f2862022-01-31 14:14:29 +000010200 }else{
10201 utf8_printf(p->out, "%12.12s: %s\n","mode", modeDescr[p->mode]);
10202 }
drh2ce15c32017-07-11 13:34:40 +000010203 utf8_printf(p->out, "%12.12s: ", "nullvalue");
10204 output_c_string(p->out, p->nullValue);
10205 raw_printf(p->out, "\n");
10206 utf8_printf(p->out,"%12.12s: %s\n","output",
10207 strlen30(p->outfile) ? p->outfile : "stdout");
10208 utf8_printf(p->out,"%12.12s: ", "colseparator");
10209 output_c_string(p->out, p->colSeparator);
10210 raw_printf(p->out, "\n");
10211 utf8_printf(p->out,"%12.12s: ", "rowseparator");
10212 output_c_string(p->out, p->rowSeparator);
10213 raw_printf(p->out, "\n");
drha6e6cf22021-01-09 19:10:04 +000010214 switch( p->statsOn ){
10215 case 0: zOut = "off"; break;
10216 default: zOut = "on"; break;
10217 case 2: zOut = "stmt"; break;
10218 case 3: zOut = "vmstep"; break;
10219 }
10220 utf8_printf(p->out, "%12.12s: %s\n","stats", zOut);
drh2ce15c32017-07-11 13:34:40 +000010221 utf8_printf(p->out, "%12.12s: ", "width");
drh0285d982020-05-29 14:38:43 +000010222 for (i=0;i<p->nWidth;i++) {
drh2ce15c32017-07-11 13:34:40 +000010223 raw_printf(p->out, "%d ", p->colWidth[i]);
10224 }
10225 raw_printf(p->out, "\n");
10226 utf8_printf(p->out, "%12.12s: %s\n", "filename",
drh37407122021-07-23 18:43:58 +000010227 p->pAuxDb->zDbFilename ? p->pAuxDb->zDbFilename : "");
drh2ce15c32017-07-11 13:34:40 +000010228 }else
10229
drhbf70f1b2022-10-19 18:04:42 +000010230 if( c=='s' && cli_strncmp(azArg[0], "stats", n)==0 ){
drh2ce15c32017-07-11 13:34:40 +000010231 if( nArg==2 ){
drhbf70f1b2022-10-19 18:04:42 +000010232 if( cli_strcmp(azArg[1],"stmt")==0 ){
drha6e6cf22021-01-09 19:10:04 +000010233 p->statsOn = 2;
drhbf70f1b2022-10-19 18:04:42 +000010234 }else if( cli_strcmp(azArg[1],"vmstep")==0 ){
drha6e6cf22021-01-09 19:10:04 +000010235 p->statsOn = 3;
10236 }else{
10237 p->statsOn = (u8)booleanValue(azArg[1]);
10238 }
drh2ce15c32017-07-11 13:34:40 +000010239 }else if( nArg==1 ){
10240 display_stats(p->db, p, 0);
10241 }else{
drha6e6cf22021-01-09 19:10:04 +000010242 raw_printf(stderr, "Usage: .stats ?on|off|stmt|vmstep?\n");
drh2ce15c32017-07-11 13:34:40 +000010243 rc = 1;
10244 }
10245 }else
10246
drhbf70f1b2022-10-19 18:04:42 +000010247 if( (c=='t' && n>1 && cli_strncmp(azArg[0], "tables", n)==0)
10248 || (c=='i' && (cli_strncmp(azArg[0], "indices", n)==0
10249 || cli_strncmp(azArg[0], "indexes", n)==0) )
drh2ce15c32017-07-11 13:34:40 +000010250 ){
10251 sqlite3_stmt *pStmt;
10252 char **azResult;
10253 int nRow, nAlloc;
10254 int ii;
10255 ShellText s;
10256 initText(&s);
10257 open_db(p, 0);
10258 rc = sqlite3_prepare_v2(p->db, "PRAGMA database_list", -1, &pStmt, 0);
drh9e804032018-05-18 17:11:50 +000010259 if( rc ){
10260 sqlite3_finalize(pStmt);
10261 return shellDatabaseError(p->db);
10262 }
drh2ce15c32017-07-11 13:34:40 +000010263
10264 if( nArg>2 && c=='i' ){
10265 /* It is an historical accident that the .indexes command shows an error
10266 ** when called with the wrong number of arguments whereas the .tables
10267 ** command does not. */
10268 raw_printf(stderr, "Usage: .indexes ?LIKE-PATTERN?\n");
10269 rc = 1;
drh9e804032018-05-18 17:11:50 +000010270 sqlite3_finalize(pStmt);
drh2ce15c32017-07-11 13:34:40 +000010271 goto meta_command_exit;
10272 }
10273 for(ii=0; sqlite3_step(pStmt)==SQLITE_ROW; ii++){
10274 const char *zDbName = (const char*)sqlite3_column_text(pStmt, 1);
10275 if( zDbName==0 ) continue;
10276 if( s.z && s.z[0] ) appendText(&s, " UNION ALL ", 0);
10277 if( sqlite3_stricmp(zDbName, "main")==0 ){
10278 appendText(&s, "SELECT name FROM ", 0);
10279 }else{
10280 appendText(&s, "SELECT ", 0);
10281 appendText(&s, zDbName, '\'');
10282 appendText(&s, "||'.'||name FROM ", 0);
10283 }
10284 appendText(&s, zDbName, '"');
drh067b92b2020-06-19 15:24:12 +000010285 appendText(&s, ".sqlite_schema ", 0);
drh2ce15c32017-07-11 13:34:40 +000010286 if( c=='t' ){
10287 appendText(&s," WHERE type IN ('table','view')"
10288 " AND name NOT LIKE 'sqlite_%'"
10289 " AND name LIKE ?1", 0);
10290 }else{
10291 appendText(&s," WHERE type='index'"
10292 " AND tbl_name LIKE ?1", 0);
10293 }
10294 }
10295 rc = sqlite3_finalize(pStmt);
drhe85e1da2021-10-01 21:01:07 +000010296 if( rc==SQLITE_OK ){
10297 appendText(&s, " ORDER BY 1", 0);
10298 rc = sqlite3_prepare_v2(p->db, s.z, -1, &pStmt, 0);
10299 }
drh2ce15c32017-07-11 13:34:40 +000010300 freeText(&s);
10301 if( rc ) return shellDatabaseError(p->db);
10302
10303 /* Run the SQL statement prepared by the above block. Store the results
10304 ** as an array of nul-terminated strings in azResult[]. */
10305 nRow = nAlloc = 0;
10306 azResult = 0;
10307 if( nArg>1 ){
10308 sqlite3_bind_text(pStmt, 1, azArg[1], -1, SQLITE_TRANSIENT);
10309 }else{
10310 sqlite3_bind_text(pStmt, 1, "%", -1, SQLITE_STATIC);
10311 }
10312 while( sqlite3_step(pStmt)==SQLITE_ROW ){
10313 if( nRow>=nAlloc ){
10314 char **azNew;
10315 int n2 = nAlloc*2 + 10;
10316 azNew = sqlite3_realloc64(azResult, sizeof(azResult[0])*n2);
drhe3e25652021-12-16 13:29:28 +000010317 shell_check_oom(azNew);
drh2ce15c32017-07-11 13:34:40 +000010318 nAlloc = n2;
10319 azResult = azNew;
10320 }
10321 azResult[nRow] = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 0));
drhe3e25652021-12-16 13:29:28 +000010322 shell_check_oom(azResult[nRow]);
drh2ce15c32017-07-11 13:34:40 +000010323 nRow++;
10324 }
10325 if( sqlite3_finalize(pStmt)!=SQLITE_OK ){
10326 rc = shellDatabaseError(p->db);
10327 }
10328
10329 /* Pretty-print the contents of array azResult[] to the output */
10330 if( rc==0 && nRow>0 ){
10331 int len, maxlen = 0;
10332 int i, j;
10333 int nPrintCol, nPrintRow;
10334 for(i=0; i<nRow; i++){
10335 len = strlen30(azResult[i]);
10336 if( len>maxlen ) maxlen = len;
10337 }
10338 nPrintCol = 80/(maxlen+2);
10339 if( nPrintCol<1 ) nPrintCol = 1;
10340 nPrintRow = (nRow + nPrintCol - 1)/nPrintCol;
10341 for(i=0; i<nPrintRow; i++){
10342 for(j=i; j<nRow; j+=nPrintRow){
10343 char *zSp = j<nPrintRow ? "" : " ";
10344 utf8_printf(p->out, "%s%-*s", zSp, maxlen,
10345 azResult[j] ? azResult[j]:"");
10346 }
10347 raw_printf(p->out, "\n");
10348 }
10349 }
10350
10351 for(ii=0; ii<nRow; ii++) sqlite3_free(azResult[ii]);
10352 sqlite3_free(azResult);
10353 }else
10354
stephan4413ec72022-07-12 15:53:02 +000010355#ifndef SQLITE_SHELL_FIDDLE
drh2ce15c32017-07-11 13:34:40 +000010356 /* Begin redirecting output to the file "testcase-out.txt" */
drhbf70f1b2022-10-19 18:04:42 +000010357 if( c=='t' && cli_strcmp(azArg[0],"testcase")==0 ){
drh2ce15c32017-07-11 13:34:40 +000010358 output_reset(p);
drha92a01a2018-01-10 22:15:37 +000010359 p->out = output_file_open("testcase-out.txt", 0);
drh2ce15c32017-07-11 13:34:40 +000010360 if( p->out==0 ){
10361 raw_printf(stderr, "Error: cannot open 'testcase-out.txt'\n");
10362 }
10363 if( nArg>=2 ){
10364 sqlite3_snprintf(sizeof(p->zTestcase), p->zTestcase, "%s", azArg[1]);
10365 }else{
10366 sqlite3_snprintf(sizeof(p->zTestcase), p->zTestcase, "?");
10367 }
10368 }else
stephan4413ec72022-07-12 15:53:02 +000010369#endif /* !defined(SQLITE_SHELL_FIDDLE) */
drh2ce15c32017-07-11 13:34:40 +000010370
10371#ifndef SQLITE_UNTESTABLE
drhbf70f1b2022-10-19 18:04:42 +000010372 if( c=='t' && n>=8 && cli_strncmp(azArg[0], "testctrl", n)==0 ){
drh2ce15c32017-07-11 13:34:40 +000010373 static const struct {
10374 const char *zCtrlName; /* Name of a test-control option */
10375 int ctrlCode; /* Integer code for that option */
drh38ed1ce2021-12-06 15:24:36 +000010376 int unSafe; /* Not valid for --safe mode */
drhef302e82017-11-15 19:14:08 +000010377 const char *zUsage; /* Usage notes */
drh2ce15c32017-07-11 13:34:40 +000010378 } aCtrl[] = {
drh38ed1ce2021-12-06 15:24:36 +000010379 { "always", SQLITE_TESTCTRL_ALWAYS, 1, "BOOLEAN" },
10380 { "assert", SQLITE_TESTCTRL_ASSERT, 1, "BOOLEAN" },
10381 /*{ "benign_malloc_hooks",SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS,1, "" },*/
10382 /*{ "bitvec_test", SQLITE_TESTCTRL_BITVEC_TEST, 1, "" },*/
10383 { "byteorder", SQLITE_TESTCTRL_BYTEORDER, 0, "" },
10384 { "extra_schema_checks",SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS,0,"BOOLEAN" },
10385 /*{ "fault_install", SQLITE_TESTCTRL_FAULT_INSTALL, 1,"" },*/
10386 { "imposter", SQLITE_TESTCTRL_IMPOSTER,1,"SCHEMA ON/OFF ROOTPAGE"},
10387 { "internal_functions", SQLITE_TESTCTRL_INTERNAL_FUNCTIONS,0,"" },
10388 { "localtime_fault", SQLITE_TESTCTRL_LOCALTIME_FAULT,0,"BOOLEAN" },
10389 { "never_corrupt", SQLITE_TESTCTRL_NEVER_CORRUPT,1, "BOOLEAN" },
10390 { "optimizations", SQLITE_TESTCTRL_OPTIMIZATIONS,0,"DISABLE-MASK" },
drh0d9de992017-12-26 18:04:23 +000010391#ifdef YYCOVERAGE
drh38ed1ce2021-12-06 15:24:36 +000010392 { "parser_coverage", SQLITE_TESTCTRL_PARSER_COVERAGE,0,"" },
drh0d9de992017-12-26 18:04:23 +000010393#endif
drh38ed1ce2021-12-06 15:24:36 +000010394 { "pending_byte", SQLITE_TESTCTRL_PENDING_BYTE,0, "OFFSET " },
10395 { "prng_restore", SQLITE_TESTCTRL_PRNG_RESTORE,0, "" },
10396 { "prng_save", SQLITE_TESTCTRL_PRNG_SAVE, 0, "" },
10397 { "prng_seed", SQLITE_TESTCTRL_PRNG_SEED, 0, "SEED ?db?" },
10398 { "seek_count", SQLITE_TESTCTRL_SEEK_COUNT, 0, "" },
10399 { "sorter_mmap", SQLITE_TESTCTRL_SORTER_MMAP, 0, "NMAX" },
10400 { "tune", SQLITE_TESTCTRL_TUNE, 1, "ID VALUE" },
drh2ce15c32017-07-11 13:34:40 +000010401 };
10402 int testctrl = -1;
drhef302e82017-11-15 19:14:08 +000010403 int iCtrl = -1;
10404 int rc2 = 0; /* 0: usage. 1: %d 2: %x 3: no-output */
10405 int isOk = 0;
drh2ce15c32017-07-11 13:34:40 +000010406 int i, n2;
mistachkinc6bc15a2017-11-21 21:14:32 +000010407 const char *zCmd = 0;
10408
drh2ce15c32017-07-11 13:34:40 +000010409 open_db(p, 0);
mistachkinc6bc15a2017-11-21 21:14:32 +000010410 zCmd = nArg>=2 ? azArg[1] : "help";
drh35f51a42017-11-15 17:07:22 +000010411
10412 /* The argument can optionally begin with "-" or "--" */
10413 if( zCmd[0]=='-' && zCmd[1] ){
10414 zCmd++;
10415 if( zCmd[0]=='-' && zCmd[1] ) zCmd++;
10416 }
10417
10418 /* --help lists all test-controls */
drhbf70f1b2022-10-19 18:04:42 +000010419 if( cli_strcmp(zCmd,"help")==0 ){
drh35f51a42017-11-15 17:07:22 +000010420 utf8_printf(p->out, "Available test-controls:\n");
10421 for(i=0; i<ArraySize(aCtrl); i++){
drhef302e82017-11-15 19:14:08 +000010422 utf8_printf(p->out, " .testctrl %s %s\n",
10423 aCtrl[i].zCtrlName, aCtrl[i].zUsage);
drh35f51a42017-11-15 17:07:22 +000010424 }
10425 rc = 1;
10426 goto meta_command_exit;
10427 }
drh2ce15c32017-07-11 13:34:40 +000010428
10429 /* convert testctrl text option to value. allow any unique prefix
10430 ** of the option name, or a numerical value. */
drh35f51a42017-11-15 17:07:22 +000010431 n2 = strlen30(zCmd);
drh2ce15c32017-07-11 13:34:40 +000010432 for(i=0; i<ArraySize(aCtrl); i++){
drhbf70f1b2022-10-19 18:04:42 +000010433 if( cli_strncmp(zCmd, aCtrl[i].zCtrlName, n2)==0 ){
drh2ce15c32017-07-11 13:34:40 +000010434 if( testctrl<0 ){
10435 testctrl = aCtrl[i].ctrlCode;
drhef302e82017-11-15 19:14:08 +000010436 iCtrl = i;
drh2ce15c32017-07-11 13:34:40 +000010437 }else{
drh35f51a42017-11-15 17:07:22 +000010438 utf8_printf(stderr, "Error: ambiguous test-control: \"%s\"\n"
10439 "Use \".testctrl --help\" for help\n", zCmd);
10440 rc = 1;
10441 goto meta_command_exit;
drh2ce15c32017-07-11 13:34:40 +000010442 }
10443 }
10444 }
drhef302e82017-11-15 19:14:08 +000010445 if( testctrl<0 ){
drh35f51a42017-11-15 17:07:22 +000010446 utf8_printf(stderr,"Error: unknown test-control: %s\n"
10447 "Use \".testctrl --help\" for help\n", zCmd);
drh38ed1ce2021-12-06 15:24:36 +000010448 }else if( aCtrl[iCtrl].unSafe && p->bSafeMode ){
10449 utf8_printf(stderr,
10450 "line %d: \".testctrl %s\" may not be used in safe mode\n",
10451 p->lineno, aCtrl[iCtrl].zCtrlName);
10452 exit(1);
drh2ce15c32017-07-11 13:34:40 +000010453 }else{
10454 switch(testctrl){
10455
10456 /* sqlite3_test_control(int, db, int) */
10457 case SQLITE_TESTCTRL_OPTIMIZATIONS:
drh2ce15c32017-07-11 13:34:40 +000010458 if( nArg==3 ){
drhaf7b7652021-01-13 19:28:17 +000010459 unsigned int opt = (unsigned int)strtol(azArg[2], 0, 0);
drh2ce15c32017-07-11 13:34:40 +000010460 rc2 = sqlite3_test_control(testctrl, p->db, opt);
drhef302e82017-11-15 19:14:08 +000010461 isOk = 3;
drh2ce15c32017-07-11 13:34:40 +000010462 }
10463 break;
10464
10465 /* sqlite3_test_control(int) */
10466 case SQLITE_TESTCTRL_PRNG_SAVE:
10467 case SQLITE_TESTCTRL_PRNG_RESTORE:
drh2ce15c32017-07-11 13:34:40 +000010468 case SQLITE_TESTCTRL_BYTEORDER:
10469 if( nArg==2 ){
10470 rc2 = sqlite3_test_control(testctrl);
drhef302e82017-11-15 19:14:08 +000010471 isOk = testctrl==SQLITE_TESTCTRL_BYTEORDER ? 1 : 3;
drh2ce15c32017-07-11 13:34:40 +000010472 }
10473 break;
10474
10475 /* sqlite3_test_control(int, uint) */
10476 case SQLITE_TESTCTRL_PENDING_BYTE:
10477 if( nArg==3 ){
10478 unsigned int opt = (unsigned int)integerValue(azArg[2]);
10479 rc2 = sqlite3_test_control(testctrl, opt);
drhef302e82017-11-15 19:14:08 +000010480 isOk = 3;
drh2ce15c32017-07-11 13:34:40 +000010481 }
10482 break;
10483
drh2e6d83b2019-08-03 01:39:20 +000010484 /* sqlite3_test_control(int, int, sqlite3*) */
10485 case SQLITE_TESTCTRL_PRNG_SEED:
10486 if( nArg==3 || nArg==4 ){
drh51755a72019-08-08 19:40:29 +000010487 int ii = (int)integerValue(azArg[2]);
drh2e6d83b2019-08-03 01:39:20 +000010488 sqlite3 *db;
drhbf70f1b2022-10-19 18:04:42 +000010489 if( ii==0 && cli_strcmp(azArg[2],"random")==0 ){
drh41428a92019-08-12 16:25:11 +000010490 sqlite3_randomness(sizeof(ii),&ii);
10491 printf("-- random seed: %d\n", ii);
10492 }
drh2e6d83b2019-08-03 01:39:20 +000010493 if( nArg==3 ){
10494 db = 0;
10495 }else{
10496 db = p->db;
10497 /* Make sure the schema has been loaded */
10498 sqlite3_table_column_metadata(db, 0, "x", 0, 0, 0, 0, 0, 0);
10499 }
drh51755a72019-08-08 19:40:29 +000010500 rc2 = sqlite3_test_control(testctrl, ii, db);
drh2e6d83b2019-08-03 01:39:20 +000010501 isOk = 3;
10502 }
10503 break;
10504
drh2ce15c32017-07-11 13:34:40 +000010505 /* sqlite3_test_control(int, int) */
10506 case SQLITE_TESTCTRL_ASSERT:
10507 case SQLITE_TESTCTRL_ALWAYS:
drhef302e82017-11-15 19:14:08 +000010508 if( nArg==3 ){
10509 int opt = booleanValue(azArg[2]);
10510 rc2 = sqlite3_test_control(testctrl, opt);
10511 isOk = 1;
10512 }
10513 break;
10514
10515 /* sqlite3_test_control(int, int) */
10516 case SQLITE_TESTCTRL_LOCALTIME_FAULT:
drh2ce15c32017-07-11 13:34:40 +000010517 case SQLITE_TESTCTRL_NEVER_CORRUPT:
10518 if( nArg==3 ){
10519 int opt = booleanValue(azArg[2]);
10520 rc2 = sqlite3_test_control(testctrl, opt);
drhef302e82017-11-15 19:14:08 +000010521 isOk = 3;
drh2ce15c32017-07-11 13:34:40 +000010522 }
10523 break;
10524
drh171c50e2020-01-01 15:43:30 +000010525 /* sqlite3_test_control(sqlite3*) */
10526 case SQLITE_TESTCTRL_INTERNAL_FUNCTIONS:
10527 rc2 = sqlite3_test_control(testctrl, p->db);
drh2a83c102020-01-01 23:02:35 +000010528 isOk = 3;
drh171c50e2020-01-01 15:43:30 +000010529 break;
10530
drh2ce15c32017-07-11 13:34:40 +000010531 case SQLITE_TESTCTRL_IMPOSTER:
10532 if( nArg==5 ){
10533 rc2 = sqlite3_test_control(testctrl, p->db,
10534 azArg[2],
10535 integerValue(azArg[3]),
10536 integerValue(azArg[4]));
drhef302e82017-11-15 19:14:08 +000010537 isOk = 3;
drh2ce15c32017-07-11 13:34:40 +000010538 }
10539 break;
drh0d9de992017-12-26 18:04:23 +000010540
drh37ccfcf2020-08-31 18:49:04 +000010541 case SQLITE_TESTCTRL_SEEK_COUNT: {
10542 u64 x = 0;
10543 rc2 = sqlite3_test_control(testctrl, p->db, &x);
10544 utf8_printf(p->out, "%llu\n", x);
10545 isOk = 3;
10546 break;
10547 }
10548
drh0d9de992017-12-26 18:04:23 +000010549#ifdef YYCOVERAGE
drhf3c12562021-06-04 13:16:46 +000010550 case SQLITE_TESTCTRL_PARSER_COVERAGE: {
drh0d9de992017-12-26 18:04:23 +000010551 if( nArg==2 ){
10552 sqlite3_test_control(testctrl, p->out);
10553 isOk = 3;
10554 }
drhf3c12562021-06-04 13:16:46 +000010555 break;
10556 }
10557#endif
10558#ifdef SQLITE_DEBUG
10559 case SQLITE_TESTCTRL_TUNE: {
10560 if( nArg==4 ){
10561 int id = (int)integerValue(azArg[2]);
drh2d26cfc2021-06-04 13:40:26 +000010562 int val = (int)integerValue(azArg[3]);
10563 sqlite3_test_control(testctrl, id, &val);
10564 isOk = 3;
10565 }else if( nArg==3 ){
10566 int id = (int)integerValue(azArg[2]);
10567 sqlite3_test_control(testctrl, -id, &rc2);
10568 isOk = 1;
10569 }else if( nArg==2 ){
10570 int id = 1;
10571 while(1){
10572 int val = 0;
10573 rc2 = sqlite3_test_control(testctrl, -id, &val);
10574 if( rc2!=SQLITE_OK ) break;
10575 if( id>1 ) utf8_printf(p->out, " ");
10576 utf8_printf(p->out, "%d: %d", id, val);
10577 id++;
10578 }
10579 if( id>1 ) utf8_printf(p->out, "\n");
drhf3c12562021-06-04 13:16:46 +000010580 isOk = 3;
10581 }
10582 break;
10583 }
drh0d9de992017-12-26 18:04:23 +000010584#endif
dan779e9902021-07-28 18:13:28 +000010585 case SQLITE_TESTCTRL_SORTER_MMAP:
10586 if( nArg==3 ){
10587 int opt = (unsigned int)integerValue(azArg[2]);
10588 rc2 = sqlite3_test_control(testctrl, p->db, opt);
10589 isOk = 3;
10590 }
10591 break;
drh2ce15c32017-07-11 13:34:40 +000010592 }
10593 }
drhef302e82017-11-15 19:14:08 +000010594 if( isOk==0 && iCtrl>=0 ){
drhe2754c12019-08-26 12:50:01 +000010595 utf8_printf(p->out, "Usage: .testctrl %s %s\n", zCmd,aCtrl[iCtrl].zUsage);
drhef302e82017-11-15 19:14:08 +000010596 rc = 1;
10597 }else if( isOk==1 ){
10598 raw_printf(p->out, "%d\n", rc2);
10599 }else if( isOk==2 ){
10600 raw_printf(p->out, "0x%08x\n", rc2);
10601 }
drh2ce15c32017-07-11 13:34:40 +000010602 }else
10603#endif /* !defined(SQLITE_UNTESTABLE) */
10604
drhbf70f1b2022-10-19 18:04:42 +000010605 if( c=='t' && n>4 && cli_strncmp(azArg[0], "timeout", n)==0 ){
drh2ce15c32017-07-11 13:34:40 +000010606 open_db(p, 0);
10607 sqlite3_busy_timeout(p->db, nArg>=2 ? (int)integerValue(azArg[1]) : 0);
10608 }else
10609
drhbf70f1b2022-10-19 18:04:42 +000010610 if( c=='t' && n>=5 && cli_strncmp(azArg[0], "timer", n)==0 ){
drh2ce15c32017-07-11 13:34:40 +000010611 if( nArg==2 ){
10612 enableTimer = booleanValue(azArg[1]);
10613 if( enableTimer && !HAS_TIMER ){
10614 raw_printf(stderr, "Error: timer not available on this system.\n");
10615 enableTimer = 0;
10616 }
10617 }else{
10618 raw_printf(stderr, "Usage: .timer on|off\n");
10619 rc = 1;
10620 }
10621 }else
10622
drh707821f2018-12-05 13:39:06 +000010623#ifndef SQLITE_OMIT_TRACE
drhbf70f1b2022-10-19 18:04:42 +000010624 if( c=='t' && cli_strncmp(azArg[0], "trace", n)==0 ){
drh707821f2018-12-05 13:39:06 +000010625 int mType = 0;
10626 int jj;
drh2ce15c32017-07-11 13:34:40 +000010627 open_db(p, 0);
drh707821f2018-12-05 13:39:06 +000010628 for(jj=1; jj<nArg; jj++){
10629 const char *z = azArg[jj];
10630 if( z[0]=='-' ){
10631 if( optionMatch(z, "expanded") ){
10632 p->eTraceType = SHELL_TRACE_EXPANDED;
10633 }
10634#ifdef SQLITE_ENABLE_NORMALIZE
10635 else if( optionMatch(z, "normalized") ){
10636 p->eTraceType = SHELL_TRACE_NORMALIZED;
10637 }
10638#endif
10639 else if( optionMatch(z, "plain") ){
10640 p->eTraceType = SHELL_TRACE_PLAIN;
10641 }
10642 else if( optionMatch(z, "profile") ){
10643 mType |= SQLITE_TRACE_PROFILE;
10644 }
10645 else if( optionMatch(z, "row") ){
10646 mType |= SQLITE_TRACE_ROW;
10647 }
10648 else if( optionMatch(z, "stmt") ){
10649 mType |= SQLITE_TRACE_STMT;
10650 }
10651 else if( optionMatch(z, "close") ){
10652 mType |= SQLITE_TRACE_CLOSE;
10653 }
10654 else {
10655 raw_printf(stderr, "Unknown option \"%s\" on \".trace\"\n", z);
10656 rc = 1;
10657 goto meta_command_exit;
10658 }
10659 }else{
10660 output_file_close(p->traceOut);
10661 p->traceOut = output_file_open(azArg[1], 0);
10662 }
drh2ce15c32017-07-11 13:34:40 +000010663 }
drh2ce15c32017-07-11 13:34:40 +000010664 if( p->traceOut==0 ){
10665 sqlite3_trace_v2(p->db, 0, 0, 0);
10666 }else{
drh707821f2018-12-05 13:39:06 +000010667 if( mType==0 ) mType = SQLITE_TRACE_STMT;
10668 sqlite3_trace_v2(p->db, mType, sql_trace_callback, p);
drh2ce15c32017-07-11 13:34:40 +000010669 }
drh2ce15c32017-07-11 13:34:40 +000010670 }else
drh707821f2018-12-05 13:39:06 +000010671#endif /* !defined(SQLITE_OMIT_TRACE) */
drh2ce15c32017-07-11 13:34:40 +000010672
drhe2b7a762019-10-02 00:25:08 +000010673#if defined(SQLITE_DEBUG) && !defined(SQLITE_OMIT_VIRTUALTABLE)
drhbf70f1b2022-10-19 18:04:42 +000010674 if( c=='u' && cli_strncmp(azArg[0], "unmodule", n)==0 ){
drhcc5979d2019-08-16 22:58:29 +000010675 int ii;
drh8c754a32019-08-19 20:35:30 +000010676 int lenOpt;
drh5df84282019-08-17 19:45:25 +000010677 char *zOpt;
drhcc5979d2019-08-16 22:58:29 +000010678 if( nArg<2 ){
drh5df84282019-08-17 19:45:25 +000010679 raw_printf(stderr, "Usage: .unmodule [--allexcept] NAME ...\n");
drhcc5979d2019-08-16 22:58:29 +000010680 rc = 1;
10681 goto meta_command_exit;
10682 }
10683 open_db(p, 0);
drh5df84282019-08-17 19:45:25 +000010684 zOpt = azArg[1];
10685 if( zOpt[0]=='-' && zOpt[1]=='-' && zOpt[2]!=0 ) zOpt++;
drh8c754a32019-08-19 20:35:30 +000010686 lenOpt = (int)strlen(zOpt);
drhbf70f1b2022-10-19 18:04:42 +000010687 if( lenOpt>=3 && cli_strncmp(zOpt, "-allexcept",lenOpt)==0 ){
drh5df84282019-08-17 19:45:25 +000010688 assert( azArg[nArg]==0 );
drh8c754a32019-08-19 20:35:30 +000010689 sqlite3_drop_modules(p->db, nArg>2 ? (const char**)(azArg+2) : 0);
drh5df84282019-08-17 19:45:25 +000010690 }else{
10691 for(ii=1; ii<nArg; ii++){
10692 sqlite3_create_module(p->db, azArg[ii], 0, 0);
10693 }
drhcc5979d2019-08-16 22:58:29 +000010694 }
10695 }else
10696#endif
10697
drh2ce15c32017-07-11 13:34:40 +000010698#if SQLITE_USER_AUTHENTICATION
drhbf70f1b2022-10-19 18:04:42 +000010699 if( c=='u' && cli_strncmp(azArg[0], "user", n)==0 ){
drh2ce15c32017-07-11 13:34:40 +000010700 if( nArg<2 ){
10701 raw_printf(stderr, "Usage: .user SUBCOMMAND ...\n");
10702 rc = 1;
10703 goto meta_command_exit;
10704 }
10705 open_db(p, 0);
drhbf70f1b2022-10-19 18:04:42 +000010706 if( cli_strcmp(azArg[1],"login")==0 ){
drh2ce15c32017-07-11 13:34:40 +000010707 if( nArg!=4 ){
10708 raw_printf(stderr, "Usage: .user login USER PASSWORD\n");
10709 rc = 1;
10710 goto meta_command_exit;
10711 }
drhe2754c12019-08-26 12:50:01 +000010712 rc = sqlite3_user_authenticate(p->db, azArg[2], azArg[3],
10713 strlen30(azArg[3]));
drh2ce15c32017-07-11 13:34:40 +000010714 if( rc ){
10715 utf8_printf(stderr, "Authentication failed for user %s\n", azArg[2]);
10716 rc = 1;
10717 }
drhbf70f1b2022-10-19 18:04:42 +000010718 }else if( cli_strcmp(azArg[1],"add")==0 ){
drh2ce15c32017-07-11 13:34:40 +000010719 if( nArg!=5 ){
10720 raw_printf(stderr, "Usage: .user add USER PASSWORD ISADMIN\n");
10721 rc = 1;
10722 goto meta_command_exit;
10723 }
drhaf2770f2018-01-05 14:55:43 +000010724 rc = sqlite3_user_add(p->db, azArg[2], azArg[3], strlen30(azArg[3]),
drh2ce15c32017-07-11 13:34:40 +000010725 booleanValue(azArg[4]));
10726 if( rc ){
10727 raw_printf(stderr, "User-Add failed: %d\n", rc);
10728 rc = 1;
10729 }
drhbf70f1b2022-10-19 18:04:42 +000010730 }else if( cli_strcmp(azArg[1],"edit")==0 ){
drh2ce15c32017-07-11 13:34:40 +000010731 if( nArg!=5 ){
10732 raw_printf(stderr, "Usage: .user edit USER PASSWORD ISADMIN\n");
10733 rc = 1;
10734 goto meta_command_exit;
10735 }
drhaf2770f2018-01-05 14:55:43 +000010736 rc = sqlite3_user_change(p->db, azArg[2], azArg[3], strlen30(azArg[3]),
drh2ce15c32017-07-11 13:34:40 +000010737 booleanValue(azArg[4]));
10738 if( rc ){
10739 raw_printf(stderr, "User-Edit failed: %d\n", rc);
10740 rc = 1;
10741 }
drhbf70f1b2022-10-19 18:04:42 +000010742 }else if( cli_strcmp(azArg[1],"delete")==0 ){
drh2ce15c32017-07-11 13:34:40 +000010743 if( nArg!=3 ){
10744 raw_printf(stderr, "Usage: .user delete USER\n");
10745 rc = 1;
10746 goto meta_command_exit;
10747 }
10748 rc = sqlite3_user_delete(p->db, azArg[2]);
10749 if( rc ){
10750 raw_printf(stderr, "User-Delete failed: %d\n", rc);
10751 rc = 1;
10752 }
10753 }else{
10754 raw_printf(stderr, "Usage: .user login|add|edit|delete ...\n");
10755 rc = 1;
10756 goto meta_command_exit;
10757 }
10758 }else
10759#endif /* SQLITE_USER_AUTHENTICATION */
10760
drhbf70f1b2022-10-19 18:04:42 +000010761 if( c=='v' && cli_strncmp(azArg[0], "version", n)==0 ){
drh2ce15c32017-07-11 13:34:40 +000010762 utf8_printf(p->out, "SQLite %s %s\n" /*extra-version-info*/,
10763 sqlite3_libversion(), sqlite3_sourceid());
drh0ed2fd82018-01-16 20:05:27 +000010764#if SQLITE_HAVE_ZLIB
10765 utf8_printf(p->out, "zlib version %s\n", zlibVersion());
10766#endif
10767#define CTIMEOPT_VAL_(opt) #opt
10768#define CTIMEOPT_VAL(opt) CTIMEOPT_VAL_(opt)
10769#if defined(__clang__) && defined(__clang_major__)
10770 utf8_printf(p->out, "clang-" CTIMEOPT_VAL(__clang_major__) "."
10771 CTIMEOPT_VAL(__clang_minor__) "."
10772 CTIMEOPT_VAL(__clang_patchlevel__) "\n");
10773#elif defined(_MSC_VER)
10774 utf8_printf(p->out, "msvc-" CTIMEOPT_VAL(_MSC_VER) "\n");
10775#elif defined(__GNUC__) && defined(__VERSION__)
10776 utf8_printf(p->out, "gcc-" __VERSION__ "\n");
10777#endif
drh2ce15c32017-07-11 13:34:40 +000010778 }else
10779
drhbf70f1b2022-10-19 18:04:42 +000010780 if( c=='v' && cli_strncmp(azArg[0], "vfsinfo", n)==0 ){
drh2ce15c32017-07-11 13:34:40 +000010781 const char *zDbName = nArg==2 ? azArg[1] : "main";
10782 sqlite3_vfs *pVfs = 0;
10783 if( p->db ){
10784 sqlite3_file_control(p->db, zDbName, SQLITE_FCNTL_VFS_POINTER, &pVfs);
10785 if( pVfs ){
10786 utf8_printf(p->out, "vfs.zName = \"%s\"\n", pVfs->zName);
10787 raw_printf(p->out, "vfs.iVersion = %d\n", pVfs->iVersion);
10788 raw_printf(p->out, "vfs.szOsFile = %d\n", pVfs->szOsFile);
10789 raw_printf(p->out, "vfs.mxPathname = %d\n", pVfs->mxPathname);
10790 }
10791 }
10792 }else
10793
drhbf70f1b2022-10-19 18:04:42 +000010794 if( c=='v' && cli_strncmp(azArg[0], "vfslist", n)==0 ){
drh2ce15c32017-07-11 13:34:40 +000010795 sqlite3_vfs *pVfs;
10796 sqlite3_vfs *pCurrent = 0;
10797 if( p->db ){
10798 sqlite3_file_control(p->db, "main", SQLITE_FCNTL_VFS_POINTER, &pCurrent);
10799 }
10800 for(pVfs=sqlite3_vfs_find(0); pVfs; pVfs=pVfs->pNext){
10801 utf8_printf(p->out, "vfs.zName = \"%s\"%s\n", pVfs->zName,
10802 pVfs==pCurrent ? " <--- CURRENT" : "");
10803 raw_printf(p->out, "vfs.iVersion = %d\n", pVfs->iVersion);
10804 raw_printf(p->out, "vfs.szOsFile = %d\n", pVfs->szOsFile);
10805 raw_printf(p->out, "vfs.mxPathname = %d\n", pVfs->mxPathname);
10806 if( pVfs->pNext ){
10807 raw_printf(p->out, "-----------------------------------\n");
10808 }
10809 }
10810 }else
10811
drhbf70f1b2022-10-19 18:04:42 +000010812 if( c=='v' && cli_strncmp(azArg[0], "vfsname", n)==0 ){
drh2ce15c32017-07-11 13:34:40 +000010813 const char *zDbName = nArg==2 ? azArg[1] : "main";
10814 char *zVfsName = 0;
10815 if( p->db ){
10816 sqlite3_file_control(p->db, zDbName, SQLITE_FCNTL_VFSNAME, &zVfsName);
10817 if( zVfsName ){
10818 utf8_printf(p->out, "%s\n", zVfsName);
10819 sqlite3_free(zVfsName);
10820 }
10821 }
10822 }else
10823
drhbf70f1b2022-10-19 18:04:42 +000010824 if( c=='w' && cli_strncmp(azArg[0], "wheretrace", n)==0 ){
drhc0622a42020-12-04 01:17:57 +000010825 unsigned int x = nArg>=2 ? (unsigned int)integerValue(azArg[1]) : 0xffffffff;
10826 sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 3, &x);
drh2ce15c32017-07-11 13:34:40 +000010827 }else
drh2ce15c32017-07-11 13:34:40 +000010828
drhbf70f1b2022-10-19 18:04:42 +000010829 if( c=='w' && cli_strncmp(azArg[0], "width", n)==0 ){
drh2ce15c32017-07-11 13:34:40 +000010830 int j;
10831 assert( nArg<=ArraySize(azArg) );
drh0285d982020-05-29 14:38:43 +000010832 p->nWidth = nArg-1;
drh76fc88f2021-10-02 16:39:16 +000010833 p->colWidth = realloc(p->colWidth, (p->nWidth+1)*sizeof(int)*2);
drh0285d982020-05-29 14:38:43 +000010834 if( p->colWidth==0 && p->nWidth>0 ) shell_out_of_memory();
10835 if( p->nWidth ) p->actualWidth = &p->colWidth[p->nWidth];
10836 for(j=1; j<nArg; j++){
drh2ce15c32017-07-11 13:34:40 +000010837 p->colWidth[j-1] = (int)integerValue(azArg[j]);
10838 }
10839 }else
10840
10841 {
10842 utf8_printf(stderr, "Error: unknown command or invalid arguments: "
10843 " \"%s\". Enter \".help\" for help\n", azArg[0]);
10844 rc = 1;
10845 }
10846
10847meta_command_exit:
10848 if( p->outCount ){
10849 p->outCount--;
10850 if( p->outCount==0 ) output_reset(p);
10851 }
drhb97e2ad2021-08-26 18:31:39 +000010852 p->bSafeMode = p->bSafeModePersist;
drh2ce15c32017-07-11 13:34:40 +000010853 return rc;
10854}
10855
larrybr8bc4cbc2021-09-10 00:58:46 +000010856/* Line scan result and intermediate states (supporting scan resumption)
drh2ce15c32017-07-11 13:34:40 +000010857*/
drh68911c22021-09-22 14:26:22 +000010858#ifndef CHAR_BIT
10859# define CHAR_BIT 8
10860#endif
larrybr8bc4cbc2021-09-10 00:58:46 +000010861typedef enum {
larrybr7e009842021-09-18 21:35:22 +000010862 QSS_HasDark = 1<<CHAR_BIT, QSS_EndingSemi = 2<<CHAR_BIT,
10863 QSS_CharMask = (1<<CHAR_BIT)-1, QSS_ScanMask = 3<<CHAR_BIT,
larrybra96bbe92021-09-10 19:45:22 +000010864 QSS_Start = 0
larrybr8bc4cbc2021-09-10 00:58:46 +000010865} QuickScanState;
larrybr7e009842021-09-18 21:35:22 +000010866#define QSS_SETV(qss, newst) ((newst) | ((qss) & QSS_ScanMask))
10867#define QSS_INPLAIN(qss) (((qss)&QSS_CharMask)==QSS_Start)
10868#define QSS_PLAINWHITE(qss) (((qss)&~QSS_EndingSemi)==QSS_Start)
larrybra96bbe92021-09-10 19:45:22 +000010869#define QSS_PLAINDARK(qss) (((qss)&~QSS_EndingSemi)==QSS_HasDark)
larrybr7e009842021-09-18 21:35:22 +000010870#define QSS_SEMITERM(qss) (((qss)&~QSS_HasDark)==QSS_EndingSemi)
drh2ce15c32017-07-11 13:34:40 +000010871
10872/*
larrybr8bc4cbc2021-09-10 00:58:46 +000010873** Scan line for classification to guide shell's handling.
10874** The scan is resumable for subsequent lines when prior
10875** return values are passed as the 2nd argument.
drh2ce15c32017-07-11 13:34:40 +000010876*/
larrybr8bc4cbc2021-09-10 00:58:46 +000010877static QuickScanState quickscan(char *zLine, QuickScanState qss){
10878 char cin;
larrybr7e009842021-09-18 21:35:22 +000010879 char cWait = (char)qss; /* intentional narrowing loss */
10880 if( cWait==0 ){
10881 PlainScan:
drhe85e1da2021-10-01 21:01:07 +000010882 assert( cWait==0 );
drhfd7abcd2021-09-22 13:43:16 +000010883 while( (cin = *zLine++)!=0 ){
larrybr8bc4cbc2021-09-10 00:58:46 +000010884 if( IsSpace(cin) )
10885 continue;
10886 switch (cin){
10887 case '-':
larrybr7e009842021-09-18 21:35:22 +000010888 if( *zLine!='-' )
10889 break;
10890 while((cin = *++zLine)!=0 )
10891 if( cin=='\n')
10892 goto PlainScan;
10893 return qss;
larrybr8bc4cbc2021-09-10 00:58:46 +000010894 case ';':
larrybra96bbe92021-09-10 19:45:22 +000010895 qss |= QSS_EndingSemi;
10896 continue;
larrybr8bc4cbc2021-09-10 00:58:46 +000010897 case '/':
10898 if( *zLine=='*' ){
10899 ++zLine;
larrybr7e009842021-09-18 21:35:22 +000010900 cWait = '*';
10901 qss = QSS_SETV(qss, cWait);
10902 goto TermScan;
larrybr8bc4cbc2021-09-10 00:58:46 +000010903 }
10904 break;
larrybra96bbe92021-09-10 19:45:22 +000010905 case '[':
10906 cin = ']';
10907 /* fall thru */
10908 case '`': case '\'': case '"':
larrybr7e009842021-09-18 21:35:22 +000010909 cWait = cin;
10910 qss = QSS_HasDark | cWait;
10911 goto TermScan;
larrybr8bc4cbc2021-09-10 00:58:46 +000010912 default:
10913 break;
10914 }
larrybr7e009842021-09-18 21:35:22 +000010915 qss = (qss & ~QSS_EndingSemi) | QSS_HasDark;
drh2ce15c32017-07-11 13:34:40 +000010916 }
larrybr7e009842021-09-18 21:35:22 +000010917 }else{
10918 TermScan:
drhfd7abcd2021-09-22 13:43:16 +000010919 while( (cin = *zLine++)!=0 ){
larrybr7e009842021-09-18 21:35:22 +000010920 if( cin==cWait ){
10921 switch( cWait ){
10922 case '*':
10923 if( *zLine != '/' )
10924 continue;
10925 ++zLine;
10926 cWait = 0;
10927 qss = QSS_SETV(qss, 0);
10928 goto PlainScan;
10929 case '`': case '\'': case '"':
10930 if(*zLine==cWait){
larrybr8d463ce2021-09-11 02:42:04 +000010931 ++zLine;
larrybr7e009842021-09-18 21:35:22 +000010932 continue;
10933 }
10934 /* fall thru */
10935 case ']':
10936 cWait = 0;
10937 qss = QSS_SETV(qss, 0);
10938 goto PlainScan;
larrybr527c39d2022-05-10 14:55:45 +000010939 default: assert(0);
larrybr8bc4cbc2021-09-10 00:58:46 +000010940 }
10941 }
10942 }
drh2ce15c32017-07-11 13:34:40 +000010943 }
larrybr8bc4cbc2021-09-10 00:58:46 +000010944 return qss;
drh2ce15c32017-07-11 13:34:40 +000010945}
10946
10947/*
10948** Return TRUE if the line typed in is an SQL command terminator other
10949** than a semi-colon. The SQL Server style "go" command is understood
10950** as is the Oracle "/".
10951*/
larrybr8bc4cbc2021-09-10 00:58:46 +000010952static int line_is_command_terminator(char *zLine){
drh2ce15c32017-07-11 13:34:40 +000010953 while( IsSpace(zLine[0]) ){ zLine++; };
larrybr8bc4cbc2021-09-10 00:58:46 +000010954 if( zLine[0]=='/' )
10955 zLine += 1; /* Oracle */
10956 else if ( ToLower(zLine[0])=='g' && ToLower(zLine[1])=='o' )
10957 zLine += 2; /* SQL Server */
10958 else
10959 return 0;
larrybr527c39d2022-05-10 14:55:45 +000010960 return quickscan(zLine, QSS_Start)==QSS_Start;
drh2ce15c32017-07-11 13:34:40 +000010961}
10962
10963/*
drh841c98e2022-11-17 01:24:06 +000010964** The CLI needs a working sqlite3_complete() to work properly. So error
10965** out of the build if compiling with SQLITE_OMIT_COMPLETE.
drh56f17742018-01-24 01:58:49 +000010966*/
10967#ifdef SQLITE_OMIT_COMPLETE
drh841c98e2022-11-17 01:24:06 +000010968# error the CLI application is imcompatable with SQLITE_OMIT_COMPLETE.
drh56f17742018-01-24 01:58:49 +000010969#endif
10970
10971/*
drh2ce15c32017-07-11 13:34:40 +000010972** Return true if zSql is a complete SQL statement. Return false if it
10973** ends in the middle of a string literal or C-style comment.
10974*/
10975static int line_is_complete(char *zSql, int nSql){
10976 int rc;
10977 if( zSql==0 ) return 1;
10978 zSql[nSql] = ';';
10979 zSql[nSql+1] = 0;
10980 rc = sqlite3_complete(zSql);
10981 zSql[nSql] = 0;
10982 return rc;
10983}
10984
10985/*
drhfc29a862018-05-11 19:11:18 +000010986** Run a single line of SQL. Return the number of errors.
drh2ce15c32017-07-11 13:34:40 +000010987*/
10988static int runOneSqlLine(ShellState *p, char *zSql, FILE *in, int startline){
10989 int rc;
10990 char *zErrMsg = 0;
10991
10992 open_db(p, 0);
10993 if( ShellHasFlag(p,SHFLG_Backslash) ) resolve_backslashes(zSql);
drhfc4eeef2019-02-05 19:48:46 +000010994 if( p->flgProgress & SHELL_PROGRESS_RESET ) p->nProgress = 0;
drh2ce15c32017-07-11 13:34:40 +000010995 BEGIN_TIMER;
drha10b9992018-03-09 15:24:33 +000010996 rc = shell_exec(p, zSql, &zErrMsg);
drh2ce15c32017-07-11 13:34:40 +000010997 END_TIMER;
10998 if( rc || zErrMsg ){
10999 char zPrefix[100];
drh3e46db22022-02-08 11:52:45 +000011000 const char *zErrorTail;
11001 const char *zErrorType;
11002 if( zErrMsg==0 ){
11003 zErrorType = "Error";
11004 zErrorTail = sqlite3_errmsg(p->db);
drhbf70f1b2022-10-19 18:04:42 +000011005 }else if( cli_strncmp(zErrMsg, "in prepare, ",12)==0 ){
drh3e46db22022-02-08 11:52:45 +000011006 zErrorType = "Parse error";
11007 zErrorTail = &zErrMsg[12];
drhbf70f1b2022-10-19 18:04:42 +000011008 }else if( cli_strncmp(zErrMsg, "stepping, ", 10)==0 ){
drh3e46db22022-02-08 11:52:45 +000011009 zErrorType = "Runtime error";
11010 zErrorTail = &zErrMsg[10];
11011 }else{
11012 zErrorType = "Error";
11013 zErrorTail = zErrMsg;
11014 }
drh2ce15c32017-07-11 13:34:40 +000011015 if( in!=0 || !stdin_is_interactive ){
11016 sqlite3_snprintf(sizeof(zPrefix), zPrefix,
drh3e46db22022-02-08 11:52:45 +000011017 "%s near line %d:", zErrorType, startline);
drh2ce15c32017-07-11 13:34:40 +000011018 }else{
drh3e46db22022-02-08 11:52:45 +000011019 sqlite3_snprintf(sizeof(zPrefix), zPrefix, "%s:", zErrorType);
drh2ce15c32017-07-11 13:34:40 +000011020 }
drh3e46db22022-02-08 11:52:45 +000011021 utf8_printf(stderr, "%s %s\n", zPrefix, zErrorTail);
11022 sqlite3_free(zErrMsg);
11023 zErrMsg = 0;
drh2ce15c32017-07-11 13:34:40 +000011024 return 1;
11025 }else if( ShellHasFlag(p, SHFLG_CountChanges) ){
drh6d9f0342021-09-22 10:28:50 +000011026 char zLineBuf[2000];
11027 sqlite3_snprintf(sizeof(zLineBuf), zLineBuf,
11028 "changes: %lld total_changes: %lld",
larrybr10496f72021-06-23 16:07:20 +000011029 sqlite3_changes64(p->db), sqlite3_total_changes64(p->db));
drh6d9f0342021-09-22 10:28:50 +000011030 raw_printf(p->out, "%s\n", zLineBuf);
drh2ce15c32017-07-11 13:34:40 +000011031 }
11032 return 0;
11033}
11034
larrybrf4874812022-05-11 19:59:31 +000011035static void echo_group_input(ShellState *p, const char *zDo){
11036 if( ShellHasFlag(p, SHFLG_Echo) ) utf8_printf(p->out, "%s\n", zDo);
11037}
drh2ce15c32017-07-11 13:34:40 +000011038
stephan4413ec72022-07-12 15:53:02 +000011039#ifdef SQLITE_SHELL_FIDDLE
stephanf8cd3d22022-05-18 17:14:24 +000011040/*
11041** Alternate one_input_line() impl for wasm mode. This is not in the primary impl
11042** because we need the global shellState and cannot access it from that function
11043** without moving lots of code around (creating a larger/messier diff).
11044*/
11045static char *one_input_line(FILE *in, char *zPrior, int isContinuation){
11046 /* Parse the next line from shellState.wasm.zInput. */
11047 const char *zBegin = shellState.wasm.zPos;
11048 const char *z = zBegin;
11049 char *zLine = 0;
drh7d23d152022-10-11 12:02:42 +000011050 i64 nZ = 0;
stephanf8cd3d22022-05-18 17:14:24 +000011051
11052 UNUSED_PARAMETER(in);
11053 UNUSED_PARAMETER(isContinuation);
11054 if(!z || !*z){
11055 return 0;
11056 }
11057 while(*z && isspace(*z)) ++z;
11058 zBegin = z;
11059 for(; *z && '\n'!=*z; ++nZ, ++z){}
11060 if(nZ>0 && '\r'==zBegin[nZ-1]){
11061 --nZ;
11062 }
11063 shellState.wasm.zPos = z;
11064 zLine = realloc(zPrior, nZ+1);
11065 shell_check_oom(zLine);
drh7d23d152022-10-11 12:02:42 +000011066 memcpy(zLine, zBegin, nZ);
stephanf8cd3d22022-05-18 17:14:24 +000011067 zLine[nZ] = 0;
11068 return zLine;
11069}
stephan4413ec72022-07-12 15:53:02 +000011070#endif /* SQLITE_SHELL_FIDDLE */
stephanf8cd3d22022-05-18 17:14:24 +000011071
drh2ce15c32017-07-11 13:34:40 +000011072/*
11073** Read input from *in and process it. If *in==0 then input
11074** is interactive - the user is typing it it. Otherwise, input
11075** is coming from a file or device. A prompt is issued and history
11076** is saved only if input is interactive. An interrupt signal will
11077** cause this routine to exit immediately, unless input is interactive.
11078**
11079** Return the number of errors.
11080*/
drh60379d42018-12-13 18:30:01 +000011081static int process_input(ShellState *p){
drh2ce15c32017-07-11 13:34:40 +000011082 char *zLine = 0; /* A single input line */
11083 char *zSql = 0; /* Accumulated SQL text */
drh7d23d152022-10-11 12:02:42 +000011084 i64 nLine; /* Length of current line */
11085 i64 nSql = 0; /* Bytes of zSql[] used */
11086 i64 nAlloc = 0; /* Allocated zSql[] space */
drh2ce15c32017-07-11 13:34:40 +000011087 int rc; /* Error code */
11088 int errCnt = 0; /* Number of errors seen */
drh7d23d152022-10-11 12:02:42 +000011089 i64 startline = 0; /* Line number for start of current input */
larrybr7e009842021-09-18 21:35:22 +000011090 QuickScanState qss = QSS_Start; /* Accumulated line status (so far) */
drh2ce15c32017-07-11 13:34:40 +000011091
larrybrd48e88e2022-01-24 06:36:16 +000011092 if( p->inputNesting==MAX_INPUT_NESTING ){
11093 /* This will be more informative in a later version. */
11094 utf8_printf(stderr,"Input nesting limit (%d) reached at line %d."
11095 " Check recursion.\n", MAX_INPUT_NESTING, p->lineno);
11096 return 1;
11097 }
11098 ++p->inputNesting;
drh2c8ee022018-12-13 18:59:30 +000011099 p->lineno = 0;
drh60379d42018-12-13 18:30:01 +000011100 while( errCnt==0 || !bail_on_error || (p->in==0 && stdin_is_interactive) ){
drh2ce15c32017-07-11 13:34:40 +000011101 fflush(p->out);
drh60379d42018-12-13 18:30:01 +000011102 zLine = one_input_line(p->in, zLine, nSql>0);
drh2ce15c32017-07-11 13:34:40 +000011103 if( zLine==0 ){
11104 /* End of input */
drh60379d42018-12-13 18:30:01 +000011105 if( p->in==0 && stdin_is_interactive ) printf("\n");
drh2ce15c32017-07-11 13:34:40 +000011106 break;
11107 }
11108 if( seenInterrupt ){
drh60379d42018-12-13 18:30:01 +000011109 if( p->in!=0 ) break;
drh2ce15c32017-07-11 13:34:40 +000011110 seenInterrupt = 0;
11111 }
drh2c8ee022018-12-13 18:59:30 +000011112 p->lineno++;
larrybr7e009842021-09-18 21:35:22 +000011113 if( QSS_INPLAIN(qss)
larrybr8bc4cbc2021-09-10 00:58:46 +000011114 && line_is_command_terminator(zLine)
11115 && line_is_complete(zSql, nSql) ){
11116 memcpy(zLine,";",2);
11117 }
11118 qss = quickscan(zLine, qss);
11119 if( QSS_PLAINWHITE(qss) && nSql==0 ){
larrybrd797d6b2021-10-03 22:03:59 +000011120 /* Just swallow single-line whitespace */
larrybrf4874812022-05-11 19:59:31 +000011121 echo_group_input(p, zLine);
larrybrd797d6b2021-10-03 22:03:59 +000011122 qss = QSS_Start;
larrybr8bc4cbc2021-09-10 00:58:46 +000011123 continue;
drh2ce15c32017-07-11 13:34:40 +000011124 }
drh1615c372018-05-12 23:56:22 +000011125 if( zLine && (zLine[0]=='.' || zLine[0]=='#') && nSql==0 ){
larrybrf4874812022-05-11 19:59:31 +000011126 echo_group_input(p, zLine);
drh1615c372018-05-12 23:56:22 +000011127 if( zLine[0]=='.' ){
11128 rc = do_meta_command(zLine, p);
11129 if( rc==2 ){ /* exit requested */
11130 break;
11131 }else if( rc ){
11132 errCnt++;
11133 }
drh2ce15c32017-07-11 13:34:40 +000011134 }
larrybr81012162021-10-02 15:34:52 +000011135 qss = QSS_Start;
drh2ce15c32017-07-11 13:34:40 +000011136 continue;
11137 }
larrybrd797d6b2021-10-03 22:03:59 +000011138 /* No single-line dispositions remain; accumulate line(s). */
drh7d23d152022-10-11 12:02:42 +000011139 nLine = strlen(zLine);
drh2ce15c32017-07-11 13:34:40 +000011140 if( nSql+nLine+2>=nAlloc ){
larrybr31bffb42021-09-08 21:49:03 +000011141 /* Grow buffer by half-again increments when big. */
11142 nAlloc = nSql+(nSql>>1)+nLine+100;
drh2ce15c32017-07-11 13:34:40 +000011143 zSql = realloc(zSql, nAlloc);
drhe3e25652021-12-16 13:29:28 +000011144 shell_check_oom(zSql);
drh2ce15c32017-07-11 13:34:40 +000011145 }
drh2ce15c32017-07-11 13:34:40 +000011146 if( nSql==0 ){
drh7d23d152022-10-11 12:02:42 +000011147 i64 i;
drh2ce15c32017-07-11 13:34:40 +000011148 for(i=0; zLine[i] && IsSpace(zLine[i]); i++){}
11149 assert( nAlloc>0 && zSql!=0 );
11150 memcpy(zSql, zLine+i, nLine+1-i);
drh2c8ee022018-12-13 18:59:30 +000011151 startline = p->lineno;
drh2ce15c32017-07-11 13:34:40 +000011152 nSql = nLine-i;
11153 }else{
11154 zSql[nSql++] = '\n';
11155 memcpy(zSql+nSql, zLine, nLine+1);
11156 nSql += nLine;
11157 }
larrybra96bbe92021-09-10 19:45:22 +000011158 if( nSql && QSS_SEMITERM(qss) && sqlite3_complete(zSql) ){
larrybrf4874812022-05-11 19:59:31 +000011159 echo_group_input(p, zSql);
drh60379d42018-12-13 18:30:01 +000011160 errCnt += runOneSqlLine(p, zSql, p->in, startline);
drh2ce15c32017-07-11 13:34:40 +000011161 nSql = 0;
11162 if( p->outCount ){
11163 output_reset(p);
11164 p->outCount = 0;
drh13c20932018-01-10 21:41:55 +000011165 }else{
11166 clearTempFile(p);
drh2ce15c32017-07-11 13:34:40 +000011167 }
drhb97e2ad2021-08-26 18:31:39 +000011168 p->bSafeMode = p->bSafeModePersist;
larrybrd797d6b2021-10-03 22:03:59 +000011169 qss = QSS_Start;
larrybr8bc4cbc2021-09-10 00:58:46 +000011170 }else if( nSql && QSS_PLAINWHITE(qss) ){
larrybrf4874812022-05-11 19:59:31 +000011171 echo_group_input(p, zSql);
drh2ce15c32017-07-11 13:34:40 +000011172 nSql = 0;
larrybrd797d6b2021-10-03 22:03:59 +000011173 qss = QSS_Start;
drh2ce15c32017-07-11 13:34:40 +000011174 }
11175 }
larrybrc6e2f2e2022-03-15 17:57:42 +000011176 if( nSql ){
11177 /* This may be incomplete. Let the SQL parser deal with that. */
larrybrf4874812022-05-11 19:59:31 +000011178 echo_group_input(p, zSql);
drh60379d42018-12-13 18:30:01 +000011179 errCnt += runOneSqlLine(p, zSql, p->in, startline);
drh2ce15c32017-07-11 13:34:40 +000011180 }
11181 free(zSql);
11182 free(zLine);
larrybrd48e88e2022-01-24 06:36:16 +000011183 --p->inputNesting;
drh2ce15c32017-07-11 13:34:40 +000011184 return errCnt>0;
11185}
11186
11187/*
11188** Return a pathname which is the user's home directory. A
11189** 0 return indicates an error of some kind.
11190*/
11191static char *find_home_dir(int clearFlag){
11192 static char *home_dir = NULL;
11193 if( clearFlag ){
11194 free(home_dir);
11195 home_dir = 0;
11196 return 0;
11197 }
11198 if( home_dir ) return home_dir;
11199
11200#if !defined(_WIN32) && !defined(WIN32) && !defined(_WIN32_WCE) \
11201 && !defined(__RTP__) && !defined(_WRS_KERNEL)
11202 {
11203 struct passwd *pwent;
11204 uid_t uid = getuid();
11205 if( (pwent=getpwuid(uid)) != NULL) {
11206 home_dir = pwent->pw_dir;
11207 }
11208 }
11209#endif
11210
11211#if defined(_WIN32_WCE)
11212 /* Windows CE (arm-wince-mingw32ce-gcc) does not provide getenv()
11213 */
11214 home_dir = "/";
11215#else
11216
11217#if defined(_WIN32) || defined(WIN32)
11218 if (!home_dir) {
11219 home_dir = getenv("USERPROFILE");
11220 }
11221#endif
11222
11223 if (!home_dir) {
11224 home_dir = getenv("HOME");
11225 }
11226
11227#if defined(_WIN32) || defined(WIN32)
11228 if (!home_dir) {
11229 char *zDrive, *zPath;
11230 int n;
11231 zDrive = getenv("HOMEDRIVE");
11232 zPath = getenv("HOMEPATH");
11233 if( zDrive && zPath ){
11234 n = strlen30(zDrive) + strlen30(zPath) + 1;
11235 home_dir = malloc( n );
11236 if( home_dir==0 ) return 0;
11237 sqlite3_snprintf(n, home_dir, "%s%s", zDrive, zPath);
11238 return home_dir;
11239 }
11240 home_dir = "c:\\";
11241 }
11242#endif
11243
11244#endif /* !_WIN32_WCE */
11245
11246 if( home_dir ){
drh7d23d152022-10-11 12:02:42 +000011247 i64 n = strlen(home_dir) + 1;
drh2ce15c32017-07-11 13:34:40 +000011248 char *z = malloc( n );
11249 if( z ) memcpy(z, home_dir, n);
11250 home_dir = z;
11251 }
11252
11253 return home_dir;
11254}
11255
11256/*
stephan6e8a3342022-11-06 13:12:11 +000011257** On non-Windows platforms, look for $XDG_CONFIG_HOME.
11258** If ${XDG_CONFIG_HOME}/sqlite3/sqliterc is found, return
11259** the path to it, else return 0. The result is cached for
11260** subsequent calls.
11261*/
11262static const char *find_xdg_config(void){
11263#if defined(_WIN32) || defined(WIN32) || defined(_WIN32_WCE) \
11264 || defined(__RTP__) || defined(_WRS_KERNEL)
11265 return 0;
11266#else
11267 static int alreadyTried = 0;
11268 static char *zConfig = 0;
11269 const char *zXdgHome;
11270
11271 if( alreadyTried!=0 ){
11272 return zConfig;
11273 }
11274 alreadyTried = 1;
11275 zXdgHome = getenv("XDG_CONFIG_HOME");
11276 if( zXdgHome==0 ){
11277 return 0;
11278 }
11279 zConfig = sqlite3_mprintf("%s/sqlite3/sqliterc", zXdgHome);
11280 shell_check_oom(zConfig);
11281 if( access(zConfig,0)!=0 ){
11282 sqlite3_free(zConfig);
11283 zConfig = 0;
11284 }
11285 return zConfig;
11286#endif
11287}
11288
11289/*
drh2ce15c32017-07-11 13:34:40 +000011290** Read input from the file given by sqliterc_override. Or if that
stephan6e8a3342022-11-06 13:12:11 +000011291** parameter is NULL, take input from the first of find_xdg_config()
11292** or ~/.sqliterc which is found.
drh2ce15c32017-07-11 13:34:40 +000011293**
11294** Returns the number of errors.
11295*/
11296static void process_sqliterc(
11297 ShellState *p, /* Configuration data */
11298 const char *sqliterc_override /* Name of config file. NULL to use default */
11299){
11300 char *home_dir = NULL;
11301 const char *sqliterc = sqliterc_override;
11302 char *zBuf = 0;
drh60379d42018-12-13 18:30:01 +000011303 FILE *inSaved = p->in;
drh2c8ee022018-12-13 18:59:30 +000011304 int savedLineno = p->lineno;
drh2ce15c32017-07-11 13:34:40 +000011305
stephan6e8a3342022-11-06 13:12:11 +000011306 if( sqliterc == NULL ){
11307 sqliterc = find_xdg_config();
11308 }
11309 if( sqliterc == NULL ){
drh2ce15c32017-07-11 13:34:40 +000011310 home_dir = find_home_dir(0);
11311 if( home_dir==0 ){
11312 raw_printf(stderr, "-- warning: cannot find home directory;"
11313 " cannot read ~/.sqliterc\n");
11314 return;
11315 }
drh2ce15c32017-07-11 13:34:40 +000011316 zBuf = sqlite3_mprintf("%s/.sqliterc",home_dir);
drhe3e25652021-12-16 13:29:28 +000011317 shell_check_oom(zBuf);
drh2ce15c32017-07-11 13:34:40 +000011318 sqliterc = zBuf;
11319 }
drh60379d42018-12-13 18:30:01 +000011320 p->in = fopen(sqliterc,"rb");
11321 if( p->in ){
drh2ce15c32017-07-11 13:34:40 +000011322 if( stdin_is_interactive ){
11323 utf8_printf(stderr,"-- Loading resources from %s\n",sqliterc);
11324 }
drhb7c46aa2020-11-25 13:59:47 +000011325 if( process_input(p) && bail_on_error ) exit(1);
drh60379d42018-12-13 18:30:01 +000011326 fclose(p->in);
drhb7c46aa2020-11-25 13:59:47 +000011327 }else if( sqliterc_override!=0 ){
11328 utf8_printf(stderr,"cannot open: \"%s\"\n", sqliterc);
11329 if( bail_on_error ) exit(1);
drh2ce15c32017-07-11 13:34:40 +000011330 }
drh60379d42018-12-13 18:30:01 +000011331 p->in = inSaved;
drh2c8ee022018-12-13 18:59:30 +000011332 p->lineno = savedLineno;
drh2ce15c32017-07-11 13:34:40 +000011333 sqlite3_free(zBuf);
11334}
11335
11336/*
11337** Show available command line options
11338*/
11339static const char zOptions[] =
drhda57d962018-03-05 19:34:05 +000011340#if defined(SQLITE_HAVE_ZLIB) && !defined(SQLITE_OMIT_VIRTUALTABLE)
drhad7fd5d2018-03-05 20:21:50 +000011341 " -A ARGS... run \".archive ARGS\" and exit\n"
drhda57d962018-03-05 19:34:05 +000011342#endif
drh3baed312018-03-08 18:14:41 +000011343 " -append append the database to the end of the file\n"
drh2ce15c32017-07-11 13:34:40 +000011344 " -ascii set output mode to 'ascii'\n"
11345 " -bail stop after hitting an error\n"
11346 " -batch force batch I/O\n"
drh0908e382020-06-04 18:05:39 +000011347 " -box set output mode to 'box'\n"
drh2ce15c32017-07-11 13:34:40 +000011348 " -column set output mode to 'column'\n"
11349 " -cmd COMMAND run \"COMMAND\" before reading stdin\n"
11350 " -csv set output mode to 'csv'\n"
drh8d889af2021-05-08 17:18:23 +000011351#if !defined(SQLITE_OMIT_DESERIALIZE)
drh6ca64482019-01-22 16:06:20 +000011352 " -deserialize open the database using sqlite3_deserialize()\n"
11353#endif
larrybr527c39d2022-05-10 14:55:45 +000011354 " -echo print inputs before execution\n"
drh2ce15c32017-07-11 13:34:40 +000011355 " -init FILENAME read/process named file\n"
11356 " -[no]header turn headers on or off\n"
11357#if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5)
11358 " -heap SIZE Size of heap for memsys3 or memsys5\n"
11359#endif
11360 " -help show this message\n"
11361 " -html set output mode to HTML\n"
11362 " -interactive force interactive I/O\n"
drh30c54a02020-05-28 23:49:50 +000011363 " -json set output mode to 'json'\n"
drh2ce15c32017-07-11 13:34:40 +000011364 " -line set output mode to 'line'\n"
11365 " -list set output mode to 'list'\n"
11366 " -lookaside SIZE N use N entries of SZ bytes for lookaside memory\n"
drh30c54a02020-05-28 23:49:50 +000011367 " -markdown set output mode to 'markdown'\n"
drh8d889af2021-05-08 17:18:23 +000011368#if !defined(SQLITE_OMIT_DESERIALIZE)
drh6ca64482019-01-22 16:06:20 +000011369 " -maxsize N maximum size for a --deserialize database\n"
11370#endif
drhaf482572019-02-04 19:52:39 +000011371 " -memtrace trace all memory allocations and deallocations\n"
drh2ce15c32017-07-11 13:34:40 +000011372 " -mmap N default mmap size set to N\n"
11373#ifdef SQLITE_ENABLE_MULTIPLEX
11374 " -multiplex enable the multiplexor VFS\n"
11375#endif
11376 " -newline SEP set output row separator. Default: '\\n'\n"
drh0933aad2019-11-18 17:46:38 +000011377 " -nofollow refuse to open symbolic links to database files\n"
drhb97e2ad2021-08-26 18:31:39 +000011378 " -nonce STRING set the safe-mode escape nonce\n"
drh2ce15c32017-07-11 13:34:40 +000011379 " -nullvalue TEXT set text string for NULL values. Default ''\n"
11380 " -pagecache SIZE N use N slots of SZ bytes each for page cache memory\n"
11381 " -quote set output mode to 'quote'\n"
drhee269a62018-02-14 23:27:43 +000011382 " -readonly open the database read-only\n"
drhb97e2ad2021-08-26 18:31:39 +000011383 " -safe enable safe-mode\n"
drh2ce15c32017-07-11 13:34:40 +000011384 " -separator SEP set output column separator. Default: '|'\n"
drha90d84f2018-04-18 15:21:13 +000011385#ifdef SQLITE_ENABLE_SORTER_REFERENCES
11386 " -sorterref SIZE sorter references threshold size\n"
11387#endif
drh2ce15c32017-07-11 13:34:40 +000011388 " -stats print memory stats before each finalize\n"
drh30c54a02020-05-28 23:49:50 +000011389 " -table set output mode to 'table'\n"
drh2fa78182020-10-31 18:58:37 +000011390 " -tabs set output mode to 'tabs'\n"
drh2ce15c32017-07-11 13:34:40 +000011391 " -version show SQLite version\n"
11392 " -vfs NAME use NAME as the default VFS\n"
11393#ifdef SQLITE_ENABLE_VFSTRACE
11394 " -vfstrace enable tracing of all VFS calls\n"
11395#endif
drh3baed312018-03-08 18:14:41 +000011396#ifdef SQLITE_HAVE_ZLIB
11397 " -zip open the file as a ZIP Archive\n"
11398#endif
drh2ce15c32017-07-11 13:34:40 +000011399;
11400static void usage(int showDetail){
11401 utf8_printf(stderr,
11402 "Usage: %s [OPTIONS] FILENAME [SQL]\n"
11403 "FILENAME is the name of an SQLite database. A new database is created\n"
11404 "if the file does not previously exist.\n", Argv0);
11405 if( showDetail ){
11406 utf8_printf(stderr, "OPTIONS include:\n%s", zOptions);
11407 }else{
11408 raw_printf(stderr, "Use the -help option for additional information\n");
11409 }
11410 exit(1);
11411}
11412
11413/*
drhe7df8922018-04-18 10:44:58 +000011414** Internal check: Verify that the SQLite is uninitialized. Print a
11415** error message if it is initialized.
11416*/
11417static void verify_uninitialized(void){
11418 if( sqlite3_config(-1)==SQLITE_MISUSE ){
drh8e02a182018-05-30 07:24:41 +000011419 utf8_printf(stdout, "WARNING: attempt to configure SQLite after"
drhe7df8922018-04-18 10:44:58 +000011420 " initialization.\n");
11421 }
11422}
11423
11424/*
drh2ce15c32017-07-11 13:34:40 +000011425** Initialize the state information in data
11426*/
11427static void main_init(ShellState *data) {
11428 memset(data, 0, sizeof(*data));
11429 data->normalMode = data->cMode = data->mode = MODE_List;
11430 data->autoExplain = 1;
drh37407122021-07-23 18:43:58 +000011431 data->pAuxDb = &data->aAuxDb[0];
drh2ce15c32017-07-11 13:34:40 +000011432 memcpy(data->colSeparator,SEP_Column, 2);
11433 memcpy(data->rowSeparator,SEP_Row, 2);
11434 data->showHeader = 0;
11435 data->shellFlgs = SHFLG_Lookaside;
drhe7df8922018-04-18 10:44:58 +000011436 verify_uninitialized();
drh2ce15c32017-07-11 13:34:40 +000011437 sqlite3_config(SQLITE_CONFIG_URI, 1);
11438 sqlite3_config(SQLITE_CONFIG_LOG, shellLog, data);
11439 sqlite3_config(SQLITE_CONFIG_MULTITHREAD);
11440 sqlite3_snprintf(sizeof(mainPrompt), mainPrompt,"sqlite> ");
11441 sqlite3_snprintf(sizeof(continuePrompt), continuePrompt," ...> ");
11442}
11443
11444/*
11445** Output text to the console in a font that attracts extra attention.
11446*/
11447#ifdef _WIN32
11448static void printBold(const char *zText){
mistachkin43e86272020-04-09 15:31:22 +000011449#if !SQLITE_OS_WINRT
drh2ce15c32017-07-11 13:34:40 +000011450 HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE);
11451 CONSOLE_SCREEN_BUFFER_INFO defaultScreenInfo;
11452 GetConsoleScreenBufferInfo(out, &defaultScreenInfo);
11453 SetConsoleTextAttribute(out,
11454 FOREGROUND_RED|FOREGROUND_INTENSITY
11455 );
mistachkin43e86272020-04-09 15:31:22 +000011456#endif
drh2ce15c32017-07-11 13:34:40 +000011457 printf("%s", zText);
mistachkin43e86272020-04-09 15:31:22 +000011458#if !SQLITE_OS_WINRT
drh2ce15c32017-07-11 13:34:40 +000011459 SetConsoleTextAttribute(out, defaultScreenInfo.wAttributes);
mistachkin43e86272020-04-09 15:31:22 +000011460#endif
drh2ce15c32017-07-11 13:34:40 +000011461}
11462#else
11463static void printBold(const char *zText){
11464 printf("\033[1m%s\033[0m", zText);
11465}
11466#endif
11467
11468/*
11469** Get the argument to an --option. Throw an error and die if no argument
11470** is available.
11471*/
11472static char *cmdline_option_value(int argc, char **argv, int i){
11473 if( i==argc ){
11474 utf8_printf(stderr, "%s: Error: missing argument to %s\n",
11475 argv[0], argv[argc-1]);
11476 exit(1);
11477 }
11478 return argv[i];
11479}
11480
11481#ifndef SQLITE_SHELL_IS_UTF8
dan39b6bd52021-03-04 18:31:07 +000011482# if (defined(_WIN32) || defined(WIN32)) \
11483 && (defined(_MSC_VER) || (defined(UNICODE) && defined(__GNUC__)))
drh2ce15c32017-07-11 13:34:40 +000011484# define SQLITE_SHELL_IS_UTF8 (0)
11485# else
11486# define SQLITE_SHELL_IS_UTF8 (1)
11487# endif
11488#endif
11489
stephan4413ec72022-07-12 15:53:02 +000011490#ifdef SQLITE_SHELL_FIDDLE
stephanf8cd3d22022-05-18 17:14:24 +000011491# define main fiddle_main
11492#endif
11493
drh2ce15c32017-07-11 13:34:40 +000011494#if SQLITE_SHELL_IS_UTF8
11495int SQLITE_CDECL main(int argc, char **argv){
11496#else
11497int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
11498 char **argv;
11499#endif
larrybrfa5dfa82022-05-07 03:53:14 +000011500#ifdef SQLITE_DEBUG
mistachkin07fae322022-07-06 23:50:01 +000011501 sqlite3_int64 mem_main_enter = sqlite3_memory_used();
larrybrfa5dfa82022-05-07 03:53:14 +000011502#endif
drh2ce15c32017-07-11 13:34:40 +000011503 char *zErrMsg = 0;
stephan4413ec72022-07-12 15:53:02 +000011504#ifdef SQLITE_SHELL_FIDDLE
stephanf8cd3d22022-05-18 17:14:24 +000011505# define data shellState
11506#else
drh2ce15c32017-07-11 13:34:40 +000011507 ShellState data;
stephanf8cd3d22022-05-18 17:14:24 +000011508#endif
drh2ce15c32017-07-11 13:34:40 +000011509 const char *zInitFile = 0;
11510 int i;
11511 int rc = 0;
11512 int warnInmemoryDb = 0;
11513 int readStdin = 1;
11514 int nCmd = 0;
11515 char **azCmd = 0;
dan16a47422018-04-18 09:16:11 +000011516 const char *zVfs = 0; /* Value of -vfs command-line option */
drh1f22f622018-05-17 13:29:14 +000011517#if !SQLITE_SHELL_IS_UTF8
11518 char **argvToFree = 0;
11519 int argcToFree = 0;
11520#endif
drh2ce15c32017-07-11 13:34:40 +000011521
11522 setBinaryMode(stdin, 0);
11523 setvbuf(stderr, 0, _IONBF, 0); /* Make sure stderr is unbuffered */
stephan4413ec72022-07-12 15:53:02 +000011524#ifdef SQLITE_SHELL_FIDDLE
stephanf8cd3d22022-05-18 17:14:24 +000011525 stdin_is_interactive = 0;
11526 stdout_is_console = 1;
stephan60d9aa72022-09-24 07:36:45 +000011527 data.wasm.zDefaultDbName = "/fiddle.sqlite3";
stephanf8cd3d22022-05-18 17:14:24 +000011528#else
drh2ce15c32017-07-11 13:34:40 +000011529 stdin_is_interactive = isatty(0);
11530 stdout_is_console = isatty(1);
stephanf8cd3d22022-05-18 17:14:24 +000011531#endif
drh2ce15c32017-07-11 13:34:40 +000011532
mistachkin1e8487d2018-07-22 06:25:35 +000011533#if !defined(_WIN32_WCE)
11534 if( getenv("SQLITE_DEBUG_BREAK") ){
11535 if( isatty(0) && isatty(2) ){
11536 fprintf(stderr,
11537 "attach debugger to process %d and press any key to continue.\n",
11538 GETPID());
11539 fgetc(stdin);
11540 }else{
11541#if defined(_WIN32) || defined(WIN32)
mistachkin43e86272020-04-09 15:31:22 +000011542#if SQLITE_OS_WINRT
11543 __debugbreak();
11544#else
mistachkin1e8487d2018-07-22 06:25:35 +000011545 DebugBreak();
mistachkin43e86272020-04-09 15:31:22 +000011546#endif
mistachkin1e8487d2018-07-22 06:25:35 +000011547#elif defined(SIGTRAP)
11548 raise(SIGTRAP);
11549#endif
11550 }
11551 }
11552#endif
11553
drh2ce15c32017-07-11 13:34:40 +000011554#if USE_SYSTEM_SQLITE+0!=1
drhbf70f1b2022-10-19 18:04:42 +000011555 if( cli_strncmp(sqlite3_sourceid(),SQLITE_SOURCE_ID,60)!=0 ){
drh2ce15c32017-07-11 13:34:40 +000011556 utf8_printf(stderr, "SQLite header and source version mismatch\n%s\n%s\n",
11557 sqlite3_sourceid(), SQLITE_SOURCE_ID);
11558 exit(1);
11559 }
11560#endif
11561 main_init(&data);
drh501ea052018-02-15 01:03:37 +000011562
11563 /* On Windows, we must translate command-line arguments into UTF-8.
11564 ** The SQLite memory allocator subsystem has to be enabled in order to
11565 ** do this. But we want to run an sqlite3_shutdown() afterwards so that
11566 ** subsequent sqlite3_config() calls will work. So copy all results into
11567 ** memory that does not come from the SQLite memory allocator.
11568 */
drh4b18c1d2018-02-04 20:33:13 +000011569#if !SQLITE_SHELL_IS_UTF8
drh501ea052018-02-15 01:03:37 +000011570 sqlite3_initialize();
drh1f22f622018-05-17 13:29:14 +000011571 argvToFree = malloc(sizeof(argv[0])*argc*2);
drhe3e25652021-12-16 13:29:28 +000011572 shell_check_oom(argvToFree);
drh1f22f622018-05-17 13:29:14 +000011573 argcToFree = argc;
11574 argv = argvToFree + argc;
drh2ce15c32017-07-11 13:34:40 +000011575 for(i=0; i<argc; i++){
drh501ea052018-02-15 01:03:37 +000011576 char *z = sqlite3_win32_unicode_to_utf8(wargv[i]);
drh7d23d152022-10-11 12:02:42 +000011577 i64 n;
drhe3e25652021-12-16 13:29:28 +000011578 shell_check_oom(z);
drh7d23d152022-10-11 12:02:42 +000011579 n = strlen(z);
drh501ea052018-02-15 01:03:37 +000011580 argv[i] = malloc( n+1 );
drhe3e25652021-12-16 13:29:28 +000011581 shell_check_oom(argv[i]);
drh501ea052018-02-15 01:03:37 +000011582 memcpy(argv[i], z, n+1);
drh1f22f622018-05-17 13:29:14 +000011583 argvToFree[i] = argv[i];
drh501ea052018-02-15 01:03:37 +000011584 sqlite3_free(z);
drh2ce15c32017-07-11 13:34:40 +000011585 }
drh501ea052018-02-15 01:03:37 +000011586 sqlite3_shutdown();
drh2ce15c32017-07-11 13:34:40 +000011587#endif
drh501ea052018-02-15 01:03:37 +000011588
drh2ce15c32017-07-11 13:34:40 +000011589 assert( argc>=1 && argv && argv[0] );
11590 Argv0 = argv[0];
11591
11592 /* Make sure we have a valid signal handler early, before anything
11593 ** else is done.
11594 */
11595#ifdef SIGINT
11596 signal(SIGINT, interrupt_handler);
mistachkinb4bab902017-10-27 17:09:44 +000011597#elif (defined(_WIN32) || defined(WIN32)) && !defined(_WIN32_WCE)
11598 SetConsoleCtrlHandler(ConsoleCtrlHandler, TRUE);
drh2ce15c32017-07-11 13:34:40 +000011599#endif
11600
11601#ifdef SQLITE_SHELL_DBNAME_PROC
11602 {
11603 /* If the SQLITE_SHELL_DBNAME_PROC macro is defined, then it is the name
11604 ** of a C-function that will provide the name of the database file. Use
11605 ** this compile-time option to embed this shell program in larger
11606 ** applications. */
11607 extern void SQLITE_SHELL_DBNAME_PROC(const char**);
drh37407122021-07-23 18:43:58 +000011608 SQLITE_SHELL_DBNAME_PROC(&data.pAuxDb->zDbFilename);
drh2ce15c32017-07-11 13:34:40 +000011609 warnInmemoryDb = 0;
11610 }
11611#endif
11612
11613 /* Do an initial pass through the command-line argument to locate
11614 ** the name of the database file, the name of the initialization file,
11615 ** the size of the alternative malloc heap,
11616 ** and the first command to execute.
11617 */
drhe7df8922018-04-18 10:44:58 +000011618 verify_uninitialized();
drh2ce15c32017-07-11 13:34:40 +000011619 for(i=1; i<argc; i++){
11620 char *z;
11621 z = argv[i];
11622 if( z[0]!='-' ){
drh37407122021-07-23 18:43:58 +000011623 if( data.aAuxDb->zDbFilename==0 ){
11624 data.aAuxDb->zDbFilename = z;
drh2ce15c32017-07-11 13:34:40 +000011625 }else{
11626 /* Excesss arguments are interpreted as SQL (or dot-commands) and
11627 ** mean that nothing is read from stdin */
11628 readStdin = 0;
11629 nCmd++;
11630 azCmd = realloc(azCmd, sizeof(azCmd[0])*nCmd);
drhe3e25652021-12-16 13:29:28 +000011631 shell_check_oom(azCmd);
drh2ce15c32017-07-11 13:34:40 +000011632 azCmd[nCmd-1] = z;
11633 }
11634 }
11635 if( z[1]=='-' ) z++;
drhbf70f1b2022-10-19 18:04:42 +000011636 if( cli_strcmp(z,"-separator")==0
11637 || cli_strcmp(z,"-nullvalue")==0
11638 || cli_strcmp(z,"-newline")==0
11639 || cli_strcmp(z,"-cmd")==0
drh2ce15c32017-07-11 13:34:40 +000011640 ){
11641 (void)cmdline_option_value(argc, argv, ++i);
drhbf70f1b2022-10-19 18:04:42 +000011642 }else if( cli_strcmp(z,"-init")==0 ){
drh2ce15c32017-07-11 13:34:40 +000011643 zInitFile = cmdline_option_value(argc, argv, ++i);
drhbf70f1b2022-10-19 18:04:42 +000011644 }else if( cli_strcmp(z,"-batch")==0 ){
drh2ce15c32017-07-11 13:34:40 +000011645 /* Need to check for batch mode here to so we can avoid printing
11646 ** informational messages (like from process_sqliterc) before
11647 ** we do the actual processing of arguments later in a second pass.
11648 */
11649 stdin_is_interactive = 0;
drhbf70f1b2022-10-19 18:04:42 +000011650 }else if( cli_strcmp(z,"-heap")==0 ){
drh2ce15c32017-07-11 13:34:40 +000011651#if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5)
11652 const char *zSize;
11653 sqlite3_int64 szHeap;
11654
11655 zSize = cmdline_option_value(argc, argv, ++i);
11656 szHeap = integerValue(zSize);
11657 if( szHeap>0x7fff0000 ) szHeap = 0x7fff0000;
11658 sqlite3_config(SQLITE_CONFIG_HEAP, malloc((int)szHeap), (int)szHeap, 64);
11659#else
11660 (void)cmdline_option_value(argc, argv, ++i);
11661#endif
drhbf70f1b2022-10-19 18:04:42 +000011662 }else if( cli_strcmp(z,"-pagecache")==0 ){
drhf573b4f2020-09-28 13:34:05 +000011663 sqlite3_int64 n, sz;
11664 sz = integerValue(cmdline_option_value(argc,argv,++i));
drh2ce15c32017-07-11 13:34:40 +000011665 if( sz>70000 ) sz = 70000;
11666 if( sz<0 ) sz = 0;
drhf573b4f2020-09-28 13:34:05 +000011667 n = integerValue(cmdline_option_value(argc,argv,++i));
11668 if( sz>0 && n>0 && 0xffffffffffffLL/sz<n ){
11669 n = 0xffffffffffffLL/sz;
11670 }
drh2ce15c32017-07-11 13:34:40 +000011671 sqlite3_config(SQLITE_CONFIG_PAGECACHE,
11672 (n>0 && sz>0) ? malloc(n*sz) : 0, sz, n);
11673 data.shellFlgs |= SHFLG_Pagecache;
drhbf70f1b2022-10-19 18:04:42 +000011674 }else if( cli_strcmp(z,"-lookaside")==0 ){
drh2ce15c32017-07-11 13:34:40 +000011675 int n, sz;
11676 sz = (int)integerValue(cmdline_option_value(argc,argv,++i));
11677 if( sz<0 ) sz = 0;
11678 n = (int)integerValue(cmdline_option_value(argc,argv,++i));
11679 if( n<0 ) n = 0;
11680 sqlite3_config(SQLITE_CONFIG_LOOKASIDE, sz, n);
11681 if( sz*n==0 ) data.shellFlgs &= ~SHFLG_Lookaside;
drhbf70f1b2022-10-19 18:04:42 +000011682 }else if( cli_strcmp(z,"-threadsafe")==0 ){
drh9d16fb12021-08-09 17:45:00 +000011683 int n;
11684 n = (int)integerValue(cmdline_option_value(argc,argv,++i));
11685 switch( n ){
drhaf6d1af2021-08-09 17:37:58 +000011686 case 0: sqlite3_config(SQLITE_CONFIG_SINGLETHREAD); break;
11687 case 2: sqlite3_config(SQLITE_CONFIG_MULTITHREAD); break;
11688 default: sqlite3_config(SQLITE_CONFIG_SERIALIZED); break;
11689 }
drh2ce15c32017-07-11 13:34:40 +000011690#ifdef SQLITE_ENABLE_VFSTRACE
drhbf70f1b2022-10-19 18:04:42 +000011691 }else if( cli_strcmp(z,"-vfstrace")==0 ){
drh2ce15c32017-07-11 13:34:40 +000011692 extern int vfstrace_register(
11693 const char *zTraceName,
11694 const char *zOldVfsName,
11695 int (*xOut)(const char*,void*),
11696 void *pOutArg,
11697 int makeDefault
11698 );
11699 vfstrace_register("trace",0,(int(*)(const char*,void*))fputs,stderr,1);
11700#endif
11701#ifdef SQLITE_ENABLE_MULTIPLEX
drhbf70f1b2022-10-19 18:04:42 +000011702 }else if( cli_strcmp(z,"-multiplex")==0 ){
drh2ce15c32017-07-11 13:34:40 +000011703 extern int sqlite3_multiple_initialize(const char*,int);
11704 sqlite3_multiplex_initialize(0, 1);
11705#endif
drhbf70f1b2022-10-19 18:04:42 +000011706 }else if( cli_strcmp(z,"-mmap")==0 ){
drh2ce15c32017-07-11 13:34:40 +000011707 sqlite3_int64 sz = integerValue(cmdline_option_value(argc,argv,++i));
11708 sqlite3_config(SQLITE_CONFIG_MMAP_SIZE, sz, sz);
drha90d84f2018-04-18 15:21:13 +000011709#ifdef SQLITE_ENABLE_SORTER_REFERENCES
drhbf70f1b2022-10-19 18:04:42 +000011710 }else if( cli_strcmp(z,"-sorterref")==0 ){
drha90d84f2018-04-18 15:21:13 +000011711 sqlite3_int64 sz = integerValue(cmdline_option_value(argc,argv,++i));
11712 sqlite3_config(SQLITE_CONFIG_SORTERREF_SIZE, (int)sz);
11713#endif
drhbf70f1b2022-10-19 18:04:42 +000011714 }else if( cli_strcmp(z,"-vfs")==0 ){
dan16a47422018-04-18 09:16:11 +000011715 zVfs = cmdline_option_value(argc, argv, ++i);
drh3baed312018-03-08 18:14:41 +000011716#ifdef SQLITE_HAVE_ZLIB
drhbf70f1b2022-10-19 18:04:42 +000011717 }else if( cli_strcmp(z,"-zip")==0 ){
drh8682e122018-01-07 20:38:10 +000011718 data.openMode = SHELL_OPEN_ZIPFILE;
11719#endif
drhbf70f1b2022-10-19 18:04:42 +000011720 }else if( cli_strcmp(z,"-append")==0 ){
drh8682e122018-01-07 20:38:10 +000011721 data.openMode = SHELL_OPEN_APPENDVFS;
drh8d889af2021-05-08 17:18:23 +000011722#ifndef SQLITE_OMIT_DESERIALIZE
drhbf70f1b2022-10-19 18:04:42 +000011723 }else if( cli_strcmp(z,"-deserialize")==0 ){
drh60f34ae2018-10-30 13:19:49 +000011724 data.openMode = SHELL_OPEN_DESERIALIZE;
drhbf70f1b2022-10-19 18:04:42 +000011725 }else if( cli_strcmp(z,"-maxsize")==0 && i+1<argc ){
drh6ca64482019-01-22 16:06:20 +000011726 data.szMax = integerValue(argv[++i]);
drha751f392018-10-30 15:31:22 +000011727#endif
drhbf70f1b2022-10-19 18:04:42 +000011728 }else if( cli_strcmp(z,"-readonly")==0 ){
drhee269a62018-02-14 23:27:43 +000011729 data.openMode = SHELL_OPEN_READONLY;
drhbf70f1b2022-10-19 18:04:42 +000011730 }else if( cli_strcmp(z,"-nofollow")==0 ){
drh0933aad2019-11-18 17:46:38 +000011731 data.openFlags = SQLITE_OPEN_NOFOLLOW;
drhda57d962018-03-05 19:34:05 +000011732#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
drhbf70f1b2022-10-19 18:04:42 +000011733 }else if( cli_strncmp(z, "-A",2)==0 ){
drhda57d962018-03-05 19:34:05 +000011734 /* All remaining command-line arguments are passed to the ".archive"
11735 ** command, so ignore them */
11736 break;
11737#endif
drhbf70f1b2022-10-19 18:04:42 +000011738 }else if( cli_strcmp(z, "-memtrace")==0 ){
drh50b910a2019-01-21 14:55:03 +000011739 sqlite3MemTraceActivate(stderr);
drhbf70f1b2022-10-19 18:04:42 +000011740 }else if( cli_strcmp(z,"-bail")==0 ){
drhb7c46aa2020-11-25 13:59:47 +000011741 bail_on_error = 1;
drhbf70f1b2022-10-19 18:04:42 +000011742 }else if( cli_strcmp(z,"-nonce")==0 ){
drhb97e2ad2021-08-26 18:31:39 +000011743 free(data.zNonce);
11744 data.zNonce = strdup(argv[++i]);
drhbf70f1b2022-10-19 18:04:42 +000011745 }else if( cli_strcmp(z,"-safe")==0 ){
drhb97e2ad2021-08-26 18:31:39 +000011746 /* no-op - catch this on the second pass */
drh2ce15c32017-07-11 13:34:40 +000011747 }
11748 }
drhe7df8922018-04-18 10:44:58 +000011749 verify_uninitialized();
11750
dan16a47422018-04-18 09:16:11 +000011751
drhd11b8f62018-04-25 13:27:07 +000011752#ifdef SQLITE_SHELL_INIT_PROC
11753 {
11754 /* If the SQLITE_SHELL_INIT_PROC macro is defined, then it is the name
11755 ** of a C-function that will perform initialization actions on SQLite that
11756 ** occur just before or after sqlite3_initialize(). Use this compile-time
11757 ** option to embed this shell program in larger applications. */
11758 extern void SQLITE_SHELL_INIT_PROC(void);
11759 SQLITE_SHELL_INIT_PROC();
11760 }
11761#else
dan16a47422018-04-18 09:16:11 +000011762 /* All the sqlite3_config() calls have now been made. So it is safe
11763 ** to call sqlite3_initialize() and process any command line -vfs option. */
11764 sqlite3_initialize();
drhd11b8f62018-04-25 13:27:07 +000011765#endif
11766
dan16a47422018-04-18 09:16:11 +000011767 if( zVfs ){
11768 sqlite3_vfs *pVfs = sqlite3_vfs_find(zVfs);
11769 if( pVfs ){
11770 sqlite3_vfs_register(pVfs, 1);
11771 }else{
11772 utf8_printf(stderr, "no such VFS: \"%s\"\n", argv[i]);
11773 exit(1);
11774 }
11775 }
11776
drh37407122021-07-23 18:43:58 +000011777 if( data.pAuxDb->zDbFilename==0 ){
drh2ce15c32017-07-11 13:34:40 +000011778#ifndef SQLITE_OMIT_MEMORYDB
drh37407122021-07-23 18:43:58 +000011779 data.pAuxDb->zDbFilename = ":memory:";
drh2ce15c32017-07-11 13:34:40 +000011780 warnInmemoryDb = argc==1;
11781#else
11782 utf8_printf(stderr,"%s: Error: no database filename specified\n", Argv0);
11783 return 1;
11784#endif
11785 }
11786 data.out = stdout;
stephan4413ec72022-07-12 15:53:02 +000011787#ifndef SQLITE_SHELL_FIDDLE
drh8682e122018-01-07 20:38:10 +000011788 sqlite3_appendvfs_init(0,0,0);
stephanf8cd3d22022-05-18 17:14:24 +000011789#endif
drh2ce15c32017-07-11 13:34:40 +000011790
11791 /* Go ahead and open the database file if it already exists. If the
11792 ** file does not exist, delay opening it. This prevents empty database
11793 ** files from being created if a user mistypes the database name argument
11794 ** to the sqlite command-line tool.
11795 */
drh37407122021-07-23 18:43:58 +000011796 if( access(data.pAuxDb->zDbFilename, 0)==0 ){
drh2ce15c32017-07-11 13:34:40 +000011797 open_db(&data, 0);
11798 }
11799
11800 /* Process the initialization file if there is one. If no -init option
11801 ** is given on the command line, look for a file named ~/.sqliterc and
11802 ** try to process it.
11803 */
11804 process_sqliterc(&data,zInitFile);
11805
11806 /* Make a second pass through the command-line argument and set
11807 ** options. This second pass is delayed until after the initialization
11808 ** file is processed so that the command-line arguments will override
11809 ** settings in the initialization file.
11810 */
11811 for(i=1; i<argc; i++){
11812 char *z = argv[i];
11813 if( z[0]!='-' ) continue;
11814 if( z[1]=='-' ){ z++; }
drhbf70f1b2022-10-19 18:04:42 +000011815 if( cli_strcmp(z,"-init")==0 ){
drh2ce15c32017-07-11 13:34:40 +000011816 i++;
drhbf70f1b2022-10-19 18:04:42 +000011817 }else if( cli_strcmp(z,"-html")==0 ){
drh2ce15c32017-07-11 13:34:40 +000011818 data.mode = MODE_Html;
drhbf70f1b2022-10-19 18:04:42 +000011819 }else if( cli_strcmp(z,"-list")==0 ){
drh2ce15c32017-07-11 13:34:40 +000011820 data.mode = MODE_List;
drhbf70f1b2022-10-19 18:04:42 +000011821 }else if( cli_strcmp(z,"-quote")==0 ){
drh2ce15c32017-07-11 13:34:40 +000011822 data.mode = MODE_Quote;
drh9191c702020-08-17 09:11:21 +000011823 sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator, SEP_Comma);
11824 sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator, SEP_Row);
drhbf70f1b2022-10-19 18:04:42 +000011825 }else if( cli_strcmp(z,"-line")==0 ){
drh2ce15c32017-07-11 13:34:40 +000011826 data.mode = MODE_Line;
drhbf70f1b2022-10-19 18:04:42 +000011827 }else if( cli_strcmp(z,"-column")==0 ){
drh2ce15c32017-07-11 13:34:40 +000011828 data.mode = MODE_Column;
drhbf70f1b2022-10-19 18:04:42 +000011829 }else if( cli_strcmp(z,"-json")==0 ){
drh30c54a02020-05-28 23:49:50 +000011830 data.mode = MODE_Json;
drhbf70f1b2022-10-19 18:04:42 +000011831 }else if( cli_strcmp(z,"-markdown")==0 ){
drh30c54a02020-05-28 23:49:50 +000011832 data.mode = MODE_Markdown;
drhbf70f1b2022-10-19 18:04:42 +000011833 }else if( cli_strcmp(z,"-table")==0 ){
drh30c54a02020-05-28 23:49:50 +000011834 data.mode = MODE_Table;
drhbf70f1b2022-10-19 18:04:42 +000011835 }else if( cli_strcmp(z,"-box")==0 ){
drh0908e382020-06-04 18:05:39 +000011836 data.mode = MODE_Box;
drhbf70f1b2022-10-19 18:04:42 +000011837 }else if( cli_strcmp(z,"-csv")==0 ){
drh2ce15c32017-07-11 13:34:40 +000011838 data.mode = MODE_Csv;
11839 memcpy(data.colSeparator,",",2);
drh3baed312018-03-08 18:14:41 +000011840#ifdef SQLITE_HAVE_ZLIB
drhbf70f1b2022-10-19 18:04:42 +000011841 }else if( cli_strcmp(z,"-zip")==0 ){
drh1fa6d9f2018-01-06 21:46:01 +000011842 data.openMode = SHELL_OPEN_ZIPFILE;
11843#endif
drhbf70f1b2022-10-19 18:04:42 +000011844 }else if( cli_strcmp(z,"-append")==0 ){
drh1fa6d9f2018-01-06 21:46:01 +000011845 data.openMode = SHELL_OPEN_APPENDVFS;
drh8d889af2021-05-08 17:18:23 +000011846#ifndef SQLITE_OMIT_DESERIALIZE
drhbf70f1b2022-10-19 18:04:42 +000011847 }else if( cli_strcmp(z,"-deserialize")==0 ){
drh60f34ae2018-10-30 13:19:49 +000011848 data.openMode = SHELL_OPEN_DESERIALIZE;
drhbf70f1b2022-10-19 18:04:42 +000011849 }else if( cli_strcmp(z,"-maxsize")==0 && i+1<argc ){
drh6ca64482019-01-22 16:06:20 +000011850 data.szMax = integerValue(argv[++i]);
drha751f392018-10-30 15:31:22 +000011851#endif
drhbf70f1b2022-10-19 18:04:42 +000011852 }else if( cli_strcmp(z,"-readonly")==0 ){
drh4aafe592018-03-23 16:08:30 +000011853 data.openMode = SHELL_OPEN_READONLY;
drhbf70f1b2022-10-19 18:04:42 +000011854 }else if( cli_strcmp(z,"-nofollow")==0 ){
drh0933aad2019-11-18 17:46:38 +000011855 data.openFlags |= SQLITE_OPEN_NOFOLLOW;
drhbf70f1b2022-10-19 18:04:42 +000011856 }else if( cli_strcmp(z,"-ascii")==0 ){
drh2ce15c32017-07-11 13:34:40 +000011857 data.mode = MODE_Ascii;
drh2fa78182020-10-31 18:58:37 +000011858 sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator, SEP_Unit);
11859 sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator, SEP_Record);
drhbf70f1b2022-10-19 18:04:42 +000011860 }else if( cli_strcmp(z,"-tabs")==0 ){
drh2fa78182020-10-31 18:58:37 +000011861 data.mode = MODE_List;
11862 sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator, SEP_Tab);
11863 sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator, SEP_Row);
drhbf70f1b2022-10-19 18:04:42 +000011864 }else if( cli_strcmp(z,"-separator")==0 ){
drh2ce15c32017-07-11 13:34:40 +000011865 sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator,
11866 "%s",cmdline_option_value(argc,argv,++i));
drhbf70f1b2022-10-19 18:04:42 +000011867 }else if( cli_strcmp(z,"-newline")==0 ){
drh2ce15c32017-07-11 13:34:40 +000011868 sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator,
11869 "%s",cmdline_option_value(argc,argv,++i));
drhbf70f1b2022-10-19 18:04:42 +000011870 }else if( cli_strcmp(z,"-nullvalue")==0 ){
drh2ce15c32017-07-11 13:34:40 +000011871 sqlite3_snprintf(sizeof(data.nullValue), data.nullValue,
11872 "%s",cmdline_option_value(argc,argv,++i));
drhbf70f1b2022-10-19 18:04:42 +000011873 }else if( cli_strcmp(z,"-header")==0 ){
drh2ce15c32017-07-11 13:34:40 +000011874 data.showHeader = 1;
larrybrae509122021-09-10 01:45:20 +000011875 ShellSetFlag(&data, SHFLG_HeaderSet);
drhbf70f1b2022-10-19 18:04:42 +000011876 }else if( cli_strcmp(z,"-noheader")==0 ){
drh2ce15c32017-07-11 13:34:40 +000011877 data.showHeader = 0;
larrybrae509122021-09-10 01:45:20 +000011878 ShellSetFlag(&data, SHFLG_HeaderSet);
drhbf70f1b2022-10-19 18:04:42 +000011879 }else if( cli_strcmp(z,"-echo")==0 ){
drh2ce15c32017-07-11 13:34:40 +000011880 ShellSetFlag(&data, SHFLG_Echo);
drhbf70f1b2022-10-19 18:04:42 +000011881 }else if( cli_strcmp(z,"-eqp")==0 ){
drhada70452017-12-21 21:02:27 +000011882 data.autoEQP = AUTOEQP_on;
drhbf70f1b2022-10-19 18:04:42 +000011883 }else if( cli_strcmp(z,"-eqpfull")==0 ){
drhada70452017-12-21 21:02:27 +000011884 data.autoEQP = AUTOEQP_full;
drhbf70f1b2022-10-19 18:04:42 +000011885 }else if( cli_strcmp(z,"-stats")==0 ){
drh2ce15c32017-07-11 13:34:40 +000011886 data.statsOn = 1;
drhbf70f1b2022-10-19 18:04:42 +000011887 }else if( cli_strcmp(z,"-scanstats")==0 ){
drh2ce15c32017-07-11 13:34:40 +000011888 data.scanstatsOn = 1;
drhbf70f1b2022-10-19 18:04:42 +000011889 }else if( cli_strcmp(z,"-backslash")==0 ){
drh2ce15c32017-07-11 13:34:40 +000011890 /* Undocumented command-line option: -backslash
11891 ** Causes C-style backslash escapes to be evaluated in SQL statements
11892 ** prior to sending the SQL into SQLite. Useful for injecting
11893 ** crazy bytes in the middle of SQL statements for testing and debugging.
11894 */
11895 ShellSetFlag(&data, SHFLG_Backslash);
drhbf70f1b2022-10-19 18:04:42 +000011896 }else if( cli_strcmp(z,"-bail")==0 ){
drhb7c46aa2020-11-25 13:59:47 +000011897 /* No-op. The bail_on_error flag should already be set. */
drhbf70f1b2022-10-19 18:04:42 +000011898 }else if( cli_strcmp(z,"-version")==0 ){
drh2ce15c32017-07-11 13:34:40 +000011899 printf("%s %s\n", sqlite3_libversion(), sqlite3_sourceid());
11900 return 0;
drhbf70f1b2022-10-19 18:04:42 +000011901 }else if( cli_strcmp(z,"-interactive")==0 ){
drh2ce15c32017-07-11 13:34:40 +000011902 stdin_is_interactive = 1;
drhbf70f1b2022-10-19 18:04:42 +000011903 }else if( cli_strcmp(z,"-batch")==0 ){
drh2ce15c32017-07-11 13:34:40 +000011904 stdin_is_interactive = 0;
drhbf70f1b2022-10-19 18:04:42 +000011905 }else if( cli_strcmp(z,"-heap")==0 ){
drh2ce15c32017-07-11 13:34:40 +000011906 i++;
drhbf70f1b2022-10-19 18:04:42 +000011907 }else if( cli_strcmp(z,"-pagecache")==0 ){
drh2ce15c32017-07-11 13:34:40 +000011908 i+=2;
drhbf70f1b2022-10-19 18:04:42 +000011909 }else if( cli_strcmp(z,"-lookaside")==0 ){
drh2ce15c32017-07-11 13:34:40 +000011910 i+=2;
drhbf70f1b2022-10-19 18:04:42 +000011911 }else if( cli_strcmp(z,"-threadsafe")==0 ){
drhaf6d1af2021-08-09 17:37:58 +000011912 i+=2;
drhbf70f1b2022-10-19 18:04:42 +000011913 }else if( cli_strcmp(z,"-nonce")==0 ){
drhb97e2ad2021-08-26 18:31:39 +000011914 i += 2;
drhbf70f1b2022-10-19 18:04:42 +000011915 }else if( cli_strcmp(z,"-mmap")==0 ){
drh2ce15c32017-07-11 13:34:40 +000011916 i++;
drhbf70f1b2022-10-19 18:04:42 +000011917 }else if( cli_strcmp(z,"-memtrace")==0 ){
drh50b910a2019-01-21 14:55:03 +000011918 i++;
drha90d84f2018-04-18 15:21:13 +000011919#ifdef SQLITE_ENABLE_SORTER_REFERENCES
drhbf70f1b2022-10-19 18:04:42 +000011920 }else if( cli_strcmp(z,"-sorterref")==0 ){
drha90d84f2018-04-18 15:21:13 +000011921 i++;
11922#endif
drhbf70f1b2022-10-19 18:04:42 +000011923 }else if( cli_strcmp(z,"-vfs")==0 ){
drh2ce15c32017-07-11 13:34:40 +000011924 i++;
11925#ifdef SQLITE_ENABLE_VFSTRACE
drhbf70f1b2022-10-19 18:04:42 +000011926 }else if( cli_strcmp(z,"-vfstrace")==0 ){
drh2ce15c32017-07-11 13:34:40 +000011927 i++;
11928#endif
11929#ifdef SQLITE_ENABLE_MULTIPLEX
drhbf70f1b2022-10-19 18:04:42 +000011930 }else if( cli_strcmp(z,"-multiplex")==0 ){
drh2ce15c32017-07-11 13:34:40 +000011931 i++;
11932#endif
drhbf70f1b2022-10-19 18:04:42 +000011933 }else if( cli_strcmp(z,"-help")==0 ){
drh2ce15c32017-07-11 13:34:40 +000011934 usage(1);
drhbf70f1b2022-10-19 18:04:42 +000011935 }else if( cli_strcmp(z,"-cmd")==0 ){
drh2ce15c32017-07-11 13:34:40 +000011936 /* Run commands that follow -cmd first and separately from commands
11937 ** that simply appear on the command-line. This seems goofy. It would
11938 ** be better if all commands ran in the order that they appear. But
11939 ** we retain the goofy behavior for historical compatibility. */
11940 if( i==argc-1 ) break;
11941 z = cmdline_option_value(argc,argv,++i);
11942 if( z[0]=='.' ){
11943 rc = do_meta_command(z, &data);
11944 if( rc && bail_on_error ) return rc==2 ? 0 : rc;
11945 }else{
11946 open_db(&data, 0);
drha10b9992018-03-09 15:24:33 +000011947 rc = shell_exec(&data, z, &zErrMsg);
drh2ce15c32017-07-11 13:34:40 +000011948 if( zErrMsg!=0 ){
11949 utf8_printf(stderr,"Error: %s\n", zErrMsg);
11950 if( bail_on_error ) return rc!=0 ? rc : 1;
11951 }else if( rc!=0 ){
11952 utf8_printf(stderr,"Error: unable to process SQL \"%s\"\n", z);
11953 if( bail_on_error ) return rc;
11954 }
11955 }
drhda57d962018-03-05 19:34:05 +000011956#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
drhbf70f1b2022-10-19 18:04:42 +000011957 }else if( cli_strncmp(z, "-A", 2)==0 ){
drhda57d962018-03-05 19:34:05 +000011958 if( nCmd>0 ){
11959 utf8_printf(stderr, "Error: cannot mix regular SQL or dot-commands"
11960 " with \"%s\"\n", z);
11961 return 1;
11962 }
drhbe4ccb22018-05-17 20:04:24 +000011963 open_db(&data, OPEN_DB_ZIPFILE);
drh93b77312018-03-05 20:20:22 +000011964 if( z[2] ){
11965 argv[i] = &z[2];
drhd0f9cdc2018-05-17 14:09:06 +000011966 arDotCommand(&data, 1, argv+(i-1), argc-(i-1));
drh93b77312018-03-05 20:20:22 +000011967 }else{
drhd0f9cdc2018-05-17 14:09:06 +000011968 arDotCommand(&data, 1, argv+i, argc-i);
drh93b77312018-03-05 20:20:22 +000011969 }
drhda57d962018-03-05 19:34:05 +000011970 readStdin = 0;
11971 break;
11972#endif
drhbf70f1b2022-10-19 18:04:42 +000011973 }else if( cli_strcmp(z,"-safe")==0 ){
drhb97e2ad2021-08-26 18:31:39 +000011974 data.bSafeMode = data.bSafeModePersist = 1;
drh2ce15c32017-07-11 13:34:40 +000011975 }else{
11976 utf8_printf(stderr,"%s: Error: unknown option: %s\n", Argv0, z);
11977 raw_printf(stderr,"Use -help for a list of options.\n");
11978 return 1;
11979 }
11980 data.cMode = data.mode;
11981 }
11982
11983 if( !readStdin ){
11984 /* Run all arguments that do not begin with '-' as if they were separate
11985 ** command-line inputs, except for the argToSkip argument which contains
11986 ** the database filename.
11987 */
11988 for(i=0; i<nCmd; i++){
11989 if( azCmd[i][0]=='.' ){
11990 rc = do_meta_command(azCmd[i], &data);
danaff1a572020-11-17 21:09:56 +000011991 if( rc ){
11992 free(azCmd);
11993 return rc==2 ? 0 : rc;
11994 }
drh2ce15c32017-07-11 13:34:40 +000011995 }else{
11996 open_db(&data, 0);
drha10b9992018-03-09 15:24:33 +000011997 rc = shell_exec(&data, azCmd[i], &zErrMsg);
danaff1a572020-11-17 21:09:56 +000011998 if( zErrMsg || rc ){
11999 if( zErrMsg!=0 ){
12000 utf8_printf(stderr,"Error: %s\n", zErrMsg);
12001 }else{
12002 utf8_printf(stderr,"Error: unable to process SQL: %s\n", azCmd[i]);
12003 }
12004 sqlite3_free(zErrMsg);
12005 free(azCmd);
drh2ce15c32017-07-11 13:34:40 +000012006 return rc!=0 ? rc : 1;
drh2ce15c32017-07-11 13:34:40 +000012007 }
12008 }
12009 }
drh2ce15c32017-07-11 13:34:40 +000012010 }else{
12011 /* Run commands received from standard input
12012 */
12013 if( stdin_is_interactive ){
12014 char *zHome;
drha9e4be32018-10-10 18:56:40 +000012015 char *zHistory;
drh2ce15c32017-07-11 13:34:40 +000012016 int nHistory;
12017 printf(
12018 "SQLite version %s %.19s\n" /*extra-version-info*/
12019 "Enter \".help\" for usage hints.\n",
12020 sqlite3_libversion(), sqlite3_sourceid()
12021 );
12022 if( warnInmemoryDb ){
12023 printf("Connected to a ");
12024 printBold("transient in-memory database");
12025 printf(".\nUse \".open FILENAME\" to reopen on a "
12026 "persistent database.\n");
12027 }
drha9e4be32018-10-10 18:56:40 +000012028 zHistory = getenv("SQLITE_HISTORY");
12029 if( zHistory ){
12030 zHistory = strdup(zHistory);
12031 }else if( (zHome = find_home_dir(0))!=0 ){
drh2ce15c32017-07-11 13:34:40 +000012032 nHistory = strlen30(zHome) + 20;
12033 if( (zHistory = malloc(nHistory))!=0 ){
12034 sqlite3_snprintf(nHistory, zHistory,"%s/.sqlite_history", zHome);
12035 }
12036 }
12037 if( zHistory ){ shell_read_history(zHistory); }
drh56eb09b2017-07-11 13:59:07 +000012038#if HAVE_READLINE || HAVE_EDITLINE
12039 rl_attempted_completion_function = readline_completion;
12040#elif HAVE_LINENOISE
12041 linenoiseSetCompletionCallback(linenoise_completion);
12042#endif
drh60379d42018-12-13 18:30:01 +000012043 data.in = 0;
12044 rc = process_input(&data);
drh2ce15c32017-07-11 13:34:40 +000012045 if( zHistory ){
drh5a75dd82017-07-18 20:59:40 +000012046 shell_stifle_history(2000);
drh2ce15c32017-07-11 13:34:40 +000012047 shell_write_history(zHistory);
12048 free(zHistory);
12049 }
12050 }else{
drh60379d42018-12-13 18:30:01 +000012051 data.in = stdin;
12052 rc = process_input(&data);
drh2ce15c32017-07-11 13:34:40 +000012053 }
12054 }
stephan4413ec72022-07-12 15:53:02 +000012055#ifndef SQLITE_SHELL_FIDDLE
stephanf8cd3d22022-05-18 17:14:24 +000012056 /* In WASM mode we have to leave the db state in place so that
12057 ** client code can "push" SQL into it after this call returns. */
danaff1a572020-11-17 21:09:56 +000012058 free(azCmd);
drh2ce15c32017-07-11 13:34:40 +000012059 set_table_name(&data, 0);
12060 if( data.db ){
drh37407122021-07-23 18:43:58 +000012061 session_close_all(&data, -1);
drh9e804032018-05-18 17:11:50 +000012062 close_db(data.db);
drh2ce15c32017-07-11 13:34:40 +000012063 }
drh37407122021-07-23 18:43:58 +000012064 for(i=0; i<ArraySize(data.aAuxDb); i++){
12065 sqlite3_free(data.aAuxDb[i].zFreeOnClose);
12066 if( data.aAuxDb[i].db ){
12067 session_close_all(&data, i);
12068 close_db(data.aAuxDb[i].db);
12069 }
12070 }
drh2ce15c32017-07-11 13:34:40 +000012071 find_home_dir(1);
drh536c3452018-01-11 00:38:39 +000012072 output_reset(&data);
12073 data.doXdgOpen = 0;
drh13c20932018-01-10 21:41:55 +000012074 clearTempFile(&data);
drh2ce15c32017-07-11 13:34:40 +000012075#if !SQLITE_SHELL_IS_UTF8
drh1f22f622018-05-17 13:29:14 +000012076 for(i=0; i<argcToFree; i++) free(argvToFree[i]);
12077 free(argvToFree);
drh2ce15c32017-07-11 13:34:40 +000012078#endif
drh0285d982020-05-29 14:38:43 +000012079 free(data.colWidth);
drhb97e2ad2021-08-26 18:31:39 +000012080 free(data.zNonce);
drh9e804032018-05-18 17:11:50 +000012081 /* Clear the global data structure so that valgrind will detect memory
12082 ** leaks */
12083 memset(&data, 0, sizeof(data));
larrybrfa5dfa82022-05-07 03:53:14 +000012084#ifdef SQLITE_DEBUG
12085 if( sqlite3_memory_used()>mem_main_enter ){
12086 utf8_printf(stderr, "Memory leaked: %u bytes\n",
12087 (unsigned int)(sqlite3_memory_used()-mem_main_enter));
12088 }
12089#endif
stephan4413ec72022-07-12 15:53:02 +000012090#endif /* !SQLITE_SHELL_FIDDLE */
drh2ce15c32017-07-11 13:34:40 +000012091 return rc;
12092}
stephanf8cd3d22022-05-18 17:14:24 +000012093
12094
stephan4413ec72022-07-12 15:53:02 +000012095#ifdef SQLITE_SHELL_FIDDLE
stephan2eb45412022-05-21 00:01:45 +000012096/* Only for emcc experimentation purposes. */
12097int fiddle_experiment(int a,int b){
stephan278d3fa2022-09-26 13:55:10 +000012098 return a + b;
stephan2eb45412022-05-21 00:01:45 +000012099}
12100
stephan1f095d42022-09-26 11:38:58 +000012101/*
12102** Returns a pointer to the current DB handle.
stephan2eb45412022-05-21 00:01:45 +000012103*/
stephan1f095d42022-09-26 11:38:58 +000012104sqlite3 * fiddle_db_handle(){
stephan278d3fa2022-09-26 13:55:10 +000012105 return globalDb;
stephan2eb45412022-05-21 00:01:45 +000012106}
stephan278d3fa2022-09-26 13:55:10 +000012107
12108/*
12109** Returns a pointer to the given DB name's VFS. If zDbName is 0 then
12110** "main" is assumed. Returns 0 if no db with the given name is
12111** open.
12112*/
12113sqlite3_vfs * fiddle_db_vfs(const char *zDbName){
12114 sqlite3_vfs * pVfs = 0;
12115 if(globalDb){
12116 sqlite3_file_control(globalDb, zDbName ? zDbName : "main",
12117 SQLITE_FCNTL_VFS_POINTER, &pVfs);
12118 }
12119 return pVfs;
stephan2eb45412022-05-21 00:01:45 +000012120}
stephan1f095d42022-09-26 11:38:58 +000012121
stephan2eb45412022-05-21 00:01:45 +000012122/* Only for emcc experimentation purposes. */
12123sqlite3 * fiddle_db_arg(sqlite3 *arg){
12124 printf("fiddle_db_arg(%p)\n", (const void*)arg);
12125 return arg;
12126}
12127
stephanf8cd3d22022-05-18 17:14:24 +000012128/*
stephan42573732022-05-21 14:19:05 +000012129** Intended to be called via a SharedWorker() while a separate
12130** SharedWorker() (which manages the wasm module) is performing work
stephan085c5c62022-05-25 04:35:22 +000012131** which should be interrupted. Unfortunately, SharedWorker is not
12132** portable enough to make real use of.
stephan42573732022-05-21 14:19:05 +000012133*/
12134void fiddle_interrupt(void){
stephan278d3fa2022-09-26 13:55:10 +000012135 if( globalDb ) sqlite3_interrupt(globalDb);
stephan42573732022-05-21 14:19:05 +000012136}
12137
12138/*
stephan085c5c62022-05-25 04:35:22 +000012139** Returns the filename of the given db name, assuming "main" if
12140** zDbName is NULL. Returns NULL if globalDb is not opened.
stephan80bf8692022-05-24 22:16:12 +000012141*/
12142const char * fiddle_db_filename(const char * zDbName){
12143 return globalDb
12144 ? sqlite3_db_filename(globalDb, zDbName ? zDbName : "main")
12145 : NULL;
12146}
12147
12148/*
stephana4c357f2022-10-03 11:42:45 +000012149** Completely wipes out the contents of the currently-opened database
12150** but leaves its storage intact for reuse.
stephancd697842022-05-27 03:27:10 +000012151*/
12152void fiddle_reset_db(void){
stephana4c357f2022-10-03 11:42:45 +000012153 if( globalDb ){
12154 int rc = sqlite3_db_config(globalDb, SQLITE_DBCONFIG_RESET_DATABASE, 1, 0);
12155 if( 0==rc ) rc = sqlite3_exec(globalDb, "VACUUM", 0, 0, 0);
12156 sqlite3_db_config(globalDb, SQLITE_DBCONFIG_RESET_DATABASE, 0, 0);
stephancd697842022-05-27 03:27:10 +000012157 }
stephancd697842022-05-27 03:27:10 +000012158}
12159
12160/*
stephan278d3fa2022-09-26 13:55:10 +000012161** Uses the current database's VFS xRead to stream the db file's
12162** contents out to the given callback. The callback gets a single
12163** chunk of size n (its 2nd argument) on each call and must return 0
12164** on success, non-0 on error. This function returns 0 on success,
12165** SQLITE_NOTFOUND if no db is open, or propagates any other non-0
12166** code from the callback. Note that this is not thread-friendly: it
12167** expects that it will be the only thread reading the db file and
12168** takes no measures to ensure that is the case.
stephan1f095d42022-09-26 11:38:58 +000012169*/
stephan278d3fa2022-09-26 13:55:10 +000012170int fiddle_export_db( int (*xCallback)(unsigned const char *zOut, int n) ){
stephan1f095d42022-09-26 11:38:58 +000012171 sqlite3_int64 nSize = 0;
12172 sqlite3_int64 nPos = 0;
stephan1f095d42022-09-26 11:38:58 +000012173 sqlite3_file * pFile = 0;
stephan278d3fa2022-09-26 13:55:10 +000012174 unsigned char buf[1024 * 8];
12175 int nBuf = (int)sizeof(buf);
stephan1f095d42022-09-26 11:38:58 +000012176 int rc = shellState.db
12177 ? sqlite3_file_control(shellState.db, "main",
stephan278d3fa2022-09-26 13:55:10 +000012178 SQLITE_FCNTL_FILE_POINTER, &pFile)
12179 : SQLITE_NOTFOUND;
stephan1f095d42022-09-26 11:38:58 +000012180 if( rc ) return rc;
12181 rc = pFile->pMethods->xFileSize(pFile, &nSize);
stephan278d3fa2022-09-26 13:55:10 +000012182 if( rc ) return rc;
12183 if(nSize % nBuf){
12184 /* DB size is not an even multiple of the buffer size. Reduce
12185 ** buffer size so that we do not unduly inflate the db size when
12186 ** exporting. */
12187 if(0 == nSize % 4096) nBuf = 4096;
12188 else if(0 == nSize % 2048) nBuf = 2048;
12189 else if(0 == nSize % 1024) nBuf = 1024;
12190 else nBuf = 512;
12191 }
stephan1f095d42022-09-26 11:38:58 +000012192 for( ; 0==rc && nPos<nSize; nPos += nBuf ){
12193 rc = pFile->pMethods->xRead(pFile, buf, nBuf, nPos);
12194 if(SQLITE_IOERR_SHORT_READ == rc){
12195 rc = (nPos + nBuf) < nSize ? rc : 0/*assume EOF*/;
12196 }
stephan278d3fa2022-09-26 13:55:10 +000012197 if( 0==rc ) rc = xCallback(buf, nBuf);
stephan1f095d42022-09-26 11:38:58 +000012198 }
12199 return rc;
12200}
stephan1f095d42022-09-26 11:38:58 +000012201
12202/*
stephan60d9aa72022-09-24 07:36:45 +000012203** Trivial exportable function for emscripten. It processes zSql as if
12204** it were input to the sqlite3 shell and redirects all output to the
stephan842c5ee2022-10-20 05:14:37 +000012205** wasm binding. fiddle_main() must have been called before this
12206** is called, or results are undefined.
stephanf8cd3d22022-05-18 17:14:24 +000012207*/
stephan0076e492022-05-18 18:10:17 +000012208void fiddle_exec(const char * zSql){
stephan60d9aa72022-09-24 07:36:45 +000012209 if(zSql && *zSql){
12210 if('.'==*zSql) puts(zSql);
stephanf8cd3d22022-05-18 17:14:24 +000012211 shellState.wasm.zInput = zSql;
12212 shellState.wasm.zPos = zSql;
12213 process_input(&shellState);
stephan60d9aa72022-09-24 07:36:45 +000012214 shellState.wasm.zInput = shellState.wasm.zPos = 0;
stephanf8cd3d22022-05-18 17:14:24 +000012215 }
12216}
stephan4413ec72022-07-12 15:53:02 +000012217#endif /* SQLITE_SHELL_FIDDLE */