xref: /minix3/external/public-domain/sqlite/dist/shell.c (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
111be35a1SLionel Sambuc /*
211be35a1SLionel Sambuc ** 2001 September 15
311be35a1SLionel Sambuc **
411be35a1SLionel Sambuc ** The author disclaims copyright to this source code.  In place of
511be35a1SLionel Sambuc ** a legal notice, here is a blessing:
611be35a1SLionel Sambuc **
711be35a1SLionel Sambuc **    May you do good and not evil.
811be35a1SLionel Sambuc **    May you find forgiveness for yourself and forgive others.
911be35a1SLionel Sambuc **    May you share freely, never taking more than you give.
1011be35a1SLionel Sambuc **
1111be35a1SLionel Sambuc *************************************************************************
1211be35a1SLionel Sambuc ** This file contains code to implement the "sqlite" command line
1311be35a1SLionel Sambuc ** utility for accessing SQLite databases.
1411be35a1SLionel Sambuc */
1511be35a1SLionel Sambuc #if (defined(_WIN32) || defined(WIN32)) && !defined(_CRT_SECURE_NO_WARNINGS)
1611be35a1SLionel Sambuc /* This needs to come before any includes for MSVC compiler */
1711be35a1SLionel Sambuc #define _CRT_SECURE_NO_WARNINGS
1811be35a1SLionel Sambuc #endif
1911be35a1SLionel Sambuc 
2011be35a1SLionel Sambuc /*
2111be35a1SLionel Sambuc ** Enable large-file support for fopen() and friends on unix.
2211be35a1SLionel Sambuc */
2311be35a1SLionel Sambuc #ifndef SQLITE_DISABLE_LFS
2411be35a1SLionel Sambuc # define _LARGE_FILE       1
2511be35a1SLionel Sambuc # ifndef _FILE_OFFSET_BITS
2611be35a1SLionel Sambuc #   define _FILE_OFFSET_BITS 64
2711be35a1SLionel Sambuc # endif
2811be35a1SLionel Sambuc # define _LARGEFILE_SOURCE 1
2911be35a1SLionel Sambuc #endif
3011be35a1SLionel Sambuc 
3111be35a1SLionel Sambuc #include <stdlib.h>
3211be35a1SLionel Sambuc #include <string.h>
3311be35a1SLionel Sambuc #include <stdio.h>
3411be35a1SLionel Sambuc #include <assert.h>
3511be35a1SLionel Sambuc #include "sqlite3.h"
3611be35a1SLionel Sambuc #include <ctype.h>
3711be35a1SLionel Sambuc #include <stdarg.h>
3811be35a1SLionel Sambuc 
39*0a6a1f1dSLionel Sambuc #if !defined(_WIN32) && !defined(WIN32)
4011be35a1SLionel Sambuc # include <signal.h>
4111be35a1SLionel Sambuc # if !defined(__RTP__) && !defined(_WRS_KERNEL)
4211be35a1SLionel Sambuc #  include <pwd.h>
4311be35a1SLionel Sambuc # endif
4411be35a1SLionel Sambuc # include <unistd.h>
4511be35a1SLionel Sambuc # include <sys/types.h>
4611be35a1SLionel Sambuc #endif
4711be35a1SLionel Sambuc 
4811be35a1SLionel Sambuc #ifdef HAVE_EDITLINE
4911be35a1SLionel Sambuc # include <editline/editline.h>
5011be35a1SLionel Sambuc #endif
5111be35a1SLionel Sambuc #if defined(HAVE_READLINE) && HAVE_READLINE==1
5211be35a1SLionel Sambuc # include <readline/readline.h>
5311be35a1SLionel Sambuc # include <readline/history.h>
5411be35a1SLionel Sambuc #endif
5511be35a1SLionel Sambuc #if !defined(HAVE_EDITLINE) && (!defined(HAVE_READLINE) || HAVE_READLINE!=1)
5611be35a1SLionel Sambuc # define add_history(X)
5711be35a1SLionel Sambuc # define read_history(X)
5811be35a1SLionel Sambuc # define write_history(X)
5911be35a1SLionel Sambuc # define stifle_history(X)
6011be35a1SLionel Sambuc #endif
6111be35a1SLionel Sambuc 
6211be35a1SLionel Sambuc #if defined(_WIN32) || defined(WIN32)
6311be35a1SLionel Sambuc # include <io.h>
6411be35a1SLionel Sambuc #define isatty(h) _isatty(h)
6511be35a1SLionel Sambuc #define access(f,m) _access((f),(m))
66*0a6a1f1dSLionel Sambuc #undef popen
67*0a6a1f1dSLionel Sambuc #define popen _popen
68*0a6a1f1dSLionel Sambuc #undef pclose
69*0a6a1f1dSLionel Sambuc #define pclose _pclose
7011be35a1SLionel Sambuc #else
7111be35a1SLionel Sambuc /* Make sure isatty() has a prototype.
7211be35a1SLionel Sambuc */
7311be35a1SLionel Sambuc extern int isatty(int);
74*0a6a1f1dSLionel Sambuc 
75*0a6a1f1dSLionel Sambuc /* popen and pclose are not C89 functions and so are sometimes omitted from
76*0a6a1f1dSLionel Sambuc ** the <stdio.h> header */
77*0a6a1f1dSLionel Sambuc extern FILE *popen(const char*,const char*);
78*0a6a1f1dSLionel Sambuc extern int pclose(FILE*);
7911be35a1SLionel Sambuc #endif
8011be35a1SLionel Sambuc 
8111be35a1SLionel Sambuc #if defined(_WIN32_WCE)
8211be35a1SLionel Sambuc /* Windows CE (arm-wince-mingw32ce-gcc) does not provide isatty()
8311be35a1SLionel Sambuc  * thus we always assume that we have a console. That can be
8411be35a1SLionel Sambuc  * overridden with the -batch command line option.
8511be35a1SLionel Sambuc  */
8611be35a1SLionel Sambuc #define isatty(x) 1
8711be35a1SLionel Sambuc #endif
8811be35a1SLionel Sambuc 
8911be35a1SLionel Sambuc /* ctype macros that work with signed characters */
9011be35a1SLionel Sambuc #define IsSpace(X)  isspace((unsigned char)X)
9111be35a1SLionel Sambuc #define IsDigit(X)  isdigit((unsigned char)X)
9211be35a1SLionel Sambuc #define ToLower(X)  (char)tolower((unsigned char)X)
9311be35a1SLionel Sambuc 
94*0a6a1f1dSLionel Sambuc 
95*0a6a1f1dSLionel Sambuc /* True if the timer is enabled */
96*0a6a1f1dSLionel Sambuc static int enableTimer = 0;
97*0a6a1f1dSLionel Sambuc 
98*0a6a1f1dSLionel Sambuc /* Return the current wall-clock time */
timeOfDay(void)99*0a6a1f1dSLionel Sambuc static sqlite3_int64 timeOfDay(void){
100*0a6a1f1dSLionel Sambuc   static sqlite3_vfs *clockVfs = 0;
101*0a6a1f1dSLionel Sambuc   sqlite3_int64 t;
102*0a6a1f1dSLionel Sambuc   if( clockVfs==0 ) clockVfs = sqlite3_vfs_find(0);
103*0a6a1f1dSLionel Sambuc   if( clockVfs->iVersion>=1 && clockVfs->xCurrentTimeInt64!=0 ){
104*0a6a1f1dSLionel Sambuc     clockVfs->xCurrentTimeInt64(clockVfs, &t);
105*0a6a1f1dSLionel Sambuc   }else{
106*0a6a1f1dSLionel Sambuc     double r;
107*0a6a1f1dSLionel Sambuc     clockVfs->xCurrentTime(clockVfs, &r);
108*0a6a1f1dSLionel Sambuc     t = (sqlite3_int64)(r*86400000.0);
109*0a6a1f1dSLionel Sambuc   }
110*0a6a1f1dSLionel Sambuc   return t;
111*0a6a1f1dSLionel Sambuc }
112*0a6a1f1dSLionel Sambuc 
113*0a6a1f1dSLionel Sambuc #if !defined(_WIN32) && !defined(WIN32) && !defined(_WRS_KERNEL) \
114*0a6a1f1dSLionel Sambuc  && !defined(__minux)
11511be35a1SLionel Sambuc #include <sys/time.h>
11611be35a1SLionel Sambuc #include <sys/resource.h>
11711be35a1SLionel Sambuc 
11811be35a1SLionel Sambuc /* Saved resource information for the beginning of an operation */
119*0a6a1f1dSLionel Sambuc static struct rusage sBegin;  /* CPU time at start */
120*0a6a1f1dSLionel Sambuc static sqlite3_int64 iBegin;  /* Wall-clock time at start */
12111be35a1SLionel Sambuc 
12211be35a1SLionel Sambuc /*
12311be35a1SLionel Sambuc ** Begin timing an operation
12411be35a1SLionel Sambuc */
beginTimer(void)12511be35a1SLionel Sambuc static void beginTimer(void){
12611be35a1SLionel Sambuc   if( enableTimer ){
12711be35a1SLionel Sambuc     getrusage(RUSAGE_SELF, &sBegin);
128*0a6a1f1dSLionel Sambuc     iBegin = timeOfDay();
12911be35a1SLionel Sambuc   }
13011be35a1SLionel Sambuc }
13111be35a1SLionel Sambuc 
13211be35a1SLionel Sambuc /* Return the difference of two time_structs in seconds */
timeDiff(struct timeval * pStart,struct timeval * pEnd)13311be35a1SLionel Sambuc static double timeDiff(struct timeval *pStart, struct timeval *pEnd){
13411be35a1SLionel Sambuc   return (pEnd->tv_usec - pStart->tv_usec)*0.000001 +
13511be35a1SLionel Sambuc          (double)(pEnd->tv_sec - pStart->tv_sec);
13611be35a1SLionel Sambuc }
13711be35a1SLionel Sambuc 
13811be35a1SLionel Sambuc /*
13911be35a1SLionel Sambuc ** Print the timing results.
14011be35a1SLionel Sambuc */
endTimer(void)14111be35a1SLionel Sambuc static void endTimer(void){
14211be35a1SLionel Sambuc   if( enableTimer ){
14311be35a1SLionel Sambuc     struct rusage sEnd;
144*0a6a1f1dSLionel Sambuc     sqlite3_int64 iEnd = timeOfDay();
14511be35a1SLionel Sambuc     getrusage(RUSAGE_SELF, &sEnd);
146*0a6a1f1dSLionel Sambuc     printf("Run Time: real %.3f user %f sys %f\n",
147*0a6a1f1dSLionel Sambuc        (iEnd - iBegin)*0.001,
14811be35a1SLionel Sambuc        timeDiff(&sBegin.ru_utime, &sEnd.ru_utime),
14911be35a1SLionel Sambuc        timeDiff(&sBegin.ru_stime, &sEnd.ru_stime));
15011be35a1SLionel Sambuc   }
15111be35a1SLionel Sambuc }
15211be35a1SLionel Sambuc 
15311be35a1SLionel Sambuc #define BEGIN_TIMER beginTimer()
15411be35a1SLionel Sambuc #define END_TIMER endTimer()
15511be35a1SLionel Sambuc #define HAS_TIMER 1
15611be35a1SLionel Sambuc 
15711be35a1SLionel Sambuc #elif (defined(_WIN32) || defined(WIN32))
15811be35a1SLionel Sambuc 
15911be35a1SLionel Sambuc #include <windows.h>
16011be35a1SLionel Sambuc 
16111be35a1SLionel Sambuc /* Saved resource information for the beginning of an operation */
16211be35a1SLionel Sambuc static HANDLE hProcess;
16311be35a1SLionel Sambuc static FILETIME ftKernelBegin;
16411be35a1SLionel Sambuc static FILETIME ftUserBegin;
165*0a6a1f1dSLionel Sambuc static sqlite3_int64 ftWallBegin;
16611be35a1SLionel Sambuc typedef BOOL (WINAPI *GETPROCTIMES)(HANDLE, LPFILETIME, LPFILETIME, LPFILETIME, LPFILETIME);
16711be35a1SLionel Sambuc static GETPROCTIMES getProcessTimesAddr = NULL;
16811be35a1SLionel Sambuc 
16911be35a1SLionel Sambuc /*
17011be35a1SLionel Sambuc ** Check to see if we have timer support.  Return 1 if necessary
17111be35a1SLionel Sambuc ** support found (or found previously).
17211be35a1SLionel Sambuc */
hasTimer(void)17311be35a1SLionel Sambuc static int hasTimer(void){
17411be35a1SLionel Sambuc   if( getProcessTimesAddr ){
17511be35a1SLionel Sambuc     return 1;
17611be35a1SLionel Sambuc   } else {
17711be35a1SLionel Sambuc     /* GetProcessTimes() isn't supported in WIN95 and some other Windows versions.
17811be35a1SLionel Sambuc     ** See if the version we are running on has it, and if it does, save off
17911be35a1SLionel Sambuc     ** a pointer to it and the current process handle.
18011be35a1SLionel Sambuc     */
18111be35a1SLionel Sambuc     hProcess = GetCurrentProcess();
18211be35a1SLionel Sambuc     if( hProcess ){
18311be35a1SLionel Sambuc       HINSTANCE hinstLib = LoadLibrary(TEXT("Kernel32.dll"));
18411be35a1SLionel Sambuc       if( NULL != hinstLib ){
18511be35a1SLionel Sambuc         getProcessTimesAddr = (GETPROCTIMES) GetProcAddress(hinstLib, "GetProcessTimes");
18611be35a1SLionel Sambuc         if( NULL != getProcessTimesAddr ){
18711be35a1SLionel Sambuc           return 1;
18811be35a1SLionel Sambuc         }
18911be35a1SLionel Sambuc         FreeLibrary(hinstLib);
19011be35a1SLionel Sambuc       }
19111be35a1SLionel Sambuc     }
19211be35a1SLionel Sambuc   }
19311be35a1SLionel Sambuc   return 0;
19411be35a1SLionel Sambuc }
19511be35a1SLionel Sambuc 
19611be35a1SLionel Sambuc /*
19711be35a1SLionel Sambuc ** Begin timing an operation
19811be35a1SLionel Sambuc */
beginTimer(void)19911be35a1SLionel Sambuc static void beginTimer(void){
20011be35a1SLionel Sambuc   if( enableTimer && getProcessTimesAddr ){
20111be35a1SLionel Sambuc     FILETIME ftCreation, ftExit;
20211be35a1SLionel Sambuc     getProcessTimesAddr(hProcess, &ftCreation, &ftExit, &ftKernelBegin, &ftUserBegin);
203*0a6a1f1dSLionel Sambuc     ftWallBegin = timeOfDay();
20411be35a1SLionel Sambuc   }
20511be35a1SLionel Sambuc }
20611be35a1SLionel Sambuc 
20711be35a1SLionel Sambuc /* Return the difference of two FILETIME structs in seconds */
timeDiff(FILETIME * pStart,FILETIME * pEnd)20811be35a1SLionel Sambuc static double timeDiff(FILETIME *pStart, FILETIME *pEnd){
20911be35a1SLionel Sambuc   sqlite_int64 i64Start = *((sqlite_int64 *) pStart);
21011be35a1SLionel Sambuc   sqlite_int64 i64End = *((sqlite_int64 *) pEnd);
21111be35a1SLionel Sambuc   return (double) ((i64End - i64Start) / 10000000.0);
21211be35a1SLionel Sambuc }
21311be35a1SLionel Sambuc 
21411be35a1SLionel Sambuc /*
21511be35a1SLionel Sambuc ** Print the timing results.
21611be35a1SLionel Sambuc */
endTimer(void)21711be35a1SLionel Sambuc static void endTimer(void){
21811be35a1SLionel Sambuc   if( enableTimer && getProcessTimesAddr){
21911be35a1SLionel Sambuc     FILETIME ftCreation, ftExit, ftKernelEnd, ftUserEnd;
220*0a6a1f1dSLionel Sambuc     sqlite3_int64 ftWallEnd = timeOfDay();
22111be35a1SLionel Sambuc     getProcessTimesAddr(hProcess, &ftCreation, &ftExit, &ftKernelEnd, &ftUserEnd);
222*0a6a1f1dSLionel Sambuc     printf("Run Time: real %.3f user %f sys %f\n",
223*0a6a1f1dSLionel Sambuc        (ftWallEnd - ftWallBegin)*0.001,
22411be35a1SLionel Sambuc        timeDiff(&ftUserBegin, &ftUserEnd),
22511be35a1SLionel Sambuc        timeDiff(&ftKernelBegin, &ftKernelEnd));
22611be35a1SLionel Sambuc   }
22711be35a1SLionel Sambuc }
22811be35a1SLionel Sambuc 
22911be35a1SLionel Sambuc #define BEGIN_TIMER beginTimer()
23011be35a1SLionel Sambuc #define END_TIMER endTimer()
23111be35a1SLionel Sambuc #define HAS_TIMER hasTimer()
23211be35a1SLionel Sambuc 
23311be35a1SLionel Sambuc #else
23411be35a1SLionel Sambuc #define BEGIN_TIMER
23511be35a1SLionel Sambuc #define END_TIMER
23611be35a1SLionel Sambuc #define HAS_TIMER 0
23711be35a1SLionel Sambuc #endif
23811be35a1SLionel Sambuc 
23911be35a1SLionel Sambuc /*
24011be35a1SLionel Sambuc ** Used to prevent warnings about unused parameters
24111be35a1SLionel Sambuc */
24211be35a1SLionel Sambuc #define UNUSED_PARAMETER(x) (void)(x)
24311be35a1SLionel Sambuc 
24411be35a1SLionel Sambuc /*
24511be35a1SLionel Sambuc ** If the following flag is set, then command execution stops
24611be35a1SLionel Sambuc ** at an error if we are not interactive.
24711be35a1SLionel Sambuc */
24811be35a1SLionel Sambuc static int bail_on_error = 0;
24911be35a1SLionel Sambuc 
25011be35a1SLionel Sambuc /*
25111be35a1SLionel Sambuc ** Threat stdin as an interactive input if the following variable
25211be35a1SLionel Sambuc ** is true.  Otherwise, assume stdin is connected to a file or pipe.
25311be35a1SLionel Sambuc */
25411be35a1SLionel Sambuc static int stdin_is_interactive = 1;
25511be35a1SLionel Sambuc 
25611be35a1SLionel Sambuc /*
25711be35a1SLionel Sambuc ** The following is the open SQLite database.  We make a pointer
25811be35a1SLionel Sambuc ** to this database a static variable so that it can be accessed
25911be35a1SLionel Sambuc ** by the SIGINT handler to interrupt database processing.
26011be35a1SLionel Sambuc */
26111be35a1SLionel Sambuc static sqlite3 *db = 0;
26211be35a1SLionel Sambuc 
26311be35a1SLionel Sambuc /*
26411be35a1SLionel Sambuc ** True if an interrupt (Control-C) has been received.
26511be35a1SLionel Sambuc */
26611be35a1SLionel Sambuc static volatile int seenInterrupt = 0;
26711be35a1SLionel Sambuc 
26811be35a1SLionel Sambuc /*
26911be35a1SLionel Sambuc ** This is the name of our program. It is set in main(), used
27011be35a1SLionel Sambuc ** in a number of other places, mostly for error messages.
27111be35a1SLionel Sambuc */
27211be35a1SLionel Sambuc static char *Argv0;
27311be35a1SLionel Sambuc 
27411be35a1SLionel Sambuc /*
27511be35a1SLionel Sambuc ** Prompt strings. Initialized in main. Settable with
27611be35a1SLionel Sambuc **   .prompt main continue
27711be35a1SLionel Sambuc */
27811be35a1SLionel Sambuc static char mainPrompt[20];     /* First line prompt. default: "sqlite> "*/
27911be35a1SLionel Sambuc static char continuePrompt[20]; /* Continuation prompt. default: "   ...> " */
28011be35a1SLionel Sambuc 
28111be35a1SLionel Sambuc /*
28211be35a1SLionel Sambuc ** Write I/O traces to the following stream.
28311be35a1SLionel Sambuc */
28411be35a1SLionel Sambuc #ifdef SQLITE_ENABLE_IOTRACE
28511be35a1SLionel Sambuc static FILE *iotrace = 0;
28611be35a1SLionel Sambuc #endif
28711be35a1SLionel Sambuc 
28811be35a1SLionel Sambuc /*
28911be35a1SLionel Sambuc ** This routine works like printf in that its first argument is a
29011be35a1SLionel Sambuc ** format string and subsequent arguments are values to be substituted
29111be35a1SLionel Sambuc ** in place of % fields.  The result of formatting this string
29211be35a1SLionel Sambuc ** is written to iotrace.
29311be35a1SLionel Sambuc */
29411be35a1SLionel Sambuc #ifdef SQLITE_ENABLE_IOTRACE
iotracePrintf(const char * zFormat,...)29511be35a1SLionel Sambuc static void iotracePrintf(const char *zFormat, ...){
29611be35a1SLionel Sambuc   va_list ap;
29711be35a1SLionel Sambuc   char *z;
29811be35a1SLionel Sambuc   if( iotrace==0 ) return;
29911be35a1SLionel Sambuc   va_start(ap, zFormat);
30011be35a1SLionel Sambuc   z = sqlite3_vmprintf(zFormat, ap);
30111be35a1SLionel Sambuc   va_end(ap);
30211be35a1SLionel Sambuc   fprintf(iotrace, "%s", z);
30311be35a1SLionel Sambuc   sqlite3_free(z);
30411be35a1SLionel Sambuc }
30511be35a1SLionel Sambuc #endif
30611be35a1SLionel Sambuc 
30711be35a1SLionel Sambuc 
30811be35a1SLionel Sambuc /*
30911be35a1SLionel Sambuc ** Determines if a string is a number of not.
31011be35a1SLionel Sambuc */
isNumber(const char * z,int * realnum)31111be35a1SLionel Sambuc static int isNumber(const char *z, int *realnum){
31211be35a1SLionel Sambuc   if( *z=='-' || *z=='+' ) z++;
31311be35a1SLionel Sambuc   if( !IsDigit(*z) ){
31411be35a1SLionel Sambuc     return 0;
31511be35a1SLionel Sambuc   }
31611be35a1SLionel Sambuc   z++;
31711be35a1SLionel Sambuc   if( realnum ) *realnum = 0;
31811be35a1SLionel Sambuc   while( IsDigit(*z) ){ z++; }
31911be35a1SLionel Sambuc   if( *z=='.' ){
32011be35a1SLionel Sambuc     z++;
32111be35a1SLionel Sambuc     if( !IsDigit(*z) ) return 0;
32211be35a1SLionel Sambuc     while( IsDigit(*z) ){ z++; }
32311be35a1SLionel Sambuc     if( realnum ) *realnum = 1;
32411be35a1SLionel Sambuc   }
32511be35a1SLionel Sambuc   if( *z=='e' || *z=='E' ){
32611be35a1SLionel Sambuc     z++;
32711be35a1SLionel Sambuc     if( *z=='+' || *z=='-' ) z++;
32811be35a1SLionel Sambuc     if( !IsDigit(*z) ) return 0;
32911be35a1SLionel Sambuc     while( IsDigit(*z) ){ z++; }
33011be35a1SLionel Sambuc     if( realnum ) *realnum = 1;
33111be35a1SLionel Sambuc   }
33211be35a1SLionel Sambuc   return *z==0;
33311be35a1SLionel Sambuc }
33411be35a1SLionel Sambuc 
33511be35a1SLionel Sambuc /*
33611be35a1SLionel Sambuc ** A global char* and an SQL function to access its current value
33711be35a1SLionel Sambuc ** from within an SQL statement. This program used to use the
33811be35a1SLionel Sambuc ** sqlite_exec_printf() API to substitue a string into an SQL statement.
33911be35a1SLionel Sambuc ** The correct way to do this with sqlite3 is to use the bind API, but
34011be35a1SLionel Sambuc ** since the shell is built around the callback paradigm it would be a lot
34111be35a1SLionel Sambuc ** of work. Instead just use this hack, which is quite harmless.
34211be35a1SLionel Sambuc */
34311be35a1SLionel Sambuc static const char *zShellStatic = 0;
shellstaticFunc(sqlite3_context * context,int argc,sqlite3_value ** argv)34411be35a1SLionel Sambuc static void shellstaticFunc(
34511be35a1SLionel Sambuc   sqlite3_context *context,
34611be35a1SLionel Sambuc   int argc,
34711be35a1SLionel Sambuc   sqlite3_value **argv
34811be35a1SLionel Sambuc ){
34911be35a1SLionel Sambuc   assert( 0==argc );
35011be35a1SLionel Sambuc   assert( zShellStatic );
35111be35a1SLionel Sambuc   UNUSED_PARAMETER(argc);
35211be35a1SLionel Sambuc   UNUSED_PARAMETER(argv);
35311be35a1SLionel Sambuc   sqlite3_result_text(context, zShellStatic, -1, SQLITE_STATIC);
35411be35a1SLionel Sambuc }
35511be35a1SLionel Sambuc 
35611be35a1SLionel Sambuc 
35711be35a1SLionel Sambuc /*
35811be35a1SLionel Sambuc ** This routine reads a line of text from FILE in, stores
35911be35a1SLionel Sambuc ** the text in memory obtained from malloc() and returns a pointer
36011be35a1SLionel Sambuc ** to the text.  NULL is returned at end of file, or if malloc()
36111be35a1SLionel Sambuc ** fails.
36211be35a1SLionel Sambuc **
363*0a6a1f1dSLionel Sambuc ** If zLine is not NULL then it is a malloced buffer returned from
364*0a6a1f1dSLionel Sambuc ** a previous call to this routine that may be reused.
36511be35a1SLionel Sambuc */
local_getline(char * zLine,FILE * in)366*0a6a1f1dSLionel Sambuc static char *local_getline(char *zLine, FILE *in){
367*0a6a1f1dSLionel Sambuc   int nLine = zLine==0 ? 0 : 100;
368*0a6a1f1dSLionel Sambuc   int n = 0;
36911be35a1SLionel Sambuc 
37011be35a1SLionel Sambuc   while( 1 ){
37111be35a1SLionel Sambuc     if( n+100>nLine ){
37211be35a1SLionel Sambuc       nLine = nLine*2 + 100;
37311be35a1SLionel Sambuc       zLine = realloc(zLine, nLine);
37411be35a1SLionel Sambuc       if( zLine==0 ) return 0;
37511be35a1SLionel Sambuc     }
37611be35a1SLionel Sambuc     if( fgets(&zLine[n], nLine - n, in)==0 ){
37711be35a1SLionel Sambuc       if( n==0 ){
37811be35a1SLionel Sambuc         free(zLine);
37911be35a1SLionel Sambuc         return 0;
38011be35a1SLionel Sambuc       }
38111be35a1SLionel Sambuc       zLine[n] = 0;
38211be35a1SLionel Sambuc       break;
38311be35a1SLionel Sambuc     }
384*0a6a1f1dSLionel Sambuc     while( zLine[n] ) n++;
38511be35a1SLionel Sambuc     if( n>0 && zLine[n-1]=='\n' ){
38611be35a1SLionel Sambuc       n--;
38711be35a1SLionel Sambuc       if( n>0 && zLine[n-1]=='\r' ) n--;
38811be35a1SLionel Sambuc       zLine[n] = 0;
38911be35a1SLionel Sambuc       break;
39011be35a1SLionel Sambuc     }
39111be35a1SLionel Sambuc   }
39211be35a1SLionel Sambuc   return zLine;
39311be35a1SLionel Sambuc }
39411be35a1SLionel Sambuc 
39511be35a1SLionel Sambuc /*
39611be35a1SLionel Sambuc ** Retrieve a single line of input text.
39711be35a1SLionel Sambuc **
398*0a6a1f1dSLionel Sambuc ** If in==0 then read from standard input and prompt before each line.
399*0a6a1f1dSLionel Sambuc ** If isContinuation is true, then a continuation prompt is appropriate.
400*0a6a1f1dSLionel Sambuc ** If isContinuation is zero, then the main prompt should be used.
401*0a6a1f1dSLionel Sambuc **
402*0a6a1f1dSLionel Sambuc ** If zPrior is not NULL then it is a buffer from a prior call to this
403*0a6a1f1dSLionel Sambuc ** routine that can be reused.
404*0a6a1f1dSLionel Sambuc **
405*0a6a1f1dSLionel Sambuc ** The result is stored in space obtained from malloc() and must either
406*0a6a1f1dSLionel Sambuc ** be freed by the caller or else passed back into this routine via the
407*0a6a1f1dSLionel Sambuc ** zPrior argument for reuse.
40811be35a1SLionel Sambuc */
one_input_line(FILE * in,char * zPrior,int isContinuation)409*0a6a1f1dSLionel Sambuc static char *one_input_line(FILE *in, char *zPrior, int isContinuation){
41011be35a1SLionel Sambuc   char *zPrompt;
41111be35a1SLionel Sambuc   char *zResult;
41211be35a1SLionel Sambuc   if( in!=0 ){
413*0a6a1f1dSLionel Sambuc     zResult = local_getline(zPrior, in);
41411be35a1SLionel Sambuc   }else{
415*0a6a1f1dSLionel Sambuc     zPrompt = isContinuation ? continuePrompt : mainPrompt;
41611be35a1SLionel Sambuc #if defined(HAVE_READLINE) && HAVE_READLINE==1
417*0a6a1f1dSLionel Sambuc     free(zPrior);
418*0a6a1f1dSLionel Sambuc     zResult = readline(zPrompt);
41911be35a1SLionel Sambuc     if( zResult && *zResult ) add_history(zResult);
420*0a6a1f1dSLionel Sambuc #else
421*0a6a1f1dSLionel Sambuc     printf("%s", zPrompt);
422*0a6a1f1dSLionel Sambuc     fflush(stdout);
423*0a6a1f1dSLionel Sambuc     zResult = local_getline(zPrior, stdin);
42411be35a1SLionel Sambuc #endif
425*0a6a1f1dSLionel Sambuc   }
42611be35a1SLionel Sambuc   return zResult;
42711be35a1SLionel Sambuc }
42811be35a1SLionel Sambuc 
42911be35a1SLionel Sambuc struct previous_mode_data {
43011be35a1SLionel Sambuc   int valid;        /* Is there legit data in here? */
43111be35a1SLionel Sambuc   int mode;
43211be35a1SLionel Sambuc   int showHeader;
43311be35a1SLionel Sambuc   int colWidth[100];
43411be35a1SLionel Sambuc };
43511be35a1SLionel Sambuc 
43611be35a1SLionel Sambuc /*
43711be35a1SLionel Sambuc ** An pointer to an instance of this structure is passed from
43811be35a1SLionel Sambuc ** the main program to the callback.  This is used to communicate
43911be35a1SLionel Sambuc ** state and mode information.
44011be35a1SLionel Sambuc */
44111be35a1SLionel Sambuc struct callback_data {
44211be35a1SLionel Sambuc   sqlite3 *db;           /* The database */
44311be35a1SLionel Sambuc   int echoOn;            /* True to echo input commands */
44411be35a1SLionel Sambuc   int statsOn;           /* True to display memory stats before each finalize */
44511be35a1SLionel Sambuc   int cnt;               /* Number of records displayed so far */
44611be35a1SLionel Sambuc   FILE *out;             /* Write results here */
447*0a6a1f1dSLionel Sambuc   FILE *traceOut;        /* Output for sqlite3_trace() */
44811be35a1SLionel Sambuc   int nErr;              /* Number of errors seen */
44911be35a1SLionel Sambuc   int mode;              /* An output mode setting */
45011be35a1SLionel Sambuc   int writableSchema;    /* True if PRAGMA writable_schema=ON */
45111be35a1SLionel Sambuc   int showHeader;        /* True to show column names in List or Column mode */
45211be35a1SLionel Sambuc   char *zDestTable;      /* Name of destination table when MODE_Insert */
45311be35a1SLionel Sambuc   char separator[20];    /* Separator character for MODE_List */
45411be35a1SLionel Sambuc   int colWidth[100];     /* Requested width of each column when in column mode*/
45511be35a1SLionel Sambuc   int actualWidth[100];  /* Actual width of each column */
45611be35a1SLionel Sambuc   char nullvalue[20];    /* The text to print when a NULL comes back from
45711be35a1SLionel Sambuc                          ** the database */
45811be35a1SLionel Sambuc   struct previous_mode_data explainPrev;
45911be35a1SLionel Sambuc                          /* Holds the mode information just before
46011be35a1SLionel Sambuc                          ** .explain ON */
46111be35a1SLionel Sambuc   char outfile[FILENAME_MAX]; /* Filename for *out */
46211be35a1SLionel Sambuc   const char *zDbFilename;    /* name of the database file */
463*0a6a1f1dSLionel Sambuc   char *zFreeOnClose;         /* Filename to free when closing */
46411be35a1SLionel Sambuc   const char *zVfs;           /* Name of VFS to use */
46511be35a1SLionel Sambuc   sqlite3_stmt *pStmt;   /* Current statement if any. */
46611be35a1SLionel Sambuc   FILE *pLog;            /* Write log output here */
467*0a6a1f1dSLionel Sambuc   int *aiIndent;         /* Array of indents used in MODE_Explain */
468*0a6a1f1dSLionel Sambuc   int nIndent;           /* Size of array aiIndent[] */
469*0a6a1f1dSLionel Sambuc   int iIndent;           /* Index of current op in aiIndent[] */
47011be35a1SLionel Sambuc };
47111be35a1SLionel Sambuc 
47211be35a1SLionel Sambuc /*
47311be35a1SLionel Sambuc ** These are the allowed modes.
47411be35a1SLionel Sambuc */
47511be35a1SLionel Sambuc #define MODE_Line     0  /* One column per line.  Blank line between records */
47611be35a1SLionel Sambuc #define MODE_Column   1  /* One record per line in neat columns */
47711be35a1SLionel Sambuc #define MODE_List     2  /* One record per line with a separator */
47811be35a1SLionel Sambuc #define MODE_Semi     3  /* Same as MODE_List but append ";" to each line */
47911be35a1SLionel Sambuc #define MODE_Html     4  /* Generate an XHTML table */
48011be35a1SLionel Sambuc #define MODE_Insert   5  /* Generate SQL "insert" statements */
48111be35a1SLionel Sambuc #define MODE_Tcl      6  /* Generate ANSI-C or TCL quoted elements */
48211be35a1SLionel Sambuc #define MODE_Csv      7  /* Quote strings, numbers are plain */
48311be35a1SLionel Sambuc #define MODE_Explain  8  /* Like MODE_Column, but do not truncate data */
48411be35a1SLionel Sambuc 
48511be35a1SLionel Sambuc static const char *modeDescr[] = {
48611be35a1SLionel Sambuc   "line",
48711be35a1SLionel Sambuc   "column",
48811be35a1SLionel Sambuc   "list",
48911be35a1SLionel Sambuc   "semi",
49011be35a1SLionel Sambuc   "html",
49111be35a1SLionel Sambuc   "insert",
49211be35a1SLionel Sambuc   "tcl",
49311be35a1SLionel Sambuc   "csv",
49411be35a1SLionel Sambuc   "explain",
49511be35a1SLionel Sambuc };
49611be35a1SLionel Sambuc 
49711be35a1SLionel Sambuc /*
49811be35a1SLionel Sambuc ** Number of elements in an array
49911be35a1SLionel Sambuc */
50011be35a1SLionel Sambuc #define ArraySize(X)  (int)(sizeof(X)/sizeof(X[0]))
50111be35a1SLionel Sambuc 
50211be35a1SLionel Sambuc /*
50311be35a1SLionel Sambuc ** Compute a string length that is limited to what can be stored in
50411be35a1SLionel Sambuc ** lower 30 bits of a 32-bit signed integer.
50511be35a1SLionel Sambuc */
strlen30(const char * z)50611be35a1SLionel Sambuc static int strlen30(const char *z){
50711be35a1SLionel Sambuc   const char *z2 = z;
50811be35a1SLionel Sambuc   while( *z2 ){ z2++; }
50911be35a1SLionel Sambuc   return 0x3fffffff & (int)(z2 - z);
51011be35a1SLionel Sambuc }
51111be35a1SLionel Sambuc 
51211be35a1SLionel Sambuc /*
51311be35a1SLionel Sambuc ** A callback for the sqlite3_log() interface.
51411be35a1SLionel Sambuc */
shellLog(void * pArg,int iErrCode,const char * zMsg)51511be35a1SLionel Sambuc static void shellLog(void *pArg, int iErrCode, const char *zMsg){
51611be35a1SLionel Sambuc   struct callback_data *p = (struct callback_data*)pArg;
51711be35a1SLionel Sambuc   if( p->pLog==0 ) return;
51811be35a1SLionel Sambuc   fprintf(p->pLog, "(%d) %s\n", iErrCode, zMsg);
51911be35a1SLionel Sambuc   fflush(p->pLog);
52011be35a1SLionel Sambuc }
52111be35a1SLionel Sambuc 
52211be35a1SLionel Sambuc /*
52311be35a1SLionel Sambuc ** Output the given string as a hex-encoded blob (eg. X'1234' )
52411be35a1SLionel Sambuc */
output_hex_blob(FILE * out,const void * pBlob,int nBlob)52511be35a1SLionel Sambuc static void output_hex_blob(FILE *out, const void *pBlob, int nBlob){
52611be35a1SLionel Sambuc   int i;
52711be35a1SLionel Sambuc   char *zBlob = (char *)pBlob;
52811be35a1SLionel Sambuc   fprintf(out,"X'");
529*0a6a1f1dSLionel Sambuc   for(i=0; i<nBlob; i++){ fprintf(out,"%02x",zBlob[i]&0xff); }
53011be35a1SLionel Sambuc   fprintf(out,"'");
53111be35a1SLionel Sambuc }
53211be35a1SLionel Sambuc 
53311be35a1SLionel Sambuc /*
53411be35a1SLionel Sambuc ** Output the given string as a quoted string using SQL quoting conventions.
53511be35a1SLionel Sambuc */
output_quoted_string(FILE * out,const char * z)53611be35a1SLionel Sambuc static void output_quoted_string(FILE *out, const char *z){
53711be35a1SLionel Sambuc   int i;
53811be35a1SLionel Sambuc   int nSingle = 0;
53911be35a1SLionel Sambuc   for(i=0; z[i]; i++){
54011be35a1SLionel Sambuc     if( z[i]=='\'' ) nSingle++;
54111be35a1SLionel Sambuc   }
54211be35a1SLionel Sambuc   if( nSingle==0 ){
54311be35a1SLionel Sambuc     fprintf(out,"'%s'",z);
54411be35a1SLionel Sambuc   }else{
54511be35a1SLionel Sambuc     fprintf(out,"'");
54611be35a1SLionel Sambuc     while( *z ){
54711be35a1SLionel Sambuc       for(i=0; z[i] && z[i]!='\''; i++){}
54811be35a1SLionel Sambuc       if( i==0 ){
54911be35a1SLionel Sambuc         fprintf(out,"''");
55011be35a1SLionel Sambuc         z++;
55111be35a1SLionel Sambuc       }else if( z[i]=='\'' ){
55211be35a1SLionel Sambuc         fprintf(out,"%.*s''",i,z);
55311be35a1SLionel Sambuc         z += i+1;
55411be35a1SLionel Sambuc       }else{
55511be35a1SLionel Sambuc         fprintf(out,"%s",z);
55611be35a1SLionel Sambuc         break;
55711be35a1SLionel Sambuc       }
55811be35a1SLionel Sambuc     }
55911be35a1SLionel Sambuc     fprintf(out,"'");
56011be35a1SLionel Sambuc   }
56111be35a1SLionel Sambuc }
56211be35a1SLionel Sambuc 
56311be35a1SLionel Sambuc /*
56411be35a1SLionel Sambuc ** Output the given string as a quoted according to C or TCL quoting rules.
56511be35a1SLionel Sambuc */
output_c_string(FILE * out,const char * z)56611be35a1SLionel Sambuc static void output_c_string(FILE *out, const char *z){
56711be35a1SLionel Sambuc   unsigned int c;
56811be35a1SLionel Sambuc   fputc('"', out);
56911be35a1SLionel Sambuc   while( (c = *(z++))!=0 ){
57011be35a1SLionel Sambuc     if( c=='\\' ){
57111be35a1SLionel Sambuc       fputc(c, out);
57211be35a1SLionel Sambuc       fputc(c, out);
573*0a6a1f1dSLionel Sambuc     }else if( c=='"' ){
574*0a6a1f1dSLionel Sambuc       fputc('\\', out);
575*0a6a1f1dSLionel Sambuc       fputc('"', out);
57611be35a1SLionel Sambuc     }else if( c=='\t' ){
57711be35a1SLionel Sambuc       fputc('\\', out);
57811be35a1SLionel Sambuc       fputc('t', out);
57911be35a1SLionel Sambuc     }else if( c=='\n' ){
58011be35a1SLionel Sambuc       fputc('\\', out);
58111be35a1SLionel Sambuc       fputc('n', out);
58211be35a1SLionel Sambuc     }else if( c=='\r' ){
58311be35a1SLionel Sambuc       fputc('\\', out);
58411be35a1SLionel Sambuc       fputc('r', out);
585*0a6a1f1dSLionel Sambuc     }else if( !isprint(c&0xff) ){
58611be35a1SLionel Sambuc       fprintf(out, "\\%03o", c&0xff);
58711be35a1SLionel Sambuc     }else{
58811be35a1SLionel Sambuc       fputc(c, out);
58911be35a1SLionel Sambuc     }
59011be35a1SLionel Sambuc   }
59111be35a1SLionel Sambuc   fputc('"', out);
59211be35a1SLionel Sambuc }
59311be35a1SLionel Sambuc 
59411be35a1SLionel Sambuc /*
59511be35a1SLionel Sambuc ** Output the given string with characters that are special to
59611be35a1SLionel Sambuc ** HTML escaped.
59711be35a1SLionel Sambuc */
output_html_string(FILE * out,const char * z)59811be35a1SLionel Sambuc static void output_html_string(FILE *out, const char *z){
59911be35a1SLionel Sambuc   int i;
600*0a6a1f1dSLionel Sambuc   if( z==0 ) z = "";
60111be35a1SLionel Sambuc   while( *z ){
60211be35a1SLionel Sambuc     for(i=0;   z[i]
60311be35a1SLionel Sambuc             && z[i]!='<'
60411be35a1SLionel Sambuc             && z[i]!='&'
60511be35a1SLionel Sambuc             && z[i]!='>'
60611be35a1SLionel Sambuc             && z[i]!='\"'
60711be35a1SLionel Sambuc             && z[i]!='\'';
60811be35a1SLionel Sambuc         i++){}
60911be35a1SLionel Sambuc     if( i>0 ){
61011be35a1SLionel Sambuc       fprintf(out,"%.*s",i,z);
61111be35a1SLionel Sambuc     }
61211be35a1SLionel Sambuc     if( z[i]=='<' ){
61311be35a1SLionel Sambuc       fprintf(out,"&lt;");
61411be35a1SLionel Sambuc     }else if( z[i]=='&' ){
61511be35a1SLionel Sambuc       fprintf(out,"&amp;");
61611be35a1SLionel Sambuc     }else if( z[i]=='>' ){
61711be35a1SLionel Sambuc       fprintf(out,"&gt;");
61811be35a1SLionel Sambuc     }else if( z[i]=='\"' ){
61911be35a1SLionel Sambuc       fprintf(out,"&quot;");
62011be35a1SLionel Sambuc     }else if( z[i]=='\'' ){
62111be35a1SLionel Sambuc       fprintf(out,"&#39;");
62211be35a1SLionel Sambuc     }else{
62311be35a1SLionel Sambuc       break;
62411be35a1SLionel Sambuc     }
62511be35a1SLionel Sambuc     z += i + 1;
62611be35a1SLionel Sambuc   }
62711be35a1SLionel Sambuc }
62811be35a1SLionel Sambuc 
62911be35a1SLionel Sambuc /*
63011be35a1SLionel Sambuc ** If a field contains any character identified by a 1 in the following
63111be35a1SLionel Sambuc ** array, then the string must be quoted for CSV.
63211be35a1SLionel Sambuc */
63311be35a1SLionel Sambuc static const char needCsvQuote[] = {
63411be35a1SLionel Sambuc   1, 1, 1, 1, 1, 1, 1, 1,   1, 1, 1, 1, 1, 1, 1, 1,
63511be35a1SLionel Sambuc   1, 1, 1, 1, 1, 1, 1, 1,   1, 1, 1, 1, 1, 1, 1, 1,
63611be35a1SLionel Sambuc   1, 0, 1, 0, 0, 0, 0, 1,   0, 0, 0, 0, 0, 0, 0, 0,
63711be35a1SLionel Sambuc   0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0,
63811be35a1SLionel Sambuc   0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0,
63911be35a1SLionel Sambuc   0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0,
64011be35a1SLionel Sambuc   0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0,
64111be35a1SLionel Sambuc   0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 1,
64211be35a1SLionel Sambuc   1, 1, 1, 1, 1, 1, 1, 1,   1, 1, 1, 1, 1, 1, 1, 1,
64311be35a1SLionel Sambuc   1, 1, 1, 1, 1, 1, 1, 1,   1, 1, 1, 1, 1, 1, 1, 1,
64411be35a1SLionel Sambuc   1, 1, 1, 1, 1, 1, 1, 1,   1, 1, 1, 1, 1, 1, 1, 1,
64511be35a1SLionel Sambuc   1, 1, 1, 1, 1, 1, 1, 1,   1, 1, 1, 1, 1, 1, 1, 1,
64611be35a1SLionel Sambuc   1, 1, 1, 1, 1, 1, 1, 1,   1, 1, 1, 1, 1, 1, 1, 1,
64711be35a1SLionel Sambuc   1, 1, 1, 1, 1, 1, 1, 1,   1, 1, 1, 1, 1, 1, 1, 1,
64811be35a1SLionel Sambuc   1, 1, 1, 1, 1, 1, 1, 1,   1, 1, 1, 1, 1, 1, 1, 1,
64911be35a1SLionel Sambuc   1, 1, 1, 1, 1, 1, 1, 1,   1, 1, 1, 1, 1, 1, 1, 1,
65011be35a1SLionel Sambuc };
65111be35a1SLionel Sambuc 
65211be35a1SLionel Sambuc /*
65311be35a1SLionel Sambuc ** Output a single term of CSV.  Actually, p->separator is used for
65411be35a1SLionel Sambuc ** the separator, which may or may not be a comma.  p->nullvalue is
655*0a6a1f1dSLionel Sambuc ** the null value.  Strings are quoted if necessary.
65611be35a1SLionel Sambuc */
output_csv(struct callback_data * p,const char * z,int bSep)65711be35a1SLionel Sambuc static void output_csv(struct callback_data *p, const char *z, int bSep){
65811be35a1SLionel Sambuc   FILE *out = p->out;
65911be35a1SLionel Sambuc   if( z==0 ){
66011be35a1SLionel Sambuc     fprintf(out,"%s",p->nullvalue);
66111be35a1SLionel Sambuc   }else{
66211be35a1SLionel Sambuc     int i;
66311be35a1SLionel Sambuc     int nSep = strlen30(p->separator);
66411be35a1SLionel Sambuc     for(i=0; z[i]; i++){
66511be35a1SLionel Sambuc       if( needCsvQuote[((unsigned char*)z)[i]]
66611be35a1SLionel Sambuc          || (z[i]==p->separator[0] &&
66711be35a1SLionel Sambuc              (nSep==1 || memcmp(z, p->separator, nSep)==0)) ){
66811be35a1SLionel Sambuc         i = 0;
66911be35a1SLionel Sambuc         break;
67011be35a1SLionel Sambuc       }
67111be35a1SLionel Sambuc     }
67211be35a1SLionel Sambuc     if( i==0 ){
67311be35a1SLionel Sambuc       putc('"', out);
67411be35a1SLionel Sambuc       for(i=0; z[i]; i++){
67511be35a1SLionel Sambuc         if( z[i]=='"' ) putc('"', out);
67611be35a1SLionel Sambuc         putc(z[i], out);
67711be35a1SLionel Sambuc       }
67811be35a1SLionel Sambuc       putc('"', out);
67911be35a1SLionel Sambuc     }else{
68011be35a1SLionel Sambuc       fprintf(out, "%s", z);
68111be35a1SLionel Sambuc     }
68211be35a1SLionel Sambuc   }
68311be35a1SLionel Sambuc   if( bSep ){
68411be35a1SLionel Sambuc     fprintf(p->out, "%s", p->separator);
68511be35a1SLionel Sambuc   }
68611be35a1SLionel Sambuc }
68711be35a1SLionel Sambuc 
68811be35a1SLionel Sambuc #ifdef SIGINT
68911be35a1SLionel Sambuc /*
69011be35a1SLionel Sambuc ** This routine runs when the user presses Ctrl-C
69111be35a1SLionel Sambuc */
interrupt_handler(int NotUsed)69211be35a1SLionel Sambuc static void interrupt_handler(int NotUsed){
69311be35a1SLionel Sambuc   UNUSED_PARAMETER(NotUsed);
69411be35a1SLionel Sambuc   seenInterrupt = 1;
69511be35a1SLionel Sambuc   if( db ) sqlite3_interrupt(db);
69611be35a1SLionel Sambuc }
69711be35a1SLionel Sambuc #endif
69811be35a1SLionel Sambuc 
69911be35a1SLionel Sambuc /*
70011be35a1SLionel Sambuc ** This is the callback routine that the shell
70111be35a1SLionel Sambuc ** invokes for each row of a query result.
70211be35a1SLionel Sambuc */
shell_callback(void * pArg,int nArg,char ** azArg,char ** azCol,int * aiType)70311be35a1SLionel Sambuc static int shell_callback(void *pArg, int nArg, char **azArg, char **azCol, int *aiType){
70411be35a1SLionel Sambuc   int i;
70511be35a1SLionel Sambuc   struct callback_data *p = (struct callback_data*)pArg;
70611be35a1SLionel Sambuc 
70711be35a1SLionel Sambuc   switch( p->mode ){
70811be35a1SLionel Sambuc     case MODE_Line: {
70911be35a1SLionel Sambuc       int w = 5;
71011be35a1SLionel Sambuc       if( azArg==0 ) break;
71111be35a1SLionel Sambuc       for(i=0; i<nArg; i++){
71211be35a1SLionel Sambuc         int len = strlen30(azCol[i] ? azCol[i] : "");
71311be35a1SLionel Sambuc         if( len>w ) w = len;
71411be35a1SLionel Sambuc       }
71511be35a1SLionel Sambuc       if( p->cnt++>0 ) fprintf(p->out,"\n");
71611be35a1SLionel Sambuc       for(i=0; i<nArg; i++){
71711be35a1SLionel Sambuc         fprintf(p->out,"%*s = %s\n", w, azCol[i],
71811be35a1SLionel Sambuc                 azArg[i] ? azArg[i] : p->nullvalue);
71911be35a1SLionel Sambuc       }
72011be35a1SLionel Sambuc       break;
72111be35a1SLionel Sambuc     }
72211be35a1SLionel Sambuc     case MODE_Explain:
72311be35a1SLionel Sambuc     case MODE_Column: {
72411be35a1SLionel Sambuc       if( p->cnt++==0 ){
72511be35a1SLionel Sambuc         for(i=0; i<nArg; i++){
72611be35a1SLionel Sambuc           int w, n;
72711be35a1SLionel Sambuc           if( i<ArraySize(p->colWidth) ){
72811be35a1SLionel Sambuc             w = p->colWidth[i];
72911be35a1SLionel Sambuc           }else{
73011be35a1SLionel Sambuc             w = 0;
73111be35a1SLionel Sambuc           }
732*0a6a1f1dSLionel Sambuc           if( w==0 ){
73311be35a1SLionel Sambuc             w = strlen30(azCol[i] ? azCol[i] : "");
73411be35a1SLionel Sambuc             if( w<10 ) w = 10;
73511be35a1SLionel Sambuc             n = strlen30(azArg && azArg[i] ? azArg[i] : p->nullvalue);
73611be35a1SLionel Sambuc             if( w<n ) w = n;
73711be35a1SLionel Sambuc           }
73811be35a1SLionel Sambuc           if( i<ArraySize(p->actualWidth) ){
73911be35a1SLionel Sambuc             p->actualWidth[i] = w;
74011be35a1SLionel Sambuc           }
74111be35a1SLionel Sambuc           if( p->showHeader ){
742*0a6a1f1dSLionel Sambuc             if( w<0 ){
743*0a6a1f1dSLionel Sambuc               fprintf(p->out,"%*.*s%s",-w,-w,azCol[i], i==nArg-1 ? "\n": "  ");
744*0a6a1f1dSLionel Sambuc             }else{
74511be35a1SLionel Sambuc               fprintf(p->out,"%-*.*s%s",w,w,azCol[i], i==nArg-1 ? "\n": "  ");
74611be35a1SLionel Sambuc             }
74711be35a1SLionel Sambuc           }
748*0a6a1f1dSLionel Sambuc         }
74911be35a1SLionel Sambuc         if( p->showHeader ){
75011be35a1SLionel Sambuc           for(i=0; i<nArg; i++){
75111be35a1SLionel Sambuc             int w;
75211be35a1SLionel Sambuc             if( i<ArraySize(p->actualWidth) ){
75311be35a1SLionel Sambuc                w = p->actualWidth[i];
754*0a6a1f1dSLionel Sambuc                if( w<0 ) w = -w;
75511be35a1SLionel Sambuc             }else{
75611be35a1SLionel Sambuc                w = 10;
75711be35a1SLionel Sambuc             }
75811be35a1SLionel Sambuc             fprintf(p->out,"%-*.*s%s",w,w,"-----------------------------------"
75911be35a1SLionel Sambuc                    "----------------------------------------------------------",
76011be35a1SLionel Sambuc                     i==nArg-1 ? "\n": "  ");
76111be35a1SLionel Sambuc           }
76211be35a1SLionel Sambuc         }
76311be35a1SLionel Sambuc       }
76411be35a1SLionel Sambuc       if( azArg==0 ) break;
76511be35a1SLionel Sambuc       for(i=0; i<nArg; i++){
76611be35a1SLionel Sambuc         int w;
76711be35a1SLionel Sambuc         if( i<ArraySize(p->actualWidth) ){
76811be35a1SLionel Sambuc            w = p->actualWidth[i];
76911be35a1SLionel Sambuc         }else{
77011be35a1SLionel Sambuc            w = 10;
77111be35a1SLionel Sambuc         }
772*0a6a1f1dSLionel Sambuc         if( p->mode==MODE_Explain && azArg[i] && strlen30(azArg[i])>w ){
77311be35a1SLionel Sambuc           w = strlen30(azArg[i]);
77411be35a1SLionel Sambuc         }
775*0a6a1f1dSLionel Sambuc         if( i==1 && p->aiIndent && p->pStmt ){
776*0a6a1f1dSLionel Sambuc           if( p->iIndent<p->nIndent ){
777*0a6a1f1dSLionel Sambuc             fprintf(p->out, "%*.s", p->aiIndent[p->iIndent], "");
778*0a6a1f1dSLionel Sambuc           }
779*0a6a1f1dSLionel Sambuc           p->iIndent++;
780*0a6a1f1dSLionel Sambuc         }
781*0a6a1f1dSLionel Sambuc         if( w<0 ){
782*0a6a1f1dSLionel Sambuc           fprintf(p->out,"%*.*s%s",-w,-w,
783*0a6a1f1dSLionel Sambuc               azArg[i] ? azArg[i] : p->nullvalue, i==nArg-1 ? "\n": "  ");
784*0a6a1f1dSLionel Sambuc         }else{
78511be35a1SLionel Sambuc           fprintf(p->out,"%-*.*s%s",w,w,
78611be35a1SLionel Sambuc               azArg[i] ? azArg[i] : p->nullvalue, i==nArg-1 ? "\n": "  ");
78711be35a1SLionel Sambuc         }
788*0a6a1f1dSLionel Sambuc       }
78911be35a1SLionel Sambuc       break;
79011be35a1SLionel Sambuc     }
79111be35a1SLionel Sambuc     case MODE_Semi:
79211be35a1SLionel Sambuc     case MODE_List: {
79311be35a1SLionel Sambuc       if( p->cnt++==0 && p->showHeader ){
79411be35a1SLionel Sambuc         for(i=0; i<nArg; i++){
79511be35a1SLionel Sambuc           fprintf(p->out,"%s%s",azCol[i], i==nArg-1 ? "\n" : p->separator);
79611be35a1SLionel Sambuc         }
79711be35a1SLionel Sambuc       }
79811be35a1SLionel Sambuc       if( azArg==0 ) break;
79911be35a1SLionel Sambuc       for(i=0; i<nArg; i++){
80011be35a1SLionel Sambuc         char *z = azArg[i];
80111be35a1SLionel Sambuc         if( z==0 ) z = p->nullvalue;
80211be35a1SLionel Sambuc         fprintf(p->out, "%s", z);
80311be35a1SLionel Sambuc         if( i<nArg-1 ){
80411be35a1SLionel Sambuc           fprintf(p->out, "%s", p->separator);
80511be35a1SLionel Sambuc         }else if( p->mode==MODE_Semi ){
80611be35a1SLionel Sambuc           fprintf(p->out, ";\n");
80711be35a1SLionel Sambuc         }else{
80811be35a1SLionel Sambuc           fprintf(p->out, "\n");
80911be35a1SLionel Sambuc         }
81011be35a1SLionel Sambuc       }
81111be35a1SLionel Sambuc       break;
81211be35a1SLionel Sambuc     }
81311be35a1SLionel Sambuc     case MODE_Html: {
81411be35a1SLionel Sambuc       if( p->cnt++==0 && p->showHeader ){
81511be35a1SLionel Sambuc         fprintf(p->out,"<TR>");
81611be35a1SLionel Sambuc         for(i=0; i<nArg; i++){
81711be35a1SLionel Sambuc           fprintf(p->out,"<TH>");
81811be35a1SLionel Sambuc           output_html_string(p->out, azCol[i]);
81911be35a1SLionel Sambuc           fprintf(p->out,"</TH>\n");
82011be35a1SLionel Sambuc         }
82111be35a1SLionel Sambuc         fprintf(p->out,"</TR>\n");
82211be35a1SLionel Sambuc       }
82311be35a1SLionel Sambuc       if( azArg==0 ) break;
82411be35a1SLionel Sambuc       fprintf(p->out,"<TR>");
82511be35a1SLionel Sambuc       for(i=0; i<nArg; i++){
82611be35a1SLionel Sambuc         fprintf(p->out,"<TD>");
82711be35a1SLionel Sambuc         output_html_string(p->out, azArg[i] ? azArg[i] : p->nullvalue);
82811be35a1SLionel Sambuc         fprintf(p->out,"</TD>\n");
82911be35a1SLionel Sambuc       }
83011be35a1SLionel Sambuc       fprintf(p->out,"</TR>\n");
83111be35a1SLionel Sambuc       break;
83211be35a1SLionel Sambuc     }
83311be35a1SLionel Sambuc     case MODE_Tcl: {
83411be35a1SLionel Sambuc       if( p->cnt++==0 && p->showHeader ){
83511be35a1SLionel Sambuc         for(i=0; i<nArg; i++){
83611be35a1SLionel Sambuc           output_c_string(p->out,azCol[i] ? azCol[i] : "");
837*0a6a1f1dSLionel Sambuc           if(i<nArg-1) fprintf(p->out, "%s", p->separator);
83811be35a1SLionel Sambuc         }
83911be35a1SLionel Sambuc         fprintf(p->out,"\n");
84011be35a1SLionel Sambuc       }
84111be35a1SLionel Sambuc       if( azArg==0 ) break;
84211be35a1SLionel Sambuc       for(i=0; i<nArg; i++){
84311be35a1SLionel Sambuc         output_c_string(p->out, azArg[i] ? azArg[i] : p->nullvalue);
844*0a6a1f1dSLionel Sambuc         if(i<nArg-1) fprintf(p->out, "%s", p->separator);
84511be35a1SLionel Sambuc       }
84611be35a1SLionel Sambuc       fprintf(p->out,"\n");
84711be35a1SLionel Sambuc       break;
84811be35a1SLionel Sambuc     }
84911be35a1SLionel Sambuc     case MODE_Csv: {
85011be35a1SLionel Sambuc       if( p->cnt++==0 && p->showHeader ){
85111be35a1SLionel Sambuc         for(i=0; i<nArg; i++){
85211be35a1SLionel Sambuc           output_csv(p, azCol[i] ? azCol[i] : "", i<nArg-1);
85311be35a1SLionel Sambuc         }
85411be35a1SLionel Sambuc         fprintf(p->out,"\n");
85511be35a1SLionel Sambuc       }
85611be35a1SLionel Sambuc       if( azArg==0 ) break;
85711be35a1SLionel Sambuc       for(i=0; i<nArg; i++){
85811be35a1SLionel Sambuc         output_csv(p, azArg[i], i<nArg-1);
85911be35a1SLionel Sambuc       }
86011be35a1SLionel Sambuc       fprintf(p->out,"\n");
86111be35a1SLionel Sambuc       break;
86211be35a1SLionel Sambuc     }
86311be35a1SLionel Sambuc     case MODE_Insert: {
86411be35a1SLionel Sambuc       p->cnt++;
86511be35a1SLionel Sambuc       if( azArg==0 ) break;
86611be35a1SLionel Sambuc       fprintf(p->out,"INSERT INTO %s VALUES(",p->zDestTable);
86711be35a1SLionel Sambuc       for(i=0; i<nArg; i++){
86811be35a1SLionel Sambuc         char *zSep = i>0 ? ",": "";
86911be35a1SLionel Sambuc         if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){
87011be35a1SLionel Sambuc           fprintf(p->out,"%sNULL",zSep);
87111be35a1SLionel Sambuc         }else if( aiType && aiType[i]==SQLITE_TEXT ){
87211be35a1SLionel Sambuc           if( zSep[0] ) fprintf(p->out,"%s",zSep);
87311be35a1SLionel Sambuc           output_quoted_string(p->out, azArg[i]);
87411be35a1SLionel Sambuc         }else if( aiType && (aiType[i]==SQLITE_INTEGER || aiType[i]==SQLITE_FLOAT) ){
87511be35a1SLionel Sambuc           fprintf(p->out,"%s%s",zSep, azArg[i]);
87611be35a1SLionel Sambuc         }else if( aiType && aiType[i]==SQLITE_BLOB && p->pStmt ){
87711be35a1SLionel Sambuc           const void *pBlob = sqlite3_column_blob(p->pStmt, i);
87811be35a1SLionel Sambuc           int nBlob = sqlite3_column_bytes(p->pStmt, i);
87911be35a1SLionel Sambuc           if( zSep[0] ) fprintf(p->out,"%s",zSep);
88011be35a1SLionel Sambuc           output_hex_blob(p->out, pBlob, nBlob);
88111be35a1SLionel Sambuc         }else if( isNumber(azArg[i], 0) ){
88211be35a1SLionel Sambuc           fprintf(p->out,"%s%s",zSep, azArg[i]);
88311be35a1SLionel Sambuc         }else{
88411be35a1SLionel Sambuc           if( zSep[0] ) fprintf(p->out,"%s",zSep);
88511be35a1SLionel Sambuc           output_quoted_string(p->out, azArg[i]);
88611be35a1SLionel Sambuc         }
88711be35a1SLionel Sambuc       }
88811be35a1SLionel Sambuc       fprintf(p->out,");\n");
88911be35a1SLionel Sambuc       break;
89011be35a1SLionel Sambuc     }
89111be35a1SLionel Sambuc   }
89211be35a1SLionel Sambuc   return 0;
89311be35a1SLionel Sambuc }
89411be35a1SLionel Sambuc 
89511be35a1SLionel Sambuc /*
89611be35a1SLionel Sambuc ** This is the callback routine that the SQLite library
89711be35a1SLionel Sambuc ** invokes for each row of a query result.
89811be35a1SLionel Sambuc */
callback(void * pArg,int nArg,char ** azArg,char ** azCol)89911be35a1SLionel Sambuc static int callback(void *pArg, int nArg, char **azArg, char **azCol){
90011be35a1SLionel Sambuc   /* since we don't have type info, call the shell_callback with a NULL value */
90111be35a1SLionel Sambuc   return shell_callback(pArg, nArg, azArg, azCol, NULL);
90211be35a1SLionel Sambuc }
90311be35a1SLionel Sambuc 
90411be35a1SLionel Sambuc /*
90511be35a1SLionel Sambuc ** Set the destination table field of the callback_data structure to
90611be35a1SLionel Sambuc ** the name of the table given.  Escape any quote characters in the
90711be35a1SLionel Sambuc ** table name.
90811be35a1SLionel Sambuc */
set_table_name(struct callback_data * p,const char * zName)90911be35a1SLionel Sambuc static void set_table_name(struct callback_data *p, const char *zName){
91011be35a1SLionel Sambuc   int i, n;
91111be35a1SLionel Sambuc   int needQuote;
91211be35a1SLionel Sambuc   char *z;
91311be35a1SLionel Sambuc 
91411be35a1SLionel Sambuc   if( p->zDestTable ){
91511be35a1SLionel Sambuc     free(p->zDestTable);
91611be35a1SLionel Sambuc     p->zDestTable = 0;
91711be35a1SLionel Sambuc   }
91811be35a1SLionel Sambuc   if( zName==0 ) return;
91911be35a1SLionel Sambuc   needQuote = !isalpha((unsigned char)*zName) && *zName!='_';
92011be35a1SLionel Sambuc   for(i=n=0; zName[i]; i++, n++){
92111be35a1SLionel Sambuc     if( !isalnum((unsigned char)zName[i]) && zName[i]!='_' ){
92211be35a1SLionel Sambuc       needQuote = 1;
92311be35a1SLionel Sambuc       if( zName[i]=='\'' ) n++;
92411be35a1SLionel Sambuc     }
92511be35a1SLionel Sambuc   }
92611be35a1SLionel Sambuc   if( needQuote ) n += 2;
92711be35a1SLionel Sambuc   z = p->zDestTable = malloc( n+1 );
92811be35a1SLionel Sambuc   if( z==0 ){
92911be35a1SLionel Sambuc     fprintf(stderr,"Error: out of memory\n");
93011be35a1SLionel Sambuc     exit(1);
93111be35a1SLionel Sambuc   }
93211be35a1SLionel Sambuc   n = 0;
93311be35a1SLionel Sambuc   if( needQuote ) z[n++] = '\'';
93411be35a1SLionel Sambuc   for(i=0; zName[i]; i++){
93511be35a1SLionel Sambuc     z[n++] = zName[i];
93611be35a1SLionel Sambuc     if( zName[i]=='\'' ) z[n++] = '\'';
93711be35a1SLionel Sambuc   }
93811be35a1SLionel Sambuc   if( needQuote ) z[n++] = '\'';
93911be35a1SLionel Sambuc   z[n] = 0;
94011be35a1SLionel Sambuc }
94111be35a1SLionel Sambuc 
94211be35a1SLionel Sambuc /* zIn is either a pointer to a NULL-terminated string in memory obtained
94311be35a1SLionel Sambuc ** from malloc(), or a NULL pointer. The string pointed to by zAppend is
94411be35a1SLionel Sambuc ** added to zIn, and the result returned in memory obtained from malloc().
94511be35a1SLionel Sambuc ** zIn, if it was not NULL, is freed.
94611be35a1SLionel Sambuc **
94711be35a1SLionel Sambuc ** If the third argument, quote, is not '\0', then it is used as a
94811be35a1SLionel Sambuc ** quote character for zAppend.
94911be35a1SLionel Sambuc */
appendText(char * zIn,char const * zAppend,char quote)95011be35a1SLionel Sambuc static char *appendText(char *zIn, char const *zAppend, char quote){
95111be35a1SLionel Sambuc   int len;
95211be35a1SLionel Sambuc   int i;
95311be35a1SLionel Sambuc   int nAppend = strlen30(zAppend);
95411be35a1SLionel Sambuc   int nIn = (zIn?strlen30(zIn):0);
95511be35a1SLionel Sambuc 
95611be35a1SLionel Sambuc   len = nAppend+nIn+1;
95711be35a1SLionel Sambuc   if( quote ){
95811be35a1SLionel Sambuc     len += 2;
95911be35a1SLionel Sambuc     for(i=0; i<nAppend; i++){
96011be35a1SLionel Sambuc       if( zAppend[i]==quote ) len++;
96111be35a1SLionel Sambuc     }
96211be35a1SLionel Sambuc   }
96311be35a1SLionel Sambuc 
96411be35a1SLionel Sambuc   zIn = (char *)realloc(zIn, len);
96511be35a1SLionel Sambuc   if( !zIn ){
96611be35a1SLionel Sambuc     return 0;
96711be35a1SLionel Sambuc   }
96811be35a1SLionel Sambuc 
96911be35a1SLionel Sambuc   if( quote ){
97011be35a1SLionel Sambuc     char *zCsr = &zIn[nIn];
97111be35a1SLionel Sambuc     *zCsr++ = quote;
97211be35a1SLionel Sambuc     for(i=0; i<nAppend; i++){
97311be35a1SLionel Sambuc       *zCsr++ = zAppend[i];
97411be35a1SLionel Sambuc       if( zAppend[i]==quote ) *zCsr++ = quote;
97511be35a1SLionel Sambuc     }
97611be35a1SLionel Sambuc     *zCsr++ = quote;
97711be35a1SLionel Sambuc     *zCsr++ = '\0';
97811be35a1SLionel Sambuc     assert( (zCsr-zIn)==len );
97911be35a1SLionel Sambuc   }else{
98011be35a1SLionel Sambuc     memcpy(&zIn[nIn], zAppend, nAppend);
98111be35a1SLionel Sambuc     zIn[len-1] = '\0';
98211be35a1SLionel Sambuc   }
98311be35a1SLionel Sambuc 
98411be35a1SLionel Sambuc   return zIn;
98511be35a1SLionel Sambuc }
98611be35a1SLionel Sambuc 
98711be35a1SLionel Sambuc 
98811be35a1SLionel Sambuc /*
989*0a6a1f1dSLionel Sambuc ** Execute a query statement that will generate SQL output.  Print
990*0a6a1f1dSLionel Sambuc ** the result columns, comma-separated, on a line and then add a
991*0a6a1f1dSLionel Sambuc ** semicolon terminator to the end of that line.
99211be35a1SLionel Sambuc **
993*0a6a1f1dSLionel Sambuc ** If the number of columns is 1 and that column contains text "--"
994*0a6a1f1dSLionel Sambuc ** then write the semicolon on a separate line.  That way, if a
995*0a6a1f1dSLionel Sambuc ** "--" comment occurs at the end of the statement, the comment
996*0a6a1f1dSLionel Sambuc ** won't consume the semicolon terminator.
99711be35a1SLionel Sambuc */
run_table_dump_query(struct callback_data * p,const char * zSelect,const char * zFirstRow)99811be35a1SLionel Sambuc static int run_table_dump_query(
99911be35a1SLionel Sambuc   struct callback_data *p, /* Query context */
100011be35a1SLionel Sambuc   const char *zSelect,     /* SELECT statement to extract content */
100111be35a1SLionel Sambuc   const char *zFirstRow    /* Print before first row, if not NULL */
100211be35a1SLionel Sambuc ){
100311be35a1SLionel Sambuc   sqlite3_stmt *pSelect;
100411be35a1SLionel Sambuc   int rc;
1005*0a6a1f1dSLionel Sambuc   int nResult;
1006*0a6a1f1dSLionel Sambuc   int i;
1007*0a6a1f1dSLionel Sambuc   const char *z;
100811be35a1SLionel Sambuc   rc = sqlite3_prepare(p->db, zSelect, -1, &pSelect, 0);
100911be35a1SLionel Sambuc   if( rc!=SQLITE_OK || !pSelect ){
101011be35a1SLionel Sambuc     fprintf(p->out, "/**** ERROR: (%d) %s *****/\n", rc, sqlite3_errmsg(p->db));
1011*0a6a1f1dSLionel Sambuc     if( (rc&0xff)!=SQLITE_CORRUPT ) p->nErr++;
101211be35a1SLionel Sambuc     return rc;
101311be35a1SLionel Sambuc   }
101411be35a1SLionel Sambuc   rc = sqlite3_step(pSelect);
1015*0a6a1f1dSLionel Sambuc   nResult = sqlite3_column_count(pSelect);
101611be35a1SLionel Sambuc   while( rc==SQLITE_ROW ){
101711be35a1SLionel Sambuc     if( zFirstRow ){
101811be35a1SLionel Sambuc       fprintf(p->out, "%s", zFirstRow);
101911be35a1SLionel Sambuc       zFirstRow = 0;
102011be35a1SLionel Sambuc     }
1021*0a6a1f1dSLionel Sambuc     z = (const char*)sqlite3_column_text(pSelect, 0);
1022*0a6a1f1dSLionel Sambuc     fprintf(p->out, "%s", z);
1023*0a6a1f1dSLionel Sambuc     for(i=1; i<nResult; i++){
1024*0a6a1f1dSLionel Sambuc       fprintf(p->out, ",%s", sqlite3_column_text(pSelect, i));
1025*0a6a1f1dSLionel Sambuc     }
1026*0a6a1f1dSLionel Sambuc     if( z==0 ) z = "";
1027*0a6a1f1dSLionel Sambuc     while( z[0] && (z[0]!='-' || z[1]!='-') ) z++;
1028*0a6a1f1dSLionel Sambuc     if( z[0] ){
1029*0a6a1f1dSLionel Sambuc       fprintf(p->out, "\n;\n");
1030*0a6a1f1dSLionel Sambuc     }else{
1031*0a6a1f1dSLionel Sambuc       fprintf(p->out, ";\n");
1032*0a6a1f1dSLionel Sambuc     }
103311be35a1SLionel Sambuc     rc = sqlite3_step(pSelect);
103411be35a1SLionel Sambuc   }
103511be35a1SLionel Sambuc   rc = sqlite3_finalize(pSelect);
103611be35a1SLionel Sambuc   if( rc!=SQLITE_OK ){
103711be35a1SLionel Sambuc     fprintf(p->out, "/**** ERROR: (%d) %s *****/\n", rc, sqlite3_errmsg(p->db));
1038*0a6a1f1dSLionel Sambuc     if( (rc&0xff)!=SQLITE_CORRUPT ) p->nErr++;
103911be35a1SLionel Sambuc   }
104011be35a1SLionel Sambuc   return rc;
104111be35a1SLionel Sambuc }
104211be35a1SLionel Sambuc 
104311be35a1SLionel Sambuc /*
104411be35a1SLionel Sambuc ** Allocate space and save off current error string.
104511be35a1SLionel Sambuc */
save_err_msg(sqlite3 * db)104611be35a1SLionel Sambuc static char *save_err_msg(
104711be35a1SLionel Sambuc   sqlite3 *db            /* Database to query */
104811be35a1SLionel Sambuc ){
104911be35a1SLionel Sambuc   int nErrMsg = 1+strlen30(sqlite3_errmsg(db));
105011be35a1SLionel Sambuc   char *zErrMsg = sqlite3_malloc(nErrMsg);
105111be35a1SLionel Sambuc   if( zErrMsg ){
105211be35a1SLionel Sambuc     memcpy(zErrMsg, sqlite3_errmsg(db), nErrMsg);
105311be35a1SLionel Sambuc   }
105411be35a1SLionel Sambuc   return zErrMsg;
105511be35a1SLionel Sambuc }
105611be35a1SLionel Sambuc 
105711be35a1SLionel Sambuc /*
105811be35a1SLionel Sambuc ** Display memory stats.
105911be35a1SLionel Sambuc */
display_stats(sqlite3 * db,struct callback_data * pArg,int bReset)106011be35a1SLionel Sambuc static int display_stats(
106111be35a1SLionel Sambuc   sqlite3 *db,                /* Database to query */
106211be35a1SLionel Sambuc   struct callback_data *pArg, /* Pointer to struct callback_data */
106311be35a1SLionel Sambuc   int bReset                  /* True to reset the stats */
106411be35a1SLionel Sambuc ){
106511be35a1SLionel Sambuc   int iCur;
106611be35a1SLionel Sambuc   int iHiwtr;
106711be35a1SLionel Sambuc 
106811be35a1SLionel Sambuc   if( pArg && pArg->out ){
106911be35a1SLionel Sambuc 
107011be35a1SLionel Sambuc     iHiwtr = iCur = -1;
107111be35a1SLionel Sambuc     sqlite3_status(SQLITE_STATUS_MEMORY_USED, &iCur, &iHiwtr, bReset);
107211be35a1SLionel Sambuc     fprintf(pArg->out, "Memory Used:                         %d (max %d) bytes\n", iCur, iHiwtr);
107311be35a1SLionel Sambuc     iHiwtr = iCur = -1;
107411be35a1SLionel Sambuc     sqlite3_status(SQLITE_STATUS_MALLOC_COUNT, &iCur, &iHiwtr, bReset);
107511be35a1SLionel Sambuc     fprintf(pArg->out, "Number of Outstanding Allocations:   %d (max %d)\n", iCur, iHiwtr);
107611be35a1SLionel Sambuc /*
107711be35a1SLionel Sambuc ** Not currently used by the CLI.
107811be35a1SLionel Sambuc **    iHiwtr = iCur = -1;
107911be35a1SLionel Sambuc **    sqlite3_status(SQLITE_STATUS_PAGECACHE_USED, &iCur, &iHiwtr, bReset);
108011be35a1SLionel Sambuc **    fprintf(pArg->out, "Number of Pcache Pages Used:         %d (max %d) pages\n", iCur, iHiwtr);
108111be35a1SLionel Sambuc */
108211be35a1SLionel Sambuc     iHiwtr = iCur = -1;
108311be35a1SLionel Sambuc     sqlite3_status(SQLITE_STATUS_PAGECACHE_OVERFLOW, &iCur, &iHiwtr, bReset);
108411be35a1SLionel Sambuc     fprintf(pArg->out, "Number of Pcache Overflow Bytes:     %d (max %d) bytes\n", iCur, iHiwtr);
108511be35a1SLionel Sambuc /*
108611be35a1SLionel Sambuc ** Not currently used by the CLI.
108711be35a1SLionel Sambuc **    iHiwtr = iCur = -1;
108811be35a1SLionel Sambuc **    sqlite3_status(SQLITE_STATUS_SCRATCH_USED, &iCur, &iHiwtr, bReset);
108911be35a1SLionel Sambuc **    fprintf(pArg->out, "Number of Scratch Allocations Used:  %d (max %d)\n", iCur, iHiwtr);
109011be35a1SLionel Sambuc */
109111be35a1SLionel Sambuc     iHiwtr = iCur = -1;
109211be35a1SLionel Sambuc     sqlite3_status(SQLITE_STATUS_SCRATCH_OVERFLOW, &iCur, &iHiwtr, bReset);
109311be35a1SLionel Sambuc     fprintf(pArg->out, "Number of Scratch Overflow Bytes:    %d (max %d) bytes\n", iCur, iHiwtr);
109411be35a1SLionel Sambuc     iHiwtr = iCur = -1;
109511be35a1SLionel Sambuc     sqlite3_status(SQLITE_STATUS_MALLOC_SIZE, &iCur, &iHiwtr, bReset);
109611be35a1SLionel Sambuc     fprintf(pArg->out, "Largest Allocation:                  %d bytes\n", iHiwtr);
109711be35a1SLionel Sambuc     iHiwtr = iCur = -1;
109811be35a1SLionel Sambuc     sqlite3_status(SQLITE_STATUS_PAGECACHE_SIZE, &iCur, &iHiwtr, bReset);
109911be35a1SLionel Sambuc     fprintf(pArg->out, "Largest Pcache Allocation:           %d bytes\n", iHiwtr);
110011be35a1SLionel Sambuc     iHiwtr = iCur = -1;
110111be35a1SLionel Sambuc     sqlite3_status(SQLITE_STATUS_SCRATCH_SIZE, &iCur, &iHiwtr, bReset);
110211be35a1SLionel Sambuc     fprintf(pArg->out, "Largest Scratch Allocation:          %d bytes\n", iHiwtr);
110311be35a1SLionel Sambuc #ifdef YYTRACKMAXSTACKDEPTH
110411be35a1SLionel Sambuc     iHiwtr = iCur = -1;
110511be35a1SLionel Sambuc     sqlite3_status(SQLITE_STATUS_PARSER_STACK, &iCur, &iHiwtr, bReset);
110611be35a1SLionel Sambuc     fprintf(pArg->out, "Deepest Parser Stack:                %d (max %d)\n", iCur, iHiwtr);
110711be35a1SLionel Sambuc #endif
110811be35a1SLionel Sambuc   }
110911be35a1SLionel Sambuc 
111011be35a1SLionel Sambuc   if( pArg && pArg->out && db ){
111111be35a1SLionel Sambuc     iHiwtr = iCur = -1;
111211be35a1SLionel Sambuc     sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_USED, &iCur, &iHiwtr, bReset);
111311be35a1SLionel Sambuc     fprintf(pArg->out, "Lookaside Slots Used:                %d (max %d)\n", iCur, iHiwtr);
111411be35a1SLionel Sambuc     sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_HIT, &iCur, &iHiwtr, bReset);
111511be35a1SLionel Sambuc     fprintf(pArg->out, "Successful lookaside attempts:       %d\n", iHiwtr);
111611be35a1SLionel Sambuc     sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE, &iCur, &iHiwtr, bReset);
111711be35a1SLionel Sambuc     fprintf(pArg->out, "Lookaside failures due to size:      %d\n", iHiwtr);
111811be35a1SLionel Sambuc     sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL, &iCur, &iHiwtr, bReset);
111911be35a1SLionel Sambuc     fprintf(pArg->out, "Lookaside failures due to OOM:       %d\n", iHiwtr);
112011be35a1SLionel Sambuc     iHiwtr = iCur = -1;
112111be35a1SLionel Sambuc     sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_USED, &iCur, &iHiwtr, bReset);
112211be35a1SLionel Sambuc     fprintf(pArg->out, "Pager Heap Usage:                    %d bytes\n", iCur);    iHiwtr = iCur = -1;
112311be35a1SLionel Sambuc     sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_HIT, &iCur, &iHiwtr, 1);
112411be35a1SLionel Sambuc     fprintf(pArg->out, "Page cache hits:                     %d\n", iCur);
112511be35a1SLionel Sambuc     iHiwtr = iCur = -1;
112611be35a1SLionel Sambuc     sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_MISS, &iCur, &iHiwtr, 1);
112711be35a1SLionel Sambuc     fprintf(pArg->out, "Page cache misses:                   %d\n", iCur);
112811be35a1SLionel Sambuc     iHiwtr = iCur = -1;
1129*0a6a1f1dSLionel Sambuc     sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_WRITE, &iCur, &iHiwtr, 1);
1130*0a6a1f1dSLionel Sambuc     fprintf(pArg->out, "Page cache writes:                   %d\n", iCur);
1131*0a6a1f1dSLionel Sambuc     iHiwtr = iCur = -1;
113211be35a1SLionel Sambuc     sqlite3_db_status(db, SQLITE_DBSTATUS_SCHEMA_USED, &iCur, &iHiwtr, bReset);
113311be35a1SLionel Sambuc     fprintf(pArg->out, "Schema Heap Usage:                   %d bytes\n", iCur);
113411be35a1SLionel Sambuc     iHiwtr = iCur = -1;
113511be35a1SLionel Sambuc     sqlite3_db_status(db, SQLITE_DBSTATUS_STMT_USED, &iCur, &iHiwtr, bReset);
113611be35a1SLionel Sambuc     fprintf(pArg->out, "Statement Heap/Lookaside Usage:      %d bytes\n", iCur);
113711be35a1SLionel Sambuc   }
113811be35a1SLionel Sambuc 
113911be35a1SLionel Sambuc   if( pArg && pArg->out && db && pArg->pStmt ){
114011be35a1SLionel Sambuc     iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_FULLSCAN_STEP, bReset);
114111be35a1SLionel Sambuc     fprintf(pArg->out, "Fullscan Steps:                      %d\n", iCur);
114211be35a1SLionel Sambuc     iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_SORT, bReset);
114311be35a1SLionel Sambuc     fprintf(pArg->out, "Sort Operations:                     %d\n", iCur);
114411be35a1SLionel Sambuc     iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_AUTOINDEX, bReset);
114511be35a1SLionel Sambuc     fprintf(pArg->out, "Autoindex Inserts:                   %d\n", iCur);
1146*0a6a1f1dSLionel Sambuc     iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_VM_STEP, bReset);
1147*0a6a1f1dSLionel Sambuc     fprintf(pArg->out, "Virtual Machine Steps:               %d\n", iCur);
114811be35a1SLionel Sambuc   }
114911be35a1SLionel Sambuc 
115011be35a1SLionel Sambuc   return 0;
115111be35a1SLionel Sambuc }
115211be35a1SLionel Sambuc 
115311be35a1SLionel Sambuc /*
1154*0a6a1f1dSLionel Sambuc ** Parameter azArray points to a zero-terminated array of strings. zStr
1155*0a6a1f1dSLionel Sambuc ** points to a single nul-terminated string. Return non-zero if zStr
1156*0a6a1f1dSLionel Sambuc ** is equal, according to strcmp(), to any of the strings in the array.
1157*0a6a1f1dSLionel Sambuc ** Otherwise, return zero.
1158*0a6a1f1dSLionel Sambuc */
str_in_array(const char * zStr,const char ** azArray)1159*0a6a1f1dSLionel Sambuc static int str_in_array(const char *zStr, const char **azArray){
1160*0a6a1f1dSLionel Sambuc   int i;
1161*0a6a1f1dSLionel Sambuc   for(i=0; azArray[i]; i++){
1162*0a6a1f1dSLionel Sambuc     if( 0==strcmp(zStr, azArray[i]) ) return 1;
1163*0a6a1f1dSLionel Sambuc   }
1164*0a6a1f1dSLionel Sambuc   return 0;
1165*0a6a1f1dSLionel Sambuc }
1166*0a6a1f1dSLionel Sambuc 
1167*0a6a1f1dSLionel Sambuc /*
1168*0a6a1f1dSLionel Sambuc ** If compiled statement pSql appears to be an EXPLAIN statement, allocate
1169*0a6a1f1dSLionel Sambuc ** and populate the callback_data.aiIndent[] array with the number of
1170*0a6a1f1dSLionel Sambuc ** spaces each opcode should be indented before it is output.
1171*0a6a1f1dSLionel Sambuc **
1172*0a6a1f1dSLionel Sambuc ** The indenting rules are:
1173*0a6a1f1dSLionel Sambuc **
1174*0a6a1f1dSLionel Sambuc **     * For each "Next", "Prev", "VNext" or "VPrev" instruction, indent
1175*0a6a1f1dSLionel Sambuc **       all opcodes that occur between the p2 jump destination and the opcode
1176*0a6a1f1dSLionel Sambuc **       itself by 2 spaces.
1177*0a6a1f1dSLionel Sambuc **
1178*0a6a1f1dSLionel Sambuc **     * For each "Goto", if the jump destination is earlier in the program
1179*0a6a1f1dSLionel Sambuc **       and ends on one of:
1180*0a6a1f1dSLionel Sambuc **          Yield  SeekGt  SeekLt  RowSetRead  Rewind
1181*0a6a1f1dSLionel Sambuc **       then indent all opcodes between the earlier instruction
1182*0a6a1f1dSLionel Sambuc **       and "Goto" by 2 spaces.
1183*0a6a1f1dSLionel Sambuc */
explain_data_prepare(struct callback_data * p,sqlite3_stmt * pSql)1184*0a6a1f1dSLionel Sambuc static void explain_data_prepare(struct callback_data *p, sqlite3_stmt *pSql){
1185*0a6a1f1dSLionel Sambuc   const char *zSql;               /* The text of the SQL statement */
1186*0a6a1f1dSLionel Sambuc   const char *z;                  /* Used to check if this is an EXPLAIN */
1187*0a6a1f1dSLionel Sambuc   int *abYield = 0;               /* True if op is an OP_Yield */
1188*0a6a1f1dSLionel Sambuc   int nAlloc = 0;                 /* Allocated size of p->aiIndent[], abYield */
1189*0a6a1f1dSLionel Sambuc   int iOp;                        /* Index of operation in p->aiIndent[] */
1190*0a6a1f1dSLionel Sambuc 
1191*0a6a1f1dSLionel Sambuc   const char *azNext[] = { "Next", "Prev", "VPrev", "VNext", "SorterNext", 0 };
1192*0a6a1f1dSLionel Sambuc   const char *azYield[] = { "Yield", "SeekLt", "SeekGt", "RowSetRead", "Rewind", 0 };
1193*0a6a1f1dSLionel Sambuc   const char *azGoto[] = { "Goto", 0 };
1194*0a6a1f1dSLionel Sambuc 
1195*0a6a1f1dSLionel Sambuc   /* Try to figure out if this is really an EXPLAIN statement. If this
1196*0a6a1f1dSLionel Sambuc   ** cannot be verified, return early.  */
1197*0a6a1f1dSLionel Sambuc   zSql = sqlite3_sql(pSql);
1198*0a6a1f1dSLionel Sambuc   if( zSql==0 ) return;
1199*0a6a1f1dSLionel Sambuc   for(z=zSql; *z==' ' || *z=='\t' || *z=='\n' || *z=='\f' || *z=='\r'; z++);
1200*0a6a1f1dSLionel Sambuc   if( sqlite3_strnicmp(z, "explain", 7) ) return;
1201*0a6a1f1dSLionel Sambuc 
1202*0a6a1f1dSLionel Sambuc   for(iOp=0; SQLITE_ROW==sqlite3_step(pSql); iOp++){
1203*0a6a1f1dSLionel Sambuc     int i;
1204*0a6a1f1dSLionel Sambuc     int iAddr = sqlite3_column_int(pSql, 0);
1205*0a6a1f1dSLionel Sambuc     const char *zOp = (const char*)sqlite3_column_text(pSql, 1);
1206*0a6a1f1dSLionel Sambuc 
1207*0a6a1f1dSLionel Sambuc     /* Set p2 to the P2 field of the current opcode. Then, assuming that
1208*0a6a1f1dSLionel Sambuc     ** p2 is an instruction address, set variable p2op to the index of that
1209*0a6a1f1dSLionel Sambuc     ** instruction in the aiIndent[] array. p2 and p2op may be different if
1210*0a6a1f1dSLionel Sambuc     ** the current instruction is part of a sub-program generated by an
1211*0a6a1f1dSLionel Sambuc     ** SQL trigger or foreign key.  */
1212*0a6a1f1dSLionel Sambuc     int p2 = sqlite3_column_int(pSql, 3);
1213*0a6a1f1dSLionel Sambuc     int p2op = (p2 + (iOp-iAddr));
1214*0a6a1f1dSLionel Sambuc 
1215*0a6a1f1dSLionel Sambuc     /* Grow the p->aiIndent array as required */
1216*0a6a1f1dSLionel Sambuc     if( iOp>=nAlloc ){
1217*0a6a1f1dSLionel Sambuc       nAlloc += 100;
1218*0a6a1f1dSLionel Sambuc       p->aiIndent = (int*)sqlite3_realloc(p->aiIndent, nAlloc*sizeof(int));
1219*0a6a1f1dSLionel Sambuc       abYield = (int*)sqlite3_realloc(abYield, nAlloc*sizeof(int));
1220*0a6a1f1dSLionel Sambuc     }
1221*0a6a1f1dSLionel Sambuc     abYield[iOp] = str_in_array(zOp, azYield);
1222*0a6a1f1dSLionel Sambuc     p->aiIndent[iOp] = 0;
1223*0a6a1f1dSLionel Sambuc     p->nIndent = iOp+1;
1224*0a6a1f1dSLionel Sambuc 
1225*0a6a1f1dSLionel Sambuc     if( str_in_array(zOp, azNext) ){
1226*0a6a1f1dSLionel Sambuc       for(i=p2op; i<iOp; i++) p->aiIndent[i] += 2;
1227*0a6a1f1dSLionel Sambuc     }
1228*0a6a1f1dSLionel Sambuc     if( str_in_array(zOp, azGoto) && p2op<p->nIndent && abYield[p2op] ){
1229*0a6a1f1dSLionel Sambuc       for(i=p2op+1; i<iOp; i++) p->aiIndent[i] += 2;
1230*0a6a1f1dSLionel Sambuc     }
1231*0a6a1f1dSLionel Sambuc   }
1232*0a6a1f1dSLionel Sambuc 
1233*0a6a1f1dSLionel Sambuc   p->iIndent = 0;
1234*0a6a1f1dSLionel Sambuc   sqlite3_free(abYield);
1235*0a6a1f1dSLionel Sambuc   sqlite3_reset(pSql);
1236*0a6a1f1dSLionel Sambuc }
1237*0a6a1f1dSLionel Sambuc 
1238*0a6a1f1dSLionel Sambuc /*
1239*0a6a1f1dSLionel Sambuc ** Free the array allocated by explain_data_prepare().
1240*0a6a1f1dSLionel Sambuc */
explain_data_delete(struct callback_data * p)1241*0a6a1f1dSLionel Sambuc static void explain_data_delete(struct callback_data *p){
1242*0a6a1f1dSLionel Sambuc   sqlite3_free(p->aiIndent);
1243*0a6a1f1dSLionel Sambuc   p->aiIndent = 0;
1244*0a6a1f1dSLionel Sambuc   p->nIndent = 0;
1245*0a6a1f1dSLionel Sambuc   p->iIndent = 0;
1246*0a6a1f1dSLionel Sambuc }
1247*0a6a1f1dSLionel Sambuc 
1248*0a6a1f1dSLionel Sambuc /*
124911be35a1SLionel Sambuc ** Execute a statement or set of statements.  Print
125011be35a1SLionel Sambuc ** any result rows/columns depending on the current mode
125111be35a1SLionel Sambuc ** set via the supplied callback.
125211be35a1SLionel Sambuc **
125311be35a1SLionel Sambuc ** This is very similar to SQLite's built-in sqlite3_exec()
125411be35a1SLionel Sambuc ** function except it takes a slightly different callback
125511be35a1SLionel Sambuc ** and callback data argument.
125611be35a1SLionel Sambuc */
shell_exec(sqlite3 * db,const char * zSql,int (* xCallback)(void *,int,char **,char **,int *),struct callback_data * pArg,char ** pzErrMsg)125711be35a1SLionel Sambuc static int shell_exec(
125811be35a1SLionel Sambuc   sqlite3 *db,                                /* An open database */
125911be35a1SLionel Sambuc   const char *zSql,                           /* SQL to be evaluated */
126011be35a1SLionel Sambuc   int (*xCallback)(void*,int,char**,char**,int*),   /* Callback function */
126111be35a1SLionel Sambuc                                               /* (not the same as sqlite3_exec) */
126211be35a1SLionel Sambuc   struct callback_data *pArg,                 /* Pointer to struct callback_data */
126311be35a1SLionel Sambuc   char **pzErrMsg                             /* Error msg written here */
126411be35a1SLionel Sambuc ){
126511be35a1SLionel Sambuc   sqlite3_stmt *pStmt = NULL;     /* Statement to execute. */
126611be35a1SLionel Sambuc   int rc = SQLITE_OK;             /* Return Code */
126711be35a1SLionel Sambuc   int rc2;
126811be35a1SLionel Sambuc   const char *zLeftover;          /* Tail of unprocessed SQL */
126911be35a1SLionel Sambuc 
127011be35a1SLionel Sambuc   if( pzErrMsg ){
127111be35a1SLionel Sambuc     *pzErrMsg = NULL;
127211be35a1SLionel Sambuc   }
127311be35a1SLionel Sambuc 
127411be35a1SLionel Sambuc   while( zSql[0] && (SQLITE_OK == rc) ){
127511be35a1SLionel Sambuc     rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zLeftover);
127611be35a1SLionel Sambuc     if( SQLITE_OK != rc ){
127711be35a1SLionel Sambuc       if( pzErrMsg ){
127811be35a1SLionel Sambuc         *pzErrMsg = save_err_msg(db);
127911be35a1SLionel Sambuc       }
128011be35a1SLionel Sambuc     }else{
128111be35a1SLionel Sambuc       if( !pStmt ){
128211be35a1SLionel Sambuc         /* this happens for a comment or white-space */
128311be35a1SLionel Sambuc         zSql = zLeftover;
128411be35a1SLionel Sambuc         while( IsSpace(zSql[0]) ) zSql++;
128511be35a1SLionel Sambuc         continue;
128611be35a1SLionel Sambuc       }
128711be35a1SLionel Sambuc 
128811be35a1SLionel Sambuc       /* save off the prepared statment handle and reset row count */
128911be35a1SLionel Sambuc       if( pArg ){
129011be35a1SLionel Sambuc         pArg->pStmt = pStmt;
129111be35a1SLionel Sambuc         pArg->cnt = 0;
129211be35a1SLionel Sambuc       }
129311be35a1SLionel Sambuc 
129411be35a1SLionel Sambuc       /* echo the sql statement if echo on */
129511be35a1SLionel Sambuc       if( pArg && pArg->echoOn ){
129611be35a1SLionel Sambuc         const char *zStmtSql = sqlite3_sql(pStmt);
129711be35a1SLionel Sambuc         fprintf(pArg->out, "%s\n", zStmtSql ? zStmtSql : zSql);
129811be35a1SLionel Sambuc       }
129911be35a1SLionel Sambuc 
130011be35a1SLionel Sambuc       /* Output TESTCTRL_EXPLAIN text of requested */
130111be35a1SLionel Sambuc       if( pArg && pArg->mode==MODE_Explain ){
130211be35a1SLionel Sambuc         const char *zExplain = 0;
130311be35a1SLionel Sambuc         sqlite3_test_control(SQLITE_TESTCTRL_EXPLAIN_STMT, pStmt, &zExplain);
130411be35a1SLionel Sambuc         if( zExplain && zExplain[0] ){
130511be35a1SLionel Sambuc           fprintf(pArg->out, "%s", zExplain);
130611be35a1SLionel Sambuc         }
130711be35a1SLionel Sambuc       }
130811be35a1SLionel Sambuc 
1309*0a6a1f1dSLionel Sambuc       /* If the shell is currently in ".explain" mode, gather the extra
1310*0a6a1f1dSLionel Sambuc       ** data required to add indents to the output.*/
1311*0a6a1f1dSLionel Sambuc       if( pArg && pArg->mode==MODE_Explain ){
1312*0a6a1f1dSLionel Sambuc         explain_data_prepare(pArg, pStmt);
1313*0a6a1f1dSLionel Sambuc       }
1314*0a6a1f1dSLionel Sambuc 
131511be35a1SLionel Sambuc       /* perform the first step.  this will tell us if we
131611be35a1SLionel Sambuc       ** have a result set or not and how wide it is.
131711be35a1SLionel Sambuc       */
131811be35a1SLionel Sambuc       rc = sqlite3_step(pStmt);
131911be35a1SLionel Sambuc       /* if we have a result set... */
132011be35a1SLionel Sambuc       if( SQLITE_ROW == rc ){
132111be35a1SLionel Sambuc         /* if we have a callback... */
132211be35a1SLionel Sambuc         if( xCallback ){
132311be35a1SLionel Sambuc           /* allocate space for col name ptr, value ptr, and type */
132411be35a1SLionel Sambuc           int nCol = sqlite3_column_count(pStmt);
132511be35a1SLionel Sambuc           void *pData = sqlite3_malloc(3*nCol*sizeof(const char*) + 1);
132611be35a1SLionel Sambuc           if( !pData ){
132711be35a1SLionel Sambuc             rc = SQLITE_NOMEM;
132811be35a1SLionel Sambuc           }else{
132911be35a1SLionel Sambuc             char **azCols = (char **)pData;      /* Names of result columns */
133011be35a1SLionel Sambuc             char **azVals = &azCols[nCol];       /* Results */
133111be35a1SLionel Sambuc             int *aiTypes = (int *)&azVals[nCol]; /* Result types */
1332*0a6a1f1dSLionel Sambuc             int i, x;
133311be35a1SLionel Sambuc             assert(sizeof(int) <= sizeof(char *));
133411be35a1SLionel Sambuc             /* save off ptrs to column names */
133511be35a1SLionel Sambuc             for(i=0; i<nCol; i++){
133611be35a1SLionel Sambuc               azCols[i] = (char *)sqlite3_column_name(pStmt, i);
133711be35a1SLionel Sambuc             }
133811be35a1SLionel Sambuc             do{
133911be35a1SLionel Sambuc               /* extract the data and data types */
134011be35a1SLionel Sambuc               for(i=0; i<nCol; i++){
1341*0a6a1f1dSLionel Sambuc                 aiTypes[i] = x = sqlite3_column_type(pStmt, i);
1342*0a6a1f1dSLionel Sambuc                 if( x==SQLITE_BLOB && pArg && pArg->mode==MODE_Insert ){
1343*0a6a1f1dSLionel Sambuc                   azVals[i] = "";
1344*0a6a1f1dSLionel Sambuc                 }else{
134511be35a1SLionel Sambuc                   azVals[i] = (char*)sqlite3_column_text(pStmt, i);
1346*0a6a1f1dSLionel Sambuc                 }
134711be35a1SLionel Sambuc                 if( !azVals[i] && (aiTypes[i]!=SQLITE_NULL) ){
134811be35a1SLionel Sambuc                   rc = SQLITE_NOMEM;
134911be35a1SLionel Sambuc                   break; /* from for */
135011be35a1SLionel Sambuc                 }
135111be35a1SLionel Sambuc               } /* end for */
135211be35a1SLionel Sambuc 
135311be35a1SLionel Sambuc               /* if data and types extracted successfully... */
135411be35a1SLionel Sambuc               if( SQLITE_ROW == rc ){
135511be35a1SLionel Sambuc                 /* call the supplied callback with the result row data */
135611be35a1SLionel Sambuc                 if( xCallback(pArg, nCol, azVals, azCols, aiTypes) ){
135711be35a1SLionel Sambuc                   rc = SQLITE_ABORT;
135811be35a1SLionel Sambuc                 }else{
135911be35a1SLionel Sambuc                   rc = sqlite3_step(pStmt);
136011be35a1SLionel Sambuc                 }
136111be35a1SLionel Sambuc               }
136211be35a1SLionel Sambuc             } while( SQLITE_ROW == rc );
136311be35a1SLionel Sambuc             sqlite3_free(pData);
136411be35a1SLionel Sambuc           }
136511be35a1SLionel Sambuc         }else{
136611be35a1SLionel Sambuc           do{
136711be35a1SLionel Sambuc             rc = sqlite3_step(pStmt);
136811be35a1SLionel Sambuc           } while( rc == SQLITE_ROW );
136911be35a1SLionel Sambuc         }
137011be35a1SLionel Sambuc       }
137111be35a1SLionel Sambuc 
1372*0a6a1f1dSLionel Sambuc       explain_data_delete(pArg);
1373*0a6a1f1dSLionel Sambuc 
137411be35a1SLionel Sambuc       /* print usage stats if stats on */
137511be35a1SLionel Sambuc       if( pArg && pArg->statsOn ){
137611be35a1SLionel Sambuc         display_stats(db, pArg, 0);
137711be35a1SLionel Sambuc       }
137811be35a1SLionel Sambuc 
137911be35a1SLionel Sambuc       /* Finalize the statement just executed. If this fails, save a
138011be35a1SLionel Sambuc       ** copy of the error message. Otherwise, set zSql to point to the
138111be35a1SLionel Sambuc       ** next statement to execute. */
138211be35a1SLionel Sambuc       rc2 = sqlite3_finalize(pStmt);
138311be35a1SLionel Sambuc       if( rc!=SQLITE_NOMEM ) rc = rc2;
138411be35a1SLionel Sambuc       if( rc==SQLITE_OK ){
138511be35a1SLionel Sambuc         zSql = zLeftover;
138611be35a1SLionel Sambuc         while( IsSpace(zSql[0]) ) zSql++;
138711be35a1SLionel Sambuc       }else if( pzErrMsg ){
138811be35a1SLionel Sambuc         *pzErrMsg = save_err_msg(db);
138911be35a1SLionel Sambuc       }
139011be35a1SLionel Sambuc 
139111be35a1SLionel Sambuc       /* clear saved stmt handle */
139211be35a1SLionel Sambuc       if( pArg ){
139311be35a1SLionel Sambuc         pArg->pStmt = NULL;
139411be35a1SLionel Sambuc       }
139511be35a1SLionel Sambuc     }
139611be35a1SLionel Sambuc   } /* end while */
139711be35a1SLionel Sambuc 
139811be35a1SLionel Sambuc   return rc;
139911be35a1SLionel Sambuc }
140011be35a1SLionel Sambuc 
140111be35a1SLionel Sambuc 
140211be35a1SLionel Sambuc /*
140311be35a1SLionel Sambuc ** This is a different callback routine used for dumping the database.
140411be35a1SLionel Sambuc ** Each row received by this callback consists of a table name,
140511be35a1SLionel Sambuc ** the table type ("index" or "table") and SQL to create the table.
140611be35a1SLionel Sambuc ** This routine should print text sufficient to recreate the table.
140711be35a1SLionel Sambuc */
dump_callback(void * pArg,int nArg,char ** azArg,char ** azCol)140811be35a1SLionel Sambuc static int dump_callback(void *pArg, int nArg, char **azArg, char **azCol){
140911be35a1SLionel Sambuc   int rc;
141011be35a1SLionel Sambuc   const char *zTable;
141111be35a1SLionel Sambuc   const char *zType;
141211be35a1SLionel Sambuc   const char *zSql;
141311be35a1SLionel Sambuc   const char *zPrepStmt = 0;
141411be35a1SLionel Sambuc   struct callback_data *p = (struct callback_data *)pArg;
141511be35a1SLionel Sambuc 
141611be35a1SLionel Sambuc   UNUSED_PARAMETER(azCol);
141711be35a1SLionel Sambuc   if( nArg!=3 ) return 1;
141811be35a1SLionel Sambuc   zTable = azArg[0];
141911be35a1SLionel Sambuc   zType = azArg[1];
142011be35a1SLionel Sambuc   zSql = azArg[2];
142111be35a1SLionel Sambuc 
142211be35a1SLionel Sambuc   if( strcmp(zTable, "sqlite_sequence")==0 ){
142311be35a1SLionel Sambuc     zPrepStmt = "DELETE FROM sqlite_sequence;\n";
1424*0a6a1f1dSLionel Sambuc   }else if( sqlite3_strglob("sqlite_stat?", zTable)==0 ){
142511be35a1SLionel Sambuc     fprintf(p->out, "ANALYZE sqlite_master;\n");
142611be35a1SLionel Sambuc   }else if( strncmp(zTable, "sqlite_", 7)==0 ){
142711be35a1SLionel Sambuc     return 0;
142811be35a1SLionel Sambuc   }else if( strncmp(zSql, "CREATE VIRTUAL TABLE", 20)==0 ){
142911be35a1SLionel Sambuc     char *zIns;
143011be35a1SLionel Sambuc     if( !p->writableSchema ){
143111be35a1SLionel Sambuc       fprintf(p->out, "PRAGMA writable_schema=ON;\n");
143211be35a1SLionel Sambuc       p->writableSchema = 1;
143311be35a1SLionel Sambuc     }
143411be35a1SLionel Sambuc     zIns = sqlite3_mprintf(
143511be35a1SLionel Sambuc        "INSERT INTO sqlite_master(type,name,tbl_name,rootpage,sql)"
143611be35a1SLionel Sambuc        "VALUES('table','%q','%q',0,'%q');",
143711be35a1SLionel Sambuc        zTable, zTable, zSql);
143811be35a1SLionel Sambuc     fprintf(p->out, "%s\n", zIns);
143911be35a1SLionel Sambuc     sqlite3_free(zIns);
144011be35a1SLionel Sambuc     return 0;
144111be35a1SLionel Sambuc   }else{
144211be35a1SLionel Sambuc     fprintf(p->out, "%s;\n", zSql);
144311be35a1SLionel Sambuc   }
144411be35a1SLionel Sambuc 
144511be35a1SLionel Sambuc   if( strcmp(zType, "table")==0 ){
144611be35a1SLionel Sambuc     sqlite3_stmt *pTableInfo = 0;
144711be35a1SLionel Sambuc     char *zSelect = 0;
144811be35a1SLionel Sambuc     char *zTableInfo = 0;
144911be35a1SLionel Sambuc     char *zTmp = 0;
145011be35a1SLionel Sambuc     int nRow = 0;
145111be35a1SLionel Sambuc 
145211be35a1SLionel Sambuc     zTableInfo = appendText(zTableInfo, "PRAGMA table_info(", 0);
145311be35a1SLionel Sambuc     zTableInfo = appendText(zTableInfo, zTable, '"');
145411be35a1SLionel Sambuc     zTableInfo = appendText(zTableInfo, ");", 0);
145511be35a1SLionel Sambuc 
145611be35a1SLionel Sambuc     rc = sqlite3_prepare(p->db, zTableInfo, -1, &pTableInfo, 0);
145711be35a1SLionel Sambuc     free(zTableInfo);
145811be35a1SLionel Sambuc     if( rc!=SQLITE_OK || !pTableInfo ){
145911be35a1SLionel Sambuc       return 1;
146011be35a1SLionel Sambuc     }
146111be35a1SLionel Sambuc 
146211be35a1SLionel Sambuc     zSelect = appendText(zSelect, "SELECT 'INSERT INTO ' || ", 0);
1463*0a6a1f1dSLionel Sambuc     /* Always quote the table name, even if it appears to be pure ascii,
1464*0a6a1f1dSLionel Sambuc     ** in case it is a keyword. Ex:  INSERT INTO "table" ... */
146511be35a1SLionel Sambuc     zTmp = appendText(zTmp, zTable, '"');
146611be35a1SLionel Sambuc     if( zTmp ){
146711be35a1SLionel Sambuc       zSelect = appendText(zSelect, zTmp, '\'');
1468*0a6a1f1dSLionel Sambuc       free(zTmp);
146911be35a1SLionel Sambuc     }
147011be35a1SLionel Sambuc     zSelect = appendText(zSelect, " || ' VALUES(' || ", 0);
147111be35a1SLionel Sambuc     rc = sqlite3_step(pTableInfo);
147211be35a1SLionel Sambuc     while( rc==SQLITE_ROW ){
147311be35a1SLionel Sambuc       const char *zText = (const char *)sqlite3_column_text(pTableInfo, 1);
147411be35a1SLionel Sambuc       zSelect = appendText(zSelect, "quote(", 0);
147511be35a1SLionel Sambuc       zSelect = appendText(zSelect, zText, '"');
147611be35a1SLionel Sambuc       rc = sqlite3_step(pTableInfo);
147711be35a1SLionel Sambuc       if( rc==SQLITE_ROW ){
1478*0a6a1f1dSLionel Sambuc         zSelect = appendText(zSelect, "), ", 0);
147911be35a1SLionel Sambuc       }else{
148011be35a1SLionel Sambuc         zSelect = appendText(zSelect, ") ", 0);
148111be35a1SLionel Sambuc       }
148211be35a1SLionel Sambuc       nRow++;
148311be35a1SLionel Sambuc     }
148411be35a1SLionel Sambuc     rc = sqlite3_finalize(pTableInfo);
148511be35a1SLionel Sambuc     if( rc!=SQLITE_OK || nRow==0 ){
148611be35a1SLionel Sambuc       free(zSelect);
148711be35a1SLionel Sambuc       return 1;
148811be35a1SLionel Sambuc     }
148911be35a1SLionel Sambuc     zSelect = appendText(zSelect, "|| ')' FROM  ", 0);
149011be35a1SLionel Sambuc     zSelect = appendText(zSelect, zTable, '"');
149111be35a1SLionel Sambuc 
149211be35a1SLionel Sambuc     rc = run_table_dump_query(p, zSelect, zPrepStmt);
149311be35a1SLionel Sambuc     if( rc==SQLITE_CORRUPT ){
149411be35a1SLionel Sambuc       zSelect = appendText(zSelect, " ORDER BY rowid DESC", 0);
149511be35a1SLionel Sambuc       run_table_dump_query(p, zSelect, 0);
149611be35a1SLionel Sambuc     }
1497*0a6a1f1dSLionel Sambuc     free(zSelect);
149811be35a1SLionel Sambuc   }
149911be35a1SLionel Sambuc   return 0;
150011be35a1SLionel Sambuc }
150111be35a1SLionel Sambuc 
150211be35a1SLionel Sambuc /*
150311be35a1SLionel Sambuc ** Run zQuery.  Use dump_callback() as the callback routine so that
150411be35a1SLionel Sambuc ** the contents of the query are output as SQL statements.
150511be35a1SLionel Sambuc **
150611be35a1SLionel Sambuc ** If we get a SQLITE_CORRUPT error, rerun the query after appending
150711be35a1SLionel Sambuc ** "ORDER BY rowid DESC" to the end.
150811be35a1SLionel Sambuc */
run_schema_dump_query(struct callback_data * p,const char * zQuery)150911be35a1SLionel Sambuc static int run_schema_dump_query(
151011be35a1SLionel Sambuc   struct callback_data *p,
151111be35a1SLionel Sambuc   const char *zQuery
151211be35a1SLionel Sambuc ){
151311be35a1SLionel Sambuc   int rc;
151411be35a1SLionel Sambuc   char *zErr = 0;
151511be35a1SLionel Sambuc   rc = sqlite3_exec(p->db, zQuery, dump_callback, p, &zErr);
151611be35a1SLionel Sambuc   if( rc==SQLITE_CORRUPT ){
151711be35a1SLionel Sambuc     char *zQ2;
151811be35a1SLionel Sambuc     int len = strlen30(zQuery);
151911be35a1SLionel Sambuc     fprintf(p->out, "/****** CORRUPTION ERROR *******/\n");
152011be35a1SLionel Sambuc     if( zErr ){
152111be35a1SLionel Sambuc       fprintf(p->out, "/****** %s ******/\n", zErr);
152211be35a1SLionel Sambuc       sqlite3_free(zErr);
152311be35a1SLionel Sambuc       zErr = 0;
152411be35a1SLionel Sambuc     }
152511be35a1SLionel Sambuc     zQ2 = malloc( len+100 );
152611be35a1SLionel Sambuc     if( zQ2==0 ) return rc;
1527*0a6a1f1dSLionel Sambuc     sqlite3_snprintf(len+100, zQ2, "%s ORDER BY rowid DESC", zQuery);
152811be35a1SLionel Sambuc     rc = sqlite3_exec(p->db, zQ2, dump_callback, p, &zErr);
152911be35a1SLionel Sambuc     if( rc ){
153011be35a1SLionel Sambuc       fprintf(p->out, "/****** ERROR: %s ******/\n", zErr);
153111be35a1SLionel Sambuc     }else{
153211be35a1SLionel Sambuc       rc = SQLITE_CORRUPT;
153311be35a1SLionel Sambuc     }
153411be35a1SLionel Sambuc     sqlite3_free(zErr);
153511be35a1SLionel Sambuc     free(zQ2);
153611be35a1SLionel Sambuc   }
153711be35a1SLionel Sambuc   return rc;
153811be35a1SLionel Sambuc }
153911be35a1SLionel Sambuc 
154011be35a1SLionel Sambuc /*
154111be35a1SLionel Sambuc ** Text of a help message
154211be35a1SLionel Sambuc */
154311be35a1SLionel Sambuc static char zHelp[] =
154411be35a1SLionel Sambuc   ".backup ?DB? FILE      Backup DB (default \"main\") to FILE\n"
154511be35a1SLionel Sambuc   ".bail ON|OFF           Stop after hitting an error.  Default OFF\n"
154611be35a1SLionel Sambuc   ".databases             List names and files of attached databases\n"
154711be35a1SLionel Sambuc   ".dump ?TABLE? ...      Dump the database in an SQL text format\n"
154811be35a1SLionel Sambuc   "                         If TABLE specified, only dump tables matching\n"
154911be35a1SLionel Sambuc   "                         LIKE pattern TABLE.\n"
155011be35a1SLionel Sambuc   ".echo ON|OFF           Turn command echo on or off\n"
155111be35a1SLionel Sambuc   ".exit                  Exit this program\n"
155211be35a1SLionel Sambuc   ".explain ?ON|OFF?      Turn output mode suitable for EXPLAIN on or off.\n"
155311be35a1SLionel Sambuc   "                         With no args, it turns EXPLAIN on.\n"
155411be35a1SLionel Sambuc   ".header(s) ON|OFF      Turn display of headers on or off\n"
155511be35a1SLionel Sambuc   ".help                  Show this message\n"
155611be35a1SLionel Sambuc   ".import FILE TABLE     Import data from FILE into TABLE\n"
155711be35a1SLionel Sambuc   ".indices ?TABLE?       Show names of all indices\n"
155811be35a1SLionel Sambuc   "                         If TABLE specified, only show indices for tables\n"
155911be35a1SLionel Sambuc   "                         matching LIKE pattern TABLE.\n"
156011be35a1SLionel Sambuc #ifdef SQLITE_ENABLE_IOTRACE
156111be35a1SLionel Sambuc   ".iotrace FILE          Enable I/O diagnostic logging to FILE\n"
156211be35a1SLionel Sambuc #endif
156311be35a1SLionel Sambuc #ifndef SQLITE_OMIT_LOAD_EXTENSION
156411be35a1SLionel Sambuc   ".load FILE ?ENTRY?     Load an extension library\n"
156511be35a1SLionel Sambuc #endif
156611be35a1SLionel Sambuc   ".log FILE|off          Turn logging on or off.  FILE can be stderr/stdout\n"
156711be35a1SLionel Sambuc   ".mode MODE ?TABLE?     Set output mode where MODE is one of:\n"
156811be35a1SLionel Sambuc   "                         csv      Comma-separated values\n"
156911be35a1SLionel Sambuc   "                         column   Left-aligned columns.  (See .width)\n"
157011be35a1SLionel Sambuc   "                         html     HTML <table> code\n"
157111be35a1SLionel Sambuc   "                         insert   SQL insert statements for TABLE\n"
157211be35a1SLionel Sambuc   "                         line     One value per line\n"
157311be35a1SLionel Sambuc   "                         list     Values delimited by .separator string\n"
157411be35a1SLionel Sambuc   "                         tabs     Tab-separated values\n"
157511be35a1SLionel Sambuc   "                         tcl      TCL list elements\n"
1576*0a6a1f1dSLionel Sambuc   ".nullvalue STRING      Use STRING in place of NULL values\n"
1577*0a6a1f1dSLionel Sambuc   ".open ?FILENAME?       Close existing database and reopen FILENAME\n"
157811be35a1SLionel Sambuc   ".output FILENAME       Send output to FILENAME\n"
157911be35a1SLionel Sambuc   ".output stdout         Send output to the screen\n"
1580*0a6a1f1dSLionel Sambuc   ".print STRING...       Print literal STRING\n"
158111be35a1SLionel Sambuc   ".prompt MAIN CONTINUE  Replace the standard prompts\n"
158211be35a1SLionel Sambuc   ".quit                  Exit this program\n"
158311be35a1SLionel Sambuc   ".read FILENAME         Execute SQL in FILENAME\n"
158411be35a1SLionel Sambuc   ".restore ?DB? FILE     Restore content of DB (default \"main\") from FILE\n"
158511be35a1SLionel Sambuc   ".schema ?TABLE?        Show the CREATE statements\n"
158611be35a1SLionel Sambuc   "                         If TABLE specified, only show tables matching\n"
158711be35a1SLionel Sambuc   "                         LIKE pattern TABLE.\n"
158811be35a1SLionel Sambuc   ".separator STRING      Change separator used by output mode and .import\n"
158911be35a1SLionel Sambuc   ".show                  Show the current values for various settings\n"
159011be35a1SLionel Sambuc   ".stats ON|OFF          Turn stats on or off\n"
159111be35a1SLionel Sambuc   ".tables ?TABLE?        List names of tables\n"
159211be35a1SLionel Sambuc   "                         If TABLE specified, only list tables matching\n"
159311be35a1SLionel Sambuc   "                         LIKE pattern TABLE.\n"
159411be35a1SLionel Sambuc   ".timeout MS            Try opening locked tables for MS milliseconds\n"
1595*0a6a1f1dSLionel Sambuc   ".trace FILE|off        Output each SQL statement as it is run\n"
159611be35a1SLionel Sambuc   ".vfsname ?AUX?         Print the name of the VFS stack\n"
159711be35a1SLionel Sambuc   ".width NUM1 NUM2 ...   Set column widths for \"column\" mode\n"
159811be35a1SLionel Sambuc ;
159911be35a1SLionel Sambuc 
160011be35a1SLionel Sambuc static char zTimerHelp[] =
160111be35a1SLionel Sambuc   ".timer ON|OFF          Turn the CPU timer measurement on or off\n"
160211be35a1SLionel Sambuc ;
160311be35a1SLionel Sambuc 
160411be35a1SLionel Sambuc /* Forward reference */
160511be35a1SLionel Sambuc static int process_input(struct callback_data *p, FILE *in);
160611be35a1SLionel Sambuc 
160711be35a1SLionel Sambuc /*
160811be35a1SLionel Sambuc ** Make sure the database is open.  If it is not, then open it.  If
160911be35a1SLionel Sambuc ** the database fails to open, print an error message and exit.
161011be35a1SLionel Sambuc */
open_db(struct callback_data * p,int keepAlive)1611*0a6a1f1dSLionel Sambuc static void open_db(struct callback_data *p, int keepAlive){
161211be35a1SLionel Sambuc   if( p->db==0 ){
1613*0a6a1f1dSLionel Sambuc     sqlite3_initialize();
161411be35a1SLionel Sambuc     sqlite3_open(p->zDbFilename, &p->db);
161511be35a1SLionel Sambuc     db = p->db;
161611be35a1SLionel Sambuc     if( db && sqlite3_errcode(db)==SQLITE_OK ){
161711be35a1SLionel Sambuc       sqlite3_create_function(db, "shellstatic", 0, SQLITE_UTF8, 0,
161811be35a1SLionel Sambuc           shellstaticFunc, 0, 0);
161911be35a1SLionel Sambuc     }
162011be35a1SLionel Sambuc     if( db==0 || SQLITE_OK!=sqlite3_errcode(db) ){
162111be35a1SLionel Sambuc       fprintf(stderr,"Error: unable to open database \"%s\": %s\n",
162211be35a1SLionel Sambuc           p->zDbFilename, sqlite3_errmsg(db));
1623*0a6a1f1dSLionel Sambuc       if( keepAlive ) return;
162411be35a1SLionel Sambuc       exit(1);
162511be35a1SLionel Sambuc     }
162611be35a1SLionel Sambuc #ifndef SQLITE_OMIT_LOAD_EXTENSION
162711be35a1SLionel Sambuc     sqlite3_enable_load_extension(p->db, 1);
162811be35a1SLionel Sambuc #endif
162911be35a1SLionel Sambuc   }
163011be35a1SLionel Sambuc }
163111be35a1SLionel Sambuc 
163211be35a1SLionel Sambuc /*
163311be35a1SLionel Sambuc ** Do C-language style dequoting.
163411be35a1SLionel Sambuc **
163511be35a1SLionel Sambuc **    \t    -> tab
163611be35a1SLionel Sambuc **    \n    -> newline
163711be35a1SLionel Sambuc **    \r    -> carriage return
1638*0a6a1f1dSLionel Sambuc **    \"    -> "
163911be35a1SLionel Sambuc **    \NNN  -> ascii character NNN in octal
164011be35a1SLionel Sambuc **    \\    -> backslash
164111be35a1SLionel Sambuc */
resolve_backslashes(char * z)164211be35a1SLionel Sambuc static void resolve_backslashes(char *z){
164311be35a1SLionel Sambuc   int i, j;
164411be35a1SLionel Sambuc   char c;
164511be35a1SLionel Sambuc   for(i=j=0; (c = z[i])!=0; i++, j++){
164611be35a1SLionel Sambuc     if( c=='\\' ){
164711be35a1SLionel Sambuc       c = z[++i];
164811be35a1SLionel Sambuc       if( c=='n' ){
164911be35a1SLionel Sambuc         c = '\n';
165011be35a1SLionel Sambuc       }else if( c=='t' ){
165111be35a1SLionel Sambuc         c = '\t';
165211be35a1SLionel Sambuc       }else if( c=='r' ){
165311be35a1SLionel Sambuc         c = '\r';
1654*0a6a1f1dSLionel Sambuc       }else if( c=='\\' ){
1655*0a6a1f1dSLionel Sambuc         c = '\\';
165611be35a1SLionel Sambuc       }else if( c>='0' && c<='7' ){
165711be35a1SLionel Sambuc         c -= '0';
165811be35a1SLionel Sambuc         if( z[i+1]>='0' && z[i+1]<='7' ){
165911be35a1SLionel Sambuc           i++;
166011be35a1SLionel Sambuc           c = (c<<3) + z[i] - '0';
166111be35a1SLionel Sambuc           if( z[i+1]>='0' && z[i+1]<='7' ){
166211be35a1SLionel Sambuc             i++;
166311be35a1SLionel Sambuc             c = (c<<3) + z[i] - '0';
166411be35a1SLionel Sambuc           }
166511be35a1SLionel Sambuc         }
166611be35a1SLionel Sambuc       }
166711be35a1SLionel Sambuc     }
166811be35a1SLionel Sambuc     z[j] = c;
166911be35a1SLionel Sambuc   }
167011be35a1SLionel Sambuc   z[j] = 0;
167111be35a1SLionel Sambuc }
167211be35a1SLionel Sambuc 
167311be35a1SLionel Sambuc /*
1674*0a6a1f1dSLionel Sambuc ** Return the value of a hexadecimal digit.  Return -1 if the input
1675*0a6a1f1dSLionel Sambuc ** is not a hex digit.
1676*0a6a1f1dSLionel Sambuc */
hexDigitValue(char c)1677*0a6a1f1dSLionel Sambuc static int hexDigitValue(char c){
1678*0a6a1f1dSLionel Sambuc   if( c>='0' && c<='9' ) return c - '0';
1679*0a6a1f1dSLionel Sambuc   if( c>='a' && c<='f' ) return c - 'a' + 10;
1680*0a6a1f1dSLionel Sambuc   if( c>='A' && c<='F' ) return c - 'A' + 10;
1681*0a6a1f1dSLionel Sambuc   return -1;
1682*0a6a1f1dSLionel Sambuc }
1683*0a6a1f1dSLionel Sambuc 
1684*0a6a1f1dSLionel Sambuc /*
1685*0a6a1f1dSLionel Sambuc ** Interpret zArg as an integer value, possibly with suffixes.
1686*0a6a1f1dSLionel Sambuc */
integerValue(const char * zArg)1687*0a6a1f1dSLionel Sambuc static sqlite3_int64 integerValue(const char *zArg){
1688*0a6a1f1dSLionel Sambuc   sqlite3_int64 v = 0;
1689*0a6a1f1dSLionel Sambuc   static const struct { char *zSuffix; int iMult; } aMult[] = {
1690*0a6a1f1dSLionel Sambuc     { "KiB", 1024 },
1691*0a6a1f1dSLionel Sambuc     { "MiB", 1024*1024 },
1692*0a6a1f1dSLionel Sambuc     { "GiB", 1024*1024*1024 },
1693*0a6a1f1dSLionel Sambuc     { "KB",  1000 },
1694*0a6a1f1dSLionel Sambuc     { "MB",  1000000 },
1695*0a6a1f1dSLionel Sambuc     { "GB",  1000000000 },
1696*0a6a1f1dSLionel Sambuc     { "K",   1000 },
1697*0a6a1f1dSLionel Sambuc     { "M",   1000000 },
1698*0a6a1f1dSLionel Sambuc     { "G",   1000000000 },
1699*0a6a1f1dSLionel Sambuc   };
1700*0a6a1f1dSLionel Sambuc   int i;
1701*0a6a1f1dSLionel Sambuc   int isNeg = 0;
1702*0a6a1f1dSLionel Sambuc   if( zArg[0]=='-' ){
1703*0a6a1f1dSLionel Sambuc     isNeg = 1;
1704*0a6a1f1dSLionel Sambuc     zArg++;
1705*0a6a1f1dSLionel Sambuc   }else if( zArg[0]=='+' ){
1706*0a6a1f1dSLionel Sambuc     zArg++;
1707*0a6a1f1dSLionel Sambuc   }
1708*0a6a1f1dSLionel Sambuc   if( zArg[0]=='0' && zArg[1]=='x' ){
1709*0a6a1f1dSLionel Sambuc     int x;
1710*0a6a1f1dSLionel Sambuc     zArg += 2;
1711*0a6a1f1dSLionel Sambuc     while( (x = hexDigitValue(zArg[0]))>=0 ){
1712*0a6a1f1dSLionel Sambuc       v = (v<<4) + x;
1713*0a6a1f1dSLionel Sambuc       zArg++;
1714*0a6a1f1dSLionel Sambuc     }
1715*0a6a1f1dSLionel Sambuc   }else{
1716*0a6a1f1dSLionel Sambuc     while( IsDigit(zArg[0]) ){
1717*0a6a1f1dSLionel Sambuc       v = v*10 + zArg[0] - '0';
1718*0a6a1f1dSLionel Sambuc       zArg++;
1719*0a6a1f1dSLionel Sambuc     }
1720*0a6a1f1dSLionel Sambuc   }
1721*0a6a1f1dSLionel Sambuc   for(i=0; i<ArraySize(aMult); i++){
1722*0a6a1f1dSLionel Sambuc     if( sqlite3_stricmp(aMult[i].zSuffix, zArg)==0 ){
1723*0a6a1f1dSLionel Sambuc       v *= aMult[i].iMult;
1724*0a6a1f1dSLionel Sambuc       break;
1725*0a6a1f1dSLionel Sambuc     }
1726*0a6a1f1dSLionel Sambuc   }
1727*0a6a1f1dSLionel Sambuc   return isNeg? -v : v;
1728*0a6a1f1dSLionel Sambuc }
1729*0a6a1f1dSLionel Sambuc 
1730*0a6a1f1dSLionel Sambuc /*
1731*0a6a1f1dSLionel Sambuc ** Interpret zArg as either an integer or a boolean value.  Return 1 or 0
1732*0a6a1f1dSLionel Sambuc ** for TRUE and FALSE.  Return the integer value if appropriate.
173311be35a1SLionel Sambuc */
booleanValue(char * zArg)173411be35a1SLionel Sambuc static int booleanValue(char *zArg){
1735*0a6a1f1dSLionel Sambuc   int i;
1736*0a6a1f1dSLionel Sambuc   if( zArg[0]=='0' && zArg[1]=='x' ){
1737*0a6a1f1dSLionel Sambuc     for(i=2; hexDigitValue(zArg[i])>=0; i++){}
1738*0a6a1f1dSLionel Sambuc   }else{
1739*0a6a1f1dSLionel Sambuc     for(i=0; zArg[i]>='0' && zArg[i]<='9'; i++){}
174011be35a1SLionel Sambuc   }
1741*0a6a1f1dSLionel Sambuc   if( i>0 && zArg[i]==0 ) return (int)(integerValue(zArg) & 0xffffffff);
1742*0a6a1f1dSLionel Sambuc   if( sqlite3_stricmp(zArg, "on")==0 || sqlite3_stricmp(zArg,"yes")==0 ){
1743*0a6a1f1dSLionel Sambuc     return 1;
174411be35a1SLionel Sambuc   }
1745*0a6a1f1dSLionel Sambuc   if( sqlite3_stricmp(zArg, "off")==0 || sqlite3_stricmp(zArg,"no")==0 ){
1746*0a6a1f1dSLionel Sambuc     return 0;
1747*0a6a1f1dSLionel Sambuc   }
1748*0a6a1f1dSLionel Sambuc   fprintf(stderr, "ERROR: Not a boolean value: \"%s\". Assuming \"no\".\n",
1749*0a6a1f1dSLionel Sambuc           zArg);
1750*0a6a1f1dSLionel Sambuc   return 0;
1751*0a6a1f1dSLionel Sambuc }
1752*0a6a1f1dSLionel Sambuc 
1753*0a6a1f1dSLionel Sambuc /*
1754*0a6a1f1dSLionel Sambuc ** Close an output file, assuming it is not stderr or stdout
1755*0a6a1f1dSLionel Sambuc */
output_file_close(FILE * f)1756*0a6a1f1dSLionel Sambuc static void output_file_close(FILE *f){
1757*0a6a1f1dSLionel Sambuc   if( f && f!=stdout && f!=stderr ) fclose(f);
1758*0a6a1f1dSLionel Sambuc }
1759*0a6a1f1dSLionel Sambuc 
1760*0a6a1f1dSLionel Sambuc /*
1761*0a6a1f1dSLionel Sambuc ** Try to open an output file.   The names "stdout" and "stderr" are
1762*0a6a1f1dSLionel Sambuc ** recognized and do the right thing.  NULL is returned if the output
1763*0a6a1f1dSLionel Sambuc ** filename is "off".
1764*0a6a1f1dSLionel Sambuc */
output_file_open(const char * zFile)1765*0a6a1f1dSLionel Sambuc static FILE *output_file_open(const char *zFile){
1766*0a6a1f1dSLionel Sambuc   FILE *f;
1767*0a6a1f1dSLionel Sambuc   if( strcmp(zFile,"stdout")==0 ){
1768*0a6a1f1dSLionel Sambuc     f = stdout;
1769*0a6a1f1dSLionel Sambuc   }else if( strcmp(zFile, "stderr")==0 ){
1770*0a6a1f1dSLionel Sambuc     f = stderr;
1771*0a6a1f1dSLionel Sambuc   }else if( strcmp(zFile, "off")==0 ){
1772*0a6a1f1dSLionel Sambuc     f = 0;
1773*0a6a1f1dSLionel Sambuc   }else{
1774*0a6a1f1dSLionel Sambuc     f = fopen(zFile, "wb");
1775*0a6a1f1dSLionel Sambuc     if( f==0 ){
1776*0a6a1f1dSLionel Sambuc       fprintf(stderr, "Error: cannot open \"%s\"\n", zFile);
1777*0a6a1f1dSLionel Sambuc     }
1778*0a6a1f1dSLionel Sambuc   }
1779*0a6a1f1dSLionel Sambuc   return f;
1780*0a6a1f1dSLionel Sambuc }
1781*0a6a1f1dSLionel Sambuc 
1782*0a6a1f1dSLionel Sambuc /*
1783*0a6a1f1dSLionel Sambuc ** A routine for handling output from sqlite3_trace().
1784*0a6a1f1dSLionel Sambuc */
sql_trace_callback(void * pArg,const char * z)1785*0a6a1f1dSLionel Sambuc static void sql_trace_callback(void *pArg, const char *z){
1786*0a6a1f1dSLionel Sambuc   FILE *f = (FILE*)pArg;
1787*0a6a1f1dSLionel Sambuc   if( f ) fprintf(f, "%s\n", z);
1788*0a6a1f1dSLionel Sambuc }
1789*0a6a1f1dSLionel Sambuc 
1790*0a6a1f1dSLionel Sambuc /*
1791*0a6a1f1dSLionel Sambuc ** A no-op routine that runs with the ".breakpoint" doc-command.  This is
1792*0a6a1f1dSLionel Sambuc ** a useful spot to set a debugger breakpoint.
1793*0a6a1f1dSLionel Sambuc */
test_breakpoint(void)1794*0a6a1f1dSLionel Sambuc static void test_breakpoint(void){
1795*0a6a1f1dSLionel Sambuc   static int nCall = 0;
1796*0a6a1f1dSLionel Sambuc   nCall++;
1797*0a6a1f1dSLionel Sambuc }
1798*0a6a1f1dSLionel Sambuc 
1799*0a6a1f1dSLionel Sambuc /*
1800*0a6a1f1dSLionel Sambuc ** An object used to read a CSV file
1801*0a6a1f1dSLionel Sambuc */
1802*0a6a1f1dSLionel Sambuc typedef struct CSVReader CSVReader;
1803*0a6a1f1dSLionel Sambuc struct CSVReader {
1804*0a6a1f1dSLionel Sambuc   const char *zFile;  /* Name of the input file */
1805*0a6a1f1dSLionel Sambuc   FILE *in;           /* Read the CSV text from this input stream */
1806*0a6a1f1dSLionel Sambuc   char *z;            /* Accumulated text for a field */
1807*0a6a1f1dSLionel Sambuc   int n;              /* Number of bytes in z */
1808*0a6a1f1dSLionel Sambuc   int nAlloc;         /* Space allocated for z[] */
1809*0a6a1f1dSLionel Sambuc   int nLine;          /* Current line number */
1810*0a6a1f1dSLionel Sambuc   int cTerm;          /* Character that terminated the most recent field */
1811*0a6a1f1dSLionel Sambuc   int cSeparator;     /* The separator character.  (Usually ",") */
1812*0a6a1f1dSLionel Sambuc };
1813*0a6a1f1dSLionel Sambuc 
1814*0a6a1f1dSLionel Sambuc /* Append a single byte to z[] */
csv_append_char(CSVReader * p,int c)1815*0a6a1f1dSLionel Sambuc static void csv_append_char(CSVReader *p, int c){
1816*0a6a1f1dSLionel Sambuc   if( p->n+1>=p->nAlloc ){
1817*0a6a1f1dSLionel Sambuc     p->nAlloc += p->nAlloc + 100;
1818*0a6a1f1dSLionel Sambuc     p->z = sqlite3_realloc(p->z, p->nAlloc);
1819*0a6a1f1dSLionel Sambuc     if( p->z==0 ){
1820*0a6a1f1dSLionel Sambuc       fprintf(stderr, "out of memory\n");
1821*0a6a1f1dSLionel Sambuc       exit(1);
1822*0a6a1f1dSLionel Sambuc     }
1823*0a6a1f1dSLionel Sambuc   }
1824*0a6a1f1dSLionel Sambuc   p->z[p->n++] = (char)c;
1825*0a6a1f1dSLionel Sambuc }
1826*0a6a1f1dSLionel Sambuc 
1827*0a6a1f1dSLionel Sambuc /* Read a single field of CSV text.  Compatible with rfc4180 and extended
1828*0a6a1f1dSLionel Sambuc ** with the option of having a separator other than ",".
1829*0a6a1f1dSLionel Sambuc **
1830*0a6a1f1dSLionel Sambuc **   +  Input comes from p->in.
1831*0a6a1f1dSLionel Sambuc **   +  Store results in p->z of length p->n.  Space to hold p->z comes
1832*0a6a1f1dSLionel Sambuc **      from sqlite3_malloc().
1833*0a6a1f1dSLionel Sambuc **   +  Use p->cSep as the separator.  The default is ",".
1834*0a6a1f1dSLionel Sambuc **   +  Keep track of the line number in p->nLine.
1835*0a6a1f1dSLionel Sambuc **   +  Store the character that terminates the field in p->cTerm.  Store
1836*0a6a1f1dSLionel Sambuc **      EOF on end-of-file.
1837*0a6a1f1dSLionel Sambuc **   +  Report syntax errors on stderr
1838*0a6a1f1dSLionel Sambuc */
csv_read_one_field(CSVReader * p)1839*0a6a1f1dSLionel Sambuc static char *csv_read_one_field(CSVReader *p){
1840*0a6a1f1dSLionel Sambuc   int c, pc, ppc;
1841*0a6a1f1dSLionel Sambuc   int cSep = p->cSeparator;
1842*0a6a1f1dSLionel Sambuc   p->n = 0;
1843*0a6a1f1dSLionel Sambuc   c = fgetc(p->in);
1844*0a6a1f1dSLionel Sambuc   if( c==EOF || seenInterrupt ){
1845*0a6a1f1dSLionel Sambuc     p->cTerm = EOF;
1846*0a6a1f1dSLionel Sambuc     return 0;
1847*0a6a1f1dSLionel Sambuc   }
1848*0a6a1f1dSLionel Sambuc   if( c=='"' ){
1849*0a6a1f1dSLionel Sambuc     int startLine = p->nLine;
1850*0a6a1f1dSLionel Sambuc     int cQuote = c;
1851*0a6a1f1dSLionel Sambuc     pc = ppc = 0;
1852*0a6a1f1dSLionel Sambuc     while( 1 ){
1853*0a6a1f1dSLionel Sambuc       c = fgetc(p->in);
1854*0a6a1f1dSLionel Sambuc       if( c=='\n' ) p->nLine++;
1855*0a6a1f1dSLionel Sambuc       if( c==cQuote ){
1856*0a6a1f1dSLionel Sambuc         if( pc==cQuote ){
1857*0a6a1f1dSLionel Sambuc           pc = 0;
1858*0a6a1f1dSLionel Sambuc           continue;
1859*0a6a1f1dSLionel Sambuc         }
1860*0a6a1f1dSLionel Sambuc       }
1861*0a6a1f1dSLionel Sambuc       if( (c==cSep && pc==cQuote)
1862*0a6a1f1dSLionel Sambuc        || (c=='\n' && pc==cQuote)
1863*0a6a1f1dSLionel Sambuc        || (c=='\n' && pc=='\r' && ppc==cQuote)
1864*0a6a1f1dSLionel Sambuc        || (c==EOF && pc==cQuote)
1865*0a6a1f1dSLionel Sambuc       ){
1866*0a6a1f1dSLionel Sambuc         do{ p->n--; }while( p->z[p->n]!=cQuote );
1867*0a6a1f1dSLionel Sambuc         p->cTerm = c;
1868*0a6a1f1dSLionel Sambuc         break;
1869*0a6a1f1dSLionel Sambuc       }
1870*0a6a1f1dSLionel Sambuc       if( pc==cQuote && c!='\r' ){
1871*0a6a1f1dSLionel Sambuc         fprintf(stderr, "%s:%d: unescaped %c character\n",
1872*0a6a1f1dSLionel Sambuc                 p->zFile, p->nLine, cQuote);
1873*0a6a1f1dSLionel Sambuc       }
1874*0a6a1f1dSLionel Sambuc       if( c==EOF ){
1875*0a6a1f1dSLionel Sambuc         fprintf(stderr, "%s:%d: unterminated %c-quoted field\n",
1876*0a6a1f1dSLionel Sambuc                 p->zFile, startLine, cQuote);
1877*0a6a1f1dSLionel Sambuc         p->cTerm = EOF;
1878*0a6a1f1dSLionel Sambuc         break;
1879*0a6a1f1dSLionel Sambuc       }
1880*0a6a1f1dSLionel Sambuc       csv_append_char(p, c);
1881*0a6a1f1dSLionel Sambuc       ppc = pc;
1882*0a6a1f1dSLionel Sambuc       pc = c;
1883*0a6a1f1dSLionel Sambuc     }
1884*0a6a1f1dSLionel Sambuc   }else{
1885*0a6a1f1dSLionel Sambuc     while( c!=EOF && c!=cSep && c!='\n' ){
1886*0a6a1f1dSLionel Sambuc       csv_append_char(p, c);
1887*0a6a1f1dSLionel Sambuc       c = fgetc(p->in);
1888*0a6a1f1dSLionel Sambuc     }
1889*0a6a1f1dSLionel Sambuc     if( c=='\n' ){
1890*0a6a1f1dSLionel Sambuc       p->nLine++;
1891*0a6a1f1dSLionel Sambuc       if( p->n>1 && p->z[p->n-1]=='\r' ) p->n--;
1892*0a6a1f1dSLionel Sambuc     }
1893*0a6a1f1dSLionel Sambuc     p->cTerm = c;
1894*0a6a1f1dSLionel Sambuc   }
1895*0a6a1f1dSLionel Sambuc   if( p->z ) p->z[p->n] = 0;
1896*0a6a1f1dSLionel Sambuc   return p->z;
189711be35a1SLionel Sambuc }
189811be35a1SLionel Sambuc 
189911be35a1SLionel Sambuc /*
190011be35a1SLionel Sambuc ** If an input line begins with "." then invoke this routine to
190111be35a1SLionel Sambuc ** process that line.
190211be35a1SLionel Sambuc **
190311be35a1SLionel Sambuc ** Return 1 on error, 2 to exit, and 0 otherwise.
190411be35a1SLionel Sambuc */
do_meta_command(char * zLine,struct callback_data * p)190511be35a1SLionel Sambuc static int do_meta_command(char *zLine, struct callback_data *p){
190611be35a1SLionel Sambuc   int i = 1;
190711be35a1SLionel Sambuc   int nArg = 0;
190811be35a1SLionel Sambuc   int n, c;
190911be35a1SLionel Sambuc   int rc = 0;
191011be35a1SLionel Sambuc   char *azArg[50];
191111be35a1SLionel Sambuc 
191211be35a1SLionel Sambuc   /* Parse the input line into tokens.
191311be35a1SLionel Sambuc   */
191411be35a1SLionel Sambuc   while( zLine[i] && nArg<ArraySize(azArg) ){
191511be35a1SLionel Sambuc     while( IsSpace(zLine[i]) ){ i++; }
191611be35a1SLionel Sambuc     if( zLine[i]==0 ) break;
191711be35a1SLionel Sambuc     if( zLine[i]=='\'' || zLine[i]=='"' ){
191811be35a1SLionel Sambuc       int delim = zLine[i++];
191911be35a1SLionel Sambuc       azArg[nArg++] = &zLine[i];
1920*0a6a1f1dSLionel Sambuc       while( zLine[i] && zLine[i]!=delim ){
1921*0a6a1f1dSLionel Sambuc         if( zLine[i]=='\\' && delim=='"' && zLine[i+1]!=0 ) i++;
1922*0a6a1f1dSLionel Sambuc         i++;
1923*0a6a1f1dSLionel Sambuc       }
192411be35a1SLionel Sambuc       if( zLine[i]==delim ){
192511be35a1SLionel Sambuc         zLine[i++] = 0;
192611be35a1SLionel Sambuc       }
192711be35a1SLionel Sambuc       if( delim=='"' ) resolve_backslashes(azArg[nArg-1]);
192811be35a1SLionel Sambuc     }else{
192911be35a1SLionel Sambuc       azArg[nArg++] = &zLine[i];
193011be35a1SLionel Sambuc       while( zLine[i] && !IsSpace(zLine[i]) ){ i++; }
193111be35a1SLionel Sambuc       if( zLine[i] ) zLine[i++] = 0;
193211be35a1SLionel Sambuc       resolve_backslashes(azArg[nArg-1]);
193311be35a1SLionel Sambuc     }
193411be35a1SLionel Sambuc   }
193511be35a1SLionel Sambuc 
193611be35a1SLionel Sambuc   /* Process the input line.
193711be35a1SLionel Sambuc   */
193811be35a1SLionel Sambuc   if( nArg==0 ) return 0; /* no tokens, no error */
193911be35a1SLionel Sambuc   n = strlen30(azArg[0]);
194011be35a1SLionel Sambuc   c = azArg[0][0];
1941*0a6a1f1dSLionel Sambuc   if( c=='b' && n>=3 && strncmp(azArg[0], "backup", n)==0 ){
1942*0a6a1f1dSLionel Sambuc     const char *zDestFile = 0;
1943*0a6a1f1dSLionel Sambuc     const char *zDb = 0;
194411be35a1SLionel Sambuc     sqlite3 *pDest;
194511be35a1SLionel Sambuc     sqlite3_backup *pBackup;
1946*0a6a1f1dSLionel Sambuc     int j;
1947*0a6a1f1dSLionel Sambuc     for(j=1; j<nArg; j++){
1948*0a6a1f1dSLionel Sambuc       const char *z = azArg[j];
1949*0a6a1f1dSLionel Sambuc       if( z[0]=='-' ){
1950*0a6a1f1dSLionel Sambuc         while( z[0]=='-' ) z++;
1951*0a6a1f1dSLionel Sambuc         /* No options to process at this time */
1952*0a6a1f1dSLionel Sambuc         {
1953*0a6a1f1dSLionel Sambuc           fprintf(stderr, "unknown option: %s\n", azArg[j]);
1954*0a6a1f1dSLionel Sambuc           return 1;
195511be35a1SLionel Sambuc         }
1956*0a6a1f1dSLionel Sambuc       }else if( zDestFile==0 ){
1957*0a6a1f1dSLionel Sambuc         zDestFile = azArg[j];
1958*0a6a1f1dSLionel Sambuc       }else if( zDb==0 ){
1959*0a6a1f1dSLionel Sambuc         zDb = zDestFile;
1960*0a6a1f1dSLionel Sambuc         zDestFile = azArg[j];
1961*0a6a1f1dSLionel Sambuc       }else{
1962*0a6a1f1dSLionel Sambuc         fprintf(stderr, "too many arguments to .backup\n");
1963*0a6a1f1dSLionel Sambuc         return 1;
1964*0a6a1f1dSLionel Sambuc       }
1965*0a6a1f1dSLionel Sambuc     }
1966*0a6a1f1dSLionel Sambuc     if( zDestFile==0 ){
1967*0a6a1f1dSLionel Sambuc       fprintf(stderr, "missing FILENAME argument on .backup\n");
1968*0a6a1f1dSLionel Sambuc       return 1;
1969*0a6a1f1dSLionel Sambuc     }
1970*0a6a1f1dSLionel Sambuc     if( zDb==0 ) zDb = "main";
197111be35a1SLionel Sambuc     rc = sqlite3_open(zDestFile, &pDest);
197211be35a1SLionel Sambuc     if( rc!=SQLITE_OK ){
197311be35a1SLionel Sambuc       fprintf(stderr, "Error: cannot open \"%s\"\n", zDestFile);
197411be35a1SLionel Sambuc       sqlite3_close(pDest);
197511be35a1SLionel Sambuc       return 1;
197611be35a1SLionel Sambuc     }
1977*0a6a1f1dSLionel Sambuc     open_db(p, 0);
197811be35a1SLionel Sambuc     pBackup = sqlite3_backup_init(pDest, "main", p->db, zDb);
197911be35a1SLionel Sambuc     if( pBackup==0 ){
198011be35a1SLionel Sambuc       fprintf(stderr, "Error: %s\n", sqlite3_errmsg(pDest));
198111be35a1SLionel Sambuc       sqlite3_close(pDest);
198211be35a1SLionel Sambuc       return 1;
198311be35a1SLionel Sambuc     }
198411be35a1SLionel Sambuc     while(  (rc = sqlite3_backup_step(pBackup,100))==SQLITE_OK ){}
198511be35a1SLionel Sambuc     sqlite3_backup_finish(pBackup);
198611be35a1SLionel Sambuc     if( rc==SQLITE_DONE ){
198711be35a1SLionel Sambuc       rc = 0;
198811be35a1SLionel Sambuc     }else{
198911be35a1SLionel Sambuc       fprintf(stderr, "Error: %s\n", sqlite3_errmsg(pDest));
199011be35a1SLionel Sambuc       rc = 1;
199111be35a1SLionel Sambuc     }
199211be35a1SLionel Sambuc     sqlite3_close(pDest);
199311be35a1SLionel Sambuc   }else
199411be35a1SLionel Sambuc 
199511be35a1SLionel Sambuc   if( c=='b' && n>=3 && strncmp(azArg[0], "bail", n)==0 && nArg>1 && nArg<3 ){
199611be35a1SLionel Sambuc     bail_on_error = booleanValue(azArg[1]);
199711be35a1SLionel Sambuc   }else
199811be35a1SLionel Sambuc 
1999*0a6a1f1dSLionel Sambuc   /* The undocumented ".breakpoint" command causes a call to the no-op
2000*0a6a1f1dSLionel Sambuc   ** routine named test_breakpoint().
2001*0a6a1f1dSLionel Sambuc   */
2002*0a6a1f1dSLionel Sambuc   if( c=='b' && n>=3 && strncmp(azArg[0], "breakpoint", n)==0 ){
2003*0a6a1f1dSLionel Sambuc     test_breakpoint();
2004*0a6a1f1dSLionel Sambuc   }else
2005*0a6a1f1dSLionel Sambuc 
200611be35a1SLionel Sambuc   if( c=='d' && n>1 && strncmp(azArg[0], "databases", n)==0 && nArg==1 ){
200711be35a1SLionel Sambuc     struct callback_data data;
200811be35a1SLionel Sambuc     char *zErrMsg = 0;
2009*0a6a1f1dSLionel Sambuc     open_db(p, 0);
201011be35a1SLionel Sambuc     memcpy(&data, p, sizeof(data));
201111be35a1SLionel Sambuc     data.showHeader = 1;
201211be35a1SLionel Sambuc     data.mode = MODE_Column;
201311be35a1SLionel Sambuc     data.colWidth[0] = 3;
201411be35a1SLionel Sambuc     data.colWidth[1] = 15;
201511be35a1SLionel Sambuc     data.colWidth[2] = 58;
201611be35a1SLionel Sambuc     data.cnt = 0;
201711be35a1SLionel Sambuc     sqlite3_exec(p->db, "PRAGMA database_list; ", callback, &data, &zErrMsg);
201811be35a1SLionel Sambuc     if( zErrMsg ){
201911be35a1SLionel Sambuc       fprintf(stderr,"Error: %s\n", zErrMsg);
202011be35a1SLionel Sambuc       sqlite3_free(zErrMsg);
202111be35a1SLionel Sambuc       rc = 1;
202211be35a1SLionel Sambuc     }
202311be35a1SLionel Sambuc   }else
202411be35a1SLionel Sambuc 
202511be35a1SLionel Sambuc   if( c=='d' && strncmp(azArg[0], "dump", n)==0 && nArg<3 ){
2026*0a6a1f1dSLionel Sambuc     open_db(p, 0);
202711be35a1SLionel Sambuc     /* When playing back a "dump", the content might appear in an order
202811be35a1SLionel Sambuc     ** which causes immediate foreign key constraints to be violated.
202911be35a1SLionel Sambuc     ** So disable foreign-key constraint enforcement to prevent problems. */
203011be35a1SLionel Sambuc     fprintf(p->out, "PRAGMA foreign_keys=OFF;\n");
203111be35a1SLionel Sambuc     fprintf(p->out, "BEGIN TRANSACTION;\n");
203211be35a1SLionel Sambuc     p->writableSchema = 0;
203311be35a1SLionel Sambuc     sqlite3_exec(p->db, "SAVEPOINT dump; PRAGMA writable_schema=ON", 0, 0, 0);
203411be35a1SLionel Sambuc     p->nErr = 0;
203511be35a1SLionel Sambuc     if( nArg==1 ){
203611be35a1SLionel Sambuc       run_schema_dump_query(p,
203711be35a1SLionel Sambuc         "SELECT name, type, sql FROM sqlite_master "
203811be35a1SLionel Sambuc         "WHERE sql NOT NULL AND type=='table' AND name!='sqlite_sequence'"
203911be35a1SLionel Sambuc       );
204011be35a1SLionel Sambuc       run_schema_dump_query(p,
204111be35a1SLionel Sambuc         "SELECT name, type, sql FROM sqlite_master "
204211be35a1SLionel Sambuc         "WHERE name=='sqlite_sequence'"
204311be35a1SLionel Sambuc       );
204411be35a1SLionel Sambuc       run_table_dump_query(p,
204511be35a1SLionel Sambuc         "SELECT sql FROM sqlite_master "
204611be35a1SLionel Sambuc         "WHERE sql NOT NULL AND type IN ('index','trigger','view')", 0
204711be35a1SLionel Sambuc       );
204811be35a1SLionel Sambuc     }else{
204911be35a1SLionel Sambuc       int i;
205011be35a1SLionel Sambuc       for(i=1; i<nArg; i++){
205111be35a1SLionel Sambuc         zShellStatic = azArg[i];
205211be35a1SLionel Sambuc         run_schema_dump_query(p,
205311be35a1SLionel Sambuc           "SELECT name, type, sql FROM sqlite_master "
205411be35a1SLionel Sambuc           "WHERE tbl_name LIKE shellstatic() AND type=='table'"
205511be35a1SLionel Sambuc           "  AND sql NOT NULL");
205611be35a1SLionel Sambuc         run_table_dump_query(p,
205711be35a1SLionel Sambuc           "SELECT sql FROM sqlite_master "
205811be35a1SLionel Sambuc           "WHERE sql NOT NULL"
205911be35a1SLionel Sambuc           "  AND type IN ('index','trigger','view')"
206011be35a1SLionel Sambuc           "  AND tbl_name LIKE shellstatic()", 0
206111be35a1SLionel Sambuc         );
206211be35a1SLionel Sambuc         zShellStatic = 0;
206311be35a1SLionel Sambuc       }
206411be35a1SLionel Sambuc     }
206511be35a1SLionel Sambuc     if( p->writableSchema ){
206611be35a1SLionel Sambuc       fprintf(p->out, "PRAGMA writable_schema=OFF;\n");
206711be35a1SLionel Sambuc       p->writableSchema = 0;
206811be35a1SLionel Sambuc     }
206911be35a1SLionel Sambuc     sqlite3_exec(p->db, "PRAGMA writable_schema=OFF;", 0, 0, 0);
207011be35a1SLionel Sambuc     sqlite3_exec(p->db, "RELEASE dump;", 0, 0, 0);
207111be35a1SLionel Sambuc     fprintf(p->out, p->nErr ? "ROLLBACK; -- due to errors\n" : "COMMIT;\n");
207211be35a1SLionel Sambuc   }else
207311be35a1SLionel Sambuc 
207411be35a1SLionel Sambuc   if( c=='e' && strncmp(azArg[0], "echo", n)==0 && nArg>1 && nArg<3 ){
207511be35a1SLionel Sambuc     p->echoOn = booleanValue(azArg[1]);
207611be35a1SLionel Sambuc   }else
207711be35a1SLionel Sambuc 
2078*0a6a1f1dSLionel Sambuc   if( c=='e' && strncmp(azArg[0], "exit", n)==0 ){
2079*0a6a1f1dSLionel Sambuc     if( nArg>1 && (rc = (int)integerValue(azArg[1]))!=0 ) exit(rc);
208011be35a1SLionel Sambuc     rc = 2;
208111be35a1SLionel Sambuc   }else
208211be35a1SLionel Sambuc 
208311be35a1SLionel Sambuc   if( c=='e' && strncmp(azArg[0], "explain", n)==0 && nArg<3 ){
208411be35a1SLionel Sambuc     int val = nArg>=2 ? booleanValue(azArg[1]) : 1;
208511be35a1SLionel Sambuc     if(val == 1) {
208611be35a1SLionel Sambuc       if(!p->explainPrev.valid) {
208711be35a1SLionel Sambuc         p->explainPrev.valid = 1;
208811be35a1SLionel Sambuc         p->explainPrev.mode = p->mode;
208911be35a1SLionel Sambuc         p->explainPrev.showHeader = p->showHeader;
209011be35a1SLionel Sambuc         memcpy(p->explainPrev.colWidth,p->colWidth,sizeof(p->colWidth));
209111be35a1SLionel Sambuc       }
209211be35a1SLionel Sambuc       /* We could put this code under the !p->explainValid
209311be35a1SLionel Sambuc       ** condition so that it does not execute if we are already in
209411be35a1SLionel Sambuc       ** explain mode. However, always executing it allows us an easy
209511be35a1SLionel Sambuc       ** was to reset to explain mode in case the user previously
209611be35a1SLionel Sambuc       ** did an .explain followed by a .width, .mode or .header
209711be35a1SLionel Sambuc       ** command.
209811be35a1SLionel Sambuc       */
209911be35a1SLionel Sambuc       p->mode = MODE_Explain;
210011be35a1SLionel Sambuc       p->showHeader = 1;
2101*0a6a1f1dSLionel Sambuc       memset(p->colWidth,0,sizeof(p->colWidth));
210211be35a1SLionel Sambuc       p->colWidth[0] = 4;                  /* addr */
210311be35a1SLionel Sambuc       p->colWidth[1] = 13;                 /* opcode */
210411be35a1SLionel Sambuc       p->colWidth[2] = 4;                  /* P1 */
210511be35a1SLionel Sambuc       p->colWidth[3] = 4;                  /* P2 */
210611be35a1SLionel Sambuc       p->colWidth[4] = 4;                  /* P3 */
210711be35a1SLionel Sambuc       p->colWidth[5] = 13;                 /* P4 */
210811be35a1SLionel Sambuc       p->colWidth[6] = 2;                  /* P5 */
210911be35a1SLionel Sambuc       p->colWidth[7] = 13;                  /* Comment */
211011be35a1SLionel Sambuc     }else if (p->explainPrev.valid) {
211111be35a1SLionel Sambuc       p->explainPrev.valid = 0;
211211be35a1SLionel Sambuc       p->mode = p->explainPrev.mode;
211311be35a1SLionel Sambuc       p->showHeader = p->explainPrev.showHeader;
211411be35a1SLionel Sambuc       memcpy(p->colWidth,p->explainPrev.colWidth,sizeof(p->colWidth));
211511be35a1SLionel Sambuc     }
211611be35a1SLionel Sambuc   }else
211711be35a1SLionel Sambuc 
211811be35a1SLionel Sambuc   if( c=='h' && (strncmp(azArg[0], "header", n)==0 ||
211911be35a1SLionel Sambuc                  strncmp(azArg[0], "headers", n)==0) && nArg>1 && nArg<3 ){
212011be35a1SLionel Sambuc     p->showHeader = booleanValue(azArg[1]);
212111be35a1SLionel Sambuc   }else
212211be35a1SLionel Sambuc 
212311be35a1SLionel Sambuc   if( c=='h' && strncmp(azArg[0], "help", n)==0 ){
212411be35a1SLionel Sambuc     fprintf(stderr,"%s",zHelp);
212511be35a1SLionel Sambuc     if( HAS_TIMER ){
212611be35a1SLionel Sambuc       fprintf(stderr,"%s",zTimerHelp);
212711be35a1SLionel Sambuc     }
212811be35a1SLionel Sambuc   }else
212911be35a1SLionel Sambuc 
213011be35a1SLionel Sambuc   if( c=='i' && strncmp(azArg[0], "import", n)==0 && nArg==3 ){
213111be35a1SLionel Sambuc     char *zTable = azArg[2];    /* Insert data into this table */
2132*0a6a1f1dSLionel Sambuc     char *zFile = azArg[1];     /* Name of file to extra content from */
213311be35a1SLionel Sambuc     sqlite3_stmt *pStmt = NULL; /* A statement */
213411be35a1SLionel Sambuc     int nCol;                   /* Number of columns in the table */
213511be35a1SLionel Sambuc     int nByte;                  /* Number of bytes in an SQL string */
213611be35a1SLionel Sambuc     int i, j;                   /* Loop counters */
2137*0a6a1f1dSLionel Sambuc     int needCommit;             /* True to COMMIT or ROLLBACK at end */
213811be35a1SLionel Sambuc     int nSep;                   /* Number of bytes in p->separator[] */
213911be35a1SLionel Sambuc     char *zSql;                 /* An SQL statement */
2140*0a6a1f1dSLionel Sambuc     CSVReader sCsv;             /* Reader context */
2141*0a6a1f1dSLionel Sambuc     int (*xCloser)(FILE*);      /* Procedure to close th3 connection */
214211be35a1SLionel Sambuc 
2143*0a6a1f1dSLionel Sambuc     seenInterrupt = 0;
2144*0a6a1f1dSLionel Sambuc     memset(&sCsv, 0, sizeof(sCsv));
2145*0a6a1f1dSLionel Sambuc     open_db(p, 0);
214611be35a1SLionel Sambuc     nSep = strlen30(p->separator);
214711be35a1SLionel Sambuc     if( nSep==0 ){
214811be35a1SLionel Sambuc       fprintf(stderr, "Error: non-null separator required for import\n");
214911be35a1SLionel Sambuc       return 1;
215011be35a1SLionel Sambuc     }
2151*0a6a1f1dSLionel Sambuc     if( nSep>1 ){
2152*0a6a1f1dSLionel Sambuc       fprintf(stderr, "Error: multi-character separators not allowed"
2153*0a6a1f1dSLionel Sambuc                       " for import\n");
2154*0a6a1f1dSLionel Sambuc       return 1;
2155*0a6a1f1dSLionel Sambuc     }
2156*0a6a1f1dSLionel Sambuc     sCsv.zFile = zFile;
2157*0a6a1f1dSLionel Sambuc     sCsv.nLine = 1;
2158*0a6a1f1dSLionel Sambuc     if( sCsv.zFile[0]=='|' ){
2159*0a6a1f1dSLionel Sambuc       sCsv.in = popen(sCsv.zFile+1, "r");
2160*0a6a1f1dSLionel Sambuc       sCsv.zFile = "<pipe>";
2161*0a6a1f1dSLionel Sambuc       xCloser = pclose;
2162*0a6a1f1dSLionel Sambuc     }else{
2163*0a6a1f1dSLionel Sambuc       sCsv.in = fopen(sCsv.zFile, "rb");
2164*0a6a1f1dSLionel Sambuc       xCloser = fclose;
2165*0a6a1f1dSLionel Sambuc     }
2166*0a6a1f1dSLionel Sambuc     if( sCsv.in==0 ){
2167*0a6a1f1dSLionel Sambuc       fprintf(stderr, "Error: cannot open \"%s\"\n", zFile);
2168*0a6a1f1dSLionel Sambuc       return 1;
2169*0a6a1f1dSLionel Sambuc     }
2170*0a6a1f1dSLionel Sambuc     sCsv.cSeparator = p->separator[0];
217111be35a1SLionel Sambuc     zSql = sqlite3_mprintf("SELECT * FROM %s", zTable);
217211be35a1SLionel Sambuc     if( zSql==0 ){
217311be35a1SLionel Sambuc       fprintf(stderr, "Error: out of memory\n");
2174*0a6a1f1dSLionel Sambuc       xCloser(sCsv.in);
217511be35a1SLionel Sambuc       return 1;
217611be35a1SLionel Sambuc     }
217711be35a1SLionel Sambuc     nByte = strlen30(zSql);
217811be35a1SLionel Sambuc     rc = sqlite3_prepare(p->db, zSql, -1, &pStmt, 0);
2179*0a6a1f1dSLionel Sambuc     if( rc && sqlite3_strglob("no such table: *", sqlite3_errmsg(db))==0 ){
2180*0a6a1f1dSLionel Sambuc       char *zCreate = sqlite3_mprintf("CREATE TABLE %s", zTable);
2181*0a6a1f1dSLionel Sambuc       char cSep = '(';
2182*0a6a1f1dSLionel Sambuc       while( csv_read_one_field(&sCsv) ){
2183*0a6a1f1dSLionel Sambuc         zCreate = sqlite3_mprintf("%z%c\n  \"%s\" TEXT", zCreate, cSep, sCsv.z);
2184*0a6a1f1dSLionel Sambuc         cSep = ',';
2185*0a6a1f1dSLionel Sambuc         if( sCsv.cTerm!=sCsv.cSeparator ) break;
2186*0a6a1f1dSLionel Sambuc       }
2187*0a6a1f1dSLionel Sambuc       if( cSep=='(' ){
2188*0a6a1f1dSLionel Sambuc         sqlite3_free(zCreate);
2189*0a6a1f1dSLionel Sambuc         sqlite3_free(sCsv.z);
2190*0a6a1f1dSLionel Sambuc         xCloser(sCsv.in);
2191*0a6a1f1dSLionel Sambuc         fprintf(stderr,"%s: empty file\n", sCsv.zFile);
2192*0a6a1f1dSLionel Sambuc         return 1;
2193*0a6a1f1dSLionel Sambuc       }
2194*0a6a1f1dSLionel Sambuc       zCreate = sqlite3_mprintf("%z\n)", zCreate);
2195*0a6a1f1dSLionel Sambuc       rc = sqlite3_exec(p->db, zCreate, 0, 0, 0);
2196*0a6a1f1dSLionel Sambuc       sqlite3_free(zCreate);
2197*0a6a1f1dSLionel Sambuc       if( rc ){
2198*0a6a1f1dSLionel Sambuc         fprintf(stderr, "CREATE TABLE %s(...) failed: %s\n", zTable,
2199*0a6a1f1dSLionel Sambuc                 sqlite3_errmsg(db));
2200*0a6a1f1dSLionel Sambuc         sqlite3_free(sCsv.z);
2201*0a6a1f1dSLionel Sambuc         xCloser(sCsv.in);
2202*0a6a1f1dSLionel Sambuc         return 1;
2203*0a6a1f1dSLionel Sambuc       }
2204*0a6a1f1dSLionel Sambuc       rc = sqlite3_prepare(p->db, zSql, -1, &pStmt, 0);
2205*0a6a1f1dSLionel Sambuc     }
220611be35a1SLionel Sambuc     sqlite3_free(zSql);
220711be35a1SLionel Sambuc     if( rc ){
220811be35a1SLionel Sambuc       if (pStmt) sqlite3_finalize(pStmt);
220911be35a1SLionel Sambuc       fprintf(stderr,"Error: %s\n", sqlite3_errmsg(db));
2210*0a6a1f1dSLionel Sambuc       xCloser(sCsv.in);
221111be35a1SLionel Sambuc       return 1;
221211be35a1SLionel Sambuc     }
221311be35a1SLionel Sambuc     nCol = sqlite3_column_count(pStmt);
221411be35a1SLionel Sambuc     sqlite3_finalize(pStmt);
221511be35a1SLionel Sambuc     pStmt = 0;
221611be35a1SLionel Sambuc     if( nCol==0 ) return 0; /* no columns, no error */
2217*0a6a1f1dSLionel Sambuc     zSql = sqlite3_malloc( nByte*2 + 20 + nCol*2 );
221811be35a1SLionel Sambuc     if( zSql==0 ){
221911be35a1SLionel Sambuc       fprintf(stderr, "Error: out of memory\n");
2220*0a6a1f1dSLionel Sambuc       xCloser(sCsv.in);
222111be35a1SLionel Sambuc       return 1;
222211be35a1SLionel Sambuc     }
2223*0a6a1f1dSLionel Sambuc     sqlite3_snprintf(nByte+20, zSql, "INSERT INTO \"%w\" VALUES(?", zTable);
222411be35a1SLionel Sambuc     j = strlen30(zSql);
222511be35a1SLionel Sambuc     for(i=1; i<nCol; i++){
222611be35a1SLionel Sambuc       zSql[j++] = ',';
222711be35a1SLionel Sambuc       zSql[j++] = '?';
222811be35a1SLionel Sambuc     }
222911be35a1SLionel Sambuc     zSql[j++] = ')';
223011be35a1SLionel Sambuc     zSql[j] = 0;
223111be35a1SLionel Sambuc     rc = sqlite3_prepare(p->db, zSql, -1, &pStmt, 0);
2232*0a6a1f1dSLionel Sambuc     sqlite3_free(zSql);
223311be35a1SLionel Sambuc     if( rc ){
223411be35a1SLionel Sambuc       fprintf(stderr, "Error: %s\n", sqlite3_errmsg(db));
223511be35a1SLionel Sambuc       if (pStmt) sqlite3_finalize(pStmt);
2236*0a6a1f1dSLionel Sambuc       xCloser(sCsv.in);
223711be35a1SLionel Sambuc       return 1;
223811be35a1SLionel Sambuc     }
2239*0a6a1f1dSLionel Sambuc     needCommit = sqlite3_get_autocommit(db);
2240*0a6a1f1dSLionel Sambuc     if( needCommit ) sqlite3_exec(db, "BEGIN", 0, 0, 0);
2241*0a6a1f1dSLionel Sambuc     do{
2242*0a6a1f1dSLionel Sambuc       int startLine = sCsv.nLine;
224311be35a1SLionel Sambuc       for(i=0; i<nCol; i++){
2244*0a6a1f1dSLionel Sambuc         char *z = csv_read_one_field(&sCsv);
2245*0a6a1f1dSLionel Sambuc         if( z==0 && i==0 ) break;
2246*0a6a1f1dSLionel Sambuc         sqlite3_bind_text(pStmt, i+1, z, -1, SQLITE_TRANSIENT);
2247*0a6a1f1dSLionel Sambuc         if( i<nCol-1 && sCsv.cTerm!=sCsv.cSeparator ){
2248*0a6a1f1dSLionel Sambuc           fprintf(stderr, "%s:%d: expected %d columns but found %d - "
2249*0a6a1f1dSLionel Sambuc                           "filling the rest with NULL\n",
2250*0a6a1f1dSLionel Sambuc                           sCsv.zFile, startLine, nCol, i+1);
2251*0a6a1f1dSLionel Sambuc           i++;
2252*0a6a1f1dSLionel Sambuc           while( i<nCol ){ sqlite3_bind_null(pStmt, i); i++; }
225311be35a1SLionel Sambuc         }
2254*0a6a1f1dSLionel Sambuc       }
2255*0a6a1f1dSLionel Sambuc       if( sCsv.cTerm==sCsv.cSeparator ){
2256*0a6a1f1dSLionel Sambuc         do{
2257*0a6a1f1dSLionel Sambuc           csv_read_one_field(&sCsv);
2258*0a6a1f1dSLionel Sambuc           i++;
2259*0a6a1f1dSLionel Sambuc         }while( sCsv.cTerm==sCsv.cSeparator );
2260*0a6a1f1dSLionel Sambuc         fprintf(stderr, "%s:%d: expected %d columns but found %d - "
2261*0a6a1f1dSLionel Sambuc                         "extras ignored\n",
2262*0a6a1f1dSLionel Sambuc                         sCsv.zFile, startLine, nCol, i);
2263*0a6a1f1dSLionel Sambuc       }
2264*0a6a1f1dSLionel Sambuc       if( i>=nCol ){
226511be35a1SLionel Sambuc         sqlite3_step(pStmt);
226611be35a1SLionel Sambuc         rc = sqlite3_reset(pStmt);
226711be35a1SLionel Sambuc         if( rc!=SQLITE_OK ){
2268*0a6a1f1dSLionel Sambuc           fprintf(stderr, "%s:%d: INSERT failed: %s\n", sCsv.zFile, startLine,
2269*0a6a1f1dSLionel Sambuc                   sqlite3_errmsg(db));
227011be35a1SLionel Sambuc         }
2271*0a6a1f1dSLionel Sambuc       }
2272*0a6a1f1dSLionel Sambuc     }while( sCsv.cTerm!=EOF );
2273*0a6a1f1dSLionel Sambuc 
2274*0a6a1f1dSLionel Sambuc     xCloser(sCsv.in);
2275*0a6a1f1dSLionel Sambuc     sqlite3_free(sCsv.z);
227611be35a1SLionel Sambuc     sqlite3_finalize(pStmt);
2277*0a6a1f1dSLionel Sambuc     if( needCommit ) sqlite3_exec(db, "COMMIT", 0, 0, 0);
227811be35a1SLionel Sambuc   }else
227911be35a1SLionel Sambuc 
228011be35a1SLionel Sambuc   if( c=='i' && strncmp(azArg[0], "indices", n)==0 && nArg<3 ){
228111be35a1SLionel Sambuc     struct callback_data data;
228211be35a1SLionel Sambuc     char *zErrMsg = 0;
2283*0a6a1f1dSLionel Sambuc     open_db(p, 0);
228411be35a1SLionel Sambuc     memcpy(&data, p, sizeof(data));
228511be35a1SLionel Sambuc     data.showHeader = 0;
228611be35a1SLionel Sambuc     data.mode = MODE_List;
228711be35a1SLionel Sambuc     if( nArg==1 ){
228811be35a1SLionel Sambuc       rc = sqlite3_exec(p->db,
228911be35a1SLionel Sambuc         "SELECT name FROM sqlite_master "
229011be35a1SLionel Sambuc         "WHERE type='index' AND name NOT LIKE 'sqlite_%' "
229111be35a1SLionel Sambuc         "UNION ALL "
229211be35a1SLionel Sambuc         "SELECT name FROM sqlite_temp_master "
229311be35a1SLionel Sambuc         "WHERE type='index' "
229411be35a1SLionel Sambuc         "ORDER BY 1",
229511be35a1SLionel Sambuc         callback, &data, &zErrMsg
229611be35a1SLionel Sambuc       );
229711be35a1SLionel Sambuc     }else{
229811be35a1SLionel Sambuc       zShellStatic = azArg[1];
229911be35a1SLionel Sambuc       rc = sqlite3_exec(p->db,
230011be35a1SLionel Sambuc         "SELECT name FROM sqlite_master "
230111be35a1SLionel Sambuc         "WHERE type='index' AND tbl_name LIKE shellstatic() "
230211be35a1SLionel Sambuc         "UNION ALL "
230311be35a1SLionel Sambuc         "SELECT name FROM sqlite_temp_master "
230411be35a1SLionel Sambuc         "WHERE type='index' AND tbl_name LIKE shellstatic() "
230511be35a1SLionel Sambuc         "ORDER BY 1",
230611be35a1SLionel Sambuc         callback, &data, &zErrMsg
230711be35a1SLionel Sambuc       );
230811be35a1SLionel Sambuc       zShellStatic = 0;
230911be35a1SLionel Sambuc     }
231011be35a1SLionel Sambuc     if( zErrMsg ){
231111be35a1SLionel Sambuc       fprintf(stderr,"Error: %s\n", zErrMsg);
231211be35a1SLionel Sambuc       sqlite3_free(zErrMsg);
231311be35a1SLionel Sambuc       rc = 1;
231411be35a1SLionel Sambuc     }else if( rc != SQLITE_OK ){
231511be35a1SLionel Sambuc       fprintf(stderr,"Error: querying sqlite_master and sqlite_temp_master\n");
231611be35a1SLionel Sambuc       rc = 1;
231711be35a1SLionel Sambuc     }
231811be35a1SLionel Sambuc   }else
231911be35a1SLionel Sambuc 
232011be35a1SLionel Sambuc #ifdef SQLITE_ENABLE_IOTRACE
232111be35a1SLionel Sambuc   if( c=='i' && strncmp(azArg[0], "iotrace", n)==0 ){
232211be35a1SLionel Sambuc     extern void (*sqlite3IoTrace)(const char*, ...);
232311be35a1SLionel Sambuc     if( iotrace && iotrace!=stdout ) fclose(iotrace);
232411be35a1SLionel Sambuc     iotrace = 0;
232511be35a1SLionel Sambuc     if( nArg<2 ){
232611be35a1SLionel Sambuc       sqlite3IoTrace = 0;
232711be35a1SLionel Sambuc     }else if( strcmp(azArg[1], "-")==0 ){
232811be35a1SLionel Sambuc       sqlite3IoTrace = iotracePrintf;
232911be35a1SLionel Sambuc       iotrace = stdout;
233011be35a1SLionel Sambuc     }else{
233111be35a1SLionel Sambuc       iotrace = fopen(azArg[1], "w");
233211be35a1SLionel Sambuc       if( iotrace==0 ){
233311be35a1SLionel Sambuc         fprintf(stderr, "Error: cannot open \"%s\"\n", azArg[1]);
233411be35a1SLionel Sambuc         sqlite3IoTrace = 0;
233511be35a1SLionel Sambuc         rc = 1;
233611be35a1SLionel Sambuc       }else{
233711be35a1SLionel Sambuc         sqlite3IoTrace = iotracePrintf;
233811be35a1SLionel Sambuc       }
233911be35a1SLionel Sambuc     }
234011be35a1SLionel Sambuc   }else
234111be35a1SLionel Sambuc #endif
234211be35a1SLionel Sambuc 
234311be35a1SLionel Sambuc #ifndef SQLITE_OMIT_LOAD_EXTENSION
234411be35a1SLionel Sambuc   if( c=='l' && strncmp(azArg[0], "load", n)==0 && nArg>=2 ){
234511be35a1SLionel Sambuc     const char *zFile, *zProc;
234611be35a1SLionel Sambuc     char *zErrMsg = 0;
234711be35a1SLionel Sambuc     zFile = azArg[1];
234811be35a1SLionel Sambuc     zProc = nArg>=3 ? azArg[2] : 0;
2349*0a6a1f1dSLionel Sambuc     open_db(p, 0);
235011be35a1SLionel Sambuc     rc = sqlite3_load_extension(p->db, zFile, zProc, &zErrMsg);
235111be35a1SLionel Sambuc     if( rc!=SQLITE_OK ){
235211be35a1SLionel Sambuc       fprintf(stderr, "Error: %s\n", zErrMsg);
235311be35a1SLionel Sambuc       sqlite3_free(zErrMsg);
235411be35a1SLionel Sambuc       rc = 1;
235511be35a1SLionel Sambuc     }
235611be35a1SLionel Sambuc   }else
235711be35a1SLionel Sambuc #endif
235811be35a1SLionel Sambuc 
235911be35a1SLionel Sambuc   if( c=='l' && strncmp(azArg[0], "log", n)==0 && nArg>=2 ){
236011be35a1SLionel Sambuc     const char *zFile = azArg[1];
2361*0a6a1f1dSLionel Sambuc     output_file_close(p->pLog);
2362*0a6a1f1dSLionel Sambuc     p->pLog = output_file_open(zFile);
236311be35a1SLionel Sambuc   }else
236411be35a1SLionel Sambuc 
236511be35a1SLionel Sambuc   if( c=='m' && strncmp(azArg[0], "mode", n)==0 && nArg==2 ){
236611be35a1SLionel Sambuc     int n2 = strlen30(azArg[1]);
236711be35a1SLionel Sambuc     if( (n2==4 && strncmp(azArg[1],"line",n2)==0)
236811be35a1SLionel Sambuc         ||
236911be35a1SLionel Sambuc         (n2==5 && strncmp(azArg[1],"lines",n2)==0) ){
237011be35a1SLionel Sambuc       p->mode = MODE_Line;
237111be35a1SLionel Sambuc     }else if( (n2==6 && strncmp(azArg[1],"column",n2)==0)
237211be35a1SLionel Sambuc               ||
237311be35a1SLionel Sambuc               (n2==7 && strncmp(azArg[1],"columns",n2)==0) ){
237411be35a1SLionel Sambuc       p->mode = MODE_Column;
237511be35a1SLionel Sambuc     }else if( n2==4 && strncmp(azArg[1],"list",n2)==0 ){
237611be35a1SLionel Sambuc       p->mode = MODE_List;
237711be35a1SLionel Sambuc     }else if( n2==4 && strncmp(azArg[1],"html",n2)==0 ){
237811be35a1SLionel Sambuc       p->mode = MODE_Html;
237911be35a1SLionel Sambuc     }else if( n2==3 && strncmp(azArg[1],"tcl",n2)==0 ){
238011be35a1SLionel Sambuc       p->mode = MODE_Tcl;
2381*0a6a1f1dSLionel Sambuc       sqlite3_snprintf(sizeof(p->separator), p->separator, " ");
238211be35a1SLionel Sambuc     }else if( n2==3 && strncmp(azArg[1],"csv",n2)==0 ){
238311be35a1SLionel Sambuc       p->mode = MODE_Csv;
238411be35a1SLionel Sambuc       sqlite3_snprintf(sizeof(p->separator), p->separator, ",");
238511be35a1SLionel Sambuc     }else if( n2==4 && strncmp(azArg[1],"tabs",n2)==0 ){
238611be35a1SLionel Sambuc       p->mode = MODE_List;
238711be35a1SLionel Sambuc       sqlite3_snprintf(sizeof(p->separator), p->separator, "\t");
238811be35a1SLionel Sambuc     }else if( n2==6 && strncmp(azArg[1],"insert",n2)==0 ){
238911be35a1SLionel Sambuc       p->mode = MODE_Insert;
239011be35a1SLionel Sambuc       set_table_name(p, "table");
239111be35a1SLionel Sambuc     }else {
239211be35a1SLionel Sambuc       fprintf(stderr,"Error: mode should be one of: "
239311be35a1SLionel Sambuc          "column csv html insert line list tabs tcl\n");
239411be35a1SLionel Sambuc       rc = 1;
239511be35a1SLionel Sambuc     }
239611be35a1SLionel Sambuc   }else
239711be35a1SLionel Sambuc 
239811be35a1SLionel Sambuc   if( c=='m' && strncmp(azArg[0], "mode", n)==0 && nArg==3 ){
239911be35a1SLionel Sambuc     int n2 = strlen30(azArg[1]);
240011be35a1SLionel Sambuc     if( n2==6 && strncmp(azArg[1],"insert",n2)==0 ){
240111be35a1SLionel Sambuc       p->mode = MODE_Insert;
240211be35a1SLionel Sambuc       set_table_name(p, azArg[2]);
240311be35a1SLionel Sambuc     }else {
240411be35a1SLionel Sambuc       fprintf(stderr, "Error: invalid arguments: "
240511be35a1SLionel Sambuc         " \"%s\". Enter \".help\" for help\n", azArg[2]);
240611be35a1SLionel Sambuc       rc = 1;
240711be35a1SLionel Sambuc     }
240811be35a1SLionel Sambuc   }else
240911be35a1SLionel Sambuc 
241011be35a1SLionel Sambuc   if( c=='n' && strncmp(azArg[0], "nullvalue", n)==0 && nArg==2 ) {
241111be35a1SLionel Sambuc     sqlite3_snprintf(sizeof(p->nullvalue), p->nullvalue,
241211be35a1SLionel Sambuc                      "%.*s", (int)ArraySize(p->nullvalue)-1, azArg[1]);
241311be35a1SLionel Sambuc   }else
241411be35a1SLionel Sambuc 
2415*0a6a1f1dSLionel Sambuc   if( c=='o' && strncmp(azArg[0], "open", n)==0 && n>=2 ){
2416*0a6a1f1dSLionel Sambuc     sqlite3 *savedDb = p->db;
2417*0a6a1f1dSLionel Sambuc     const char *zSavedFilename = p->zDbFilename;
2418*0a6a1f1dSLionel Sambuc     char *zNewFilename = 0;
2419*0a6a1f1dSLionel Sambuc     p->db = 0;
2420*0a6a1f1dSLionel Sambuc     if( nArg>=2 ){
2421*0a6a1f1dSLionel Sambuc       p->zDbFilename = zNewFilename = sqlite3_mprintf("%s", azArg[1]);
242211be35a1SLionel Sambuc     }
2423*0a6a1f1dSLionel Sambuc     open_db(p, 1);
2424*0a6a1f1dSLionel Sambuc     if( p->db!=0 ){
2425*0a6a1f1dSLionel Sambuc       sqlite3_close(savedDb);
2426*0a6a1f1dSLionel Sambuc       sqlite3_free(p->zFreeOnClose);
2427*0a6a1f1dSLionel Sambuc       p->zFreeOnClose = zNewFilename;
242811be35a1SLionel Sambuc     }else{
2429*0a6a1f1dSLionel Sambuc       sqlite3_free(zNewFilename);
2430*0a6a1f1dSLionel Sambuc       p->db = savedDb;
2431*0a6a1f1dSLionel Sambuc       p->zDbFilename = zSavedFilename;
2432*0a6a1f1dSLionel Sambuc     }
2433*0a6a1f1dSLionel Sambuc   }else
2434*0a6a1f1dSLionel Sambuc 
2435*0a6a1f1dSLionel Sambuc   if( c=='o' && strncmp(azArg[0], "output", n)==0 && nArg==2 ){
2436*0a6a1f1dSLionel Sambuc     if( p->outfile[0]=='|' ){
2437*0a6a1f1dSLionel Sambuc       pclose(p->out);
2438*0a6a1f1dSLionel Sambuc     }else{
2439*0a6a1f1dSLionel Sambuc       output_file_close(p->out);
2440*0a6a1f1dSLionel Sambuc     }
2441*0a6a1f1dSLionel Sambuc     p->outfile[0] = 0;
2442*0a6a1f1dSLionel Sambuc     if( azArg[1][0]=='|' ){
2443*0a6a1f1dSLionel Sambuc       p->out = popen(&azArg[1][1], "w");
244411be35a1SLionel Sambuc       if( p->out==0 ){
2445*0a6a1f1dSLionel Sambuc         fprintf(stderr,"Error: cannot open pipe \"%s\"\n", &azArg[1][1]);
2446*0a6a1f1dSLionel Sambuc         p->out = stdout;
2447*0a6a1f1dSLionel Sambuc         rc = 1;
2448*0a6a1f1dSLionel Sambuc       }else{
2449*0a6a1f1dSLionel Sambuc         sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", azArg[1]);
2450*0a6a1f1dSLionel Sambuc       }
2451*0a6a1f1dSLionel Sambuc     }else{
2452*0a6a1f1dSLionel Sambuc       p->out = output_file_open(azArg[1]);
2453*0a6a1f1dSLionel Sambuc       if( p->out==0 ){
2454*0a6a1f1dSLionel Sambuc         if( strcmp(azArg[1],"off")!=0 ){
245511be35a1SLionel Sambuc           fprintf(stderr,"Error: cannot write to \"%s\"\n", azArg[1]);
2456*0a6a1f1dSLionel Sambuc         }
245711be35a1SLionel Sambuc         p->out = stdout;
245811be35a1SLionel Sambuc         rc = 1;
245911be35a1SLionel Sambuc       } else {
246011be35a1SLionel Sambuc         sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", azArg[1]);
246111be35a1SLionel Sambuc       }
246211be35a1SLionel Sambuc     }
246311be35a1SLionel Sambuc   }else
246411be35a1SLionel Sambuc 
2465*0a6a1f1dSLionel Sambuc   if( c=='p' && n>=3 && strncmp(azArg[0], "print", n)==0 ){
2466*0a6a1f1dSLionel Sambuc     int i;
2467*0a6a1f1dSLionel Sambuc     for(i=1; i<nArg; i++){
2468*0a6a1f1dSLionel Sambuc       if( i>1 ) fprintf(p->out, " ");
2469*0a6a1f1dSLionel Sambuc       fprintf(p->out, "%s", azArg[i]);
2470*0a6a1f1dSLionel Sambuc     }
2471*0a6a1f1dSLionel Sambuc     fprintf(p->out, "\n");
2472*0a6a1f1dSLionel Sambuc   }else
2473*0a6a1f1dSLionel Sambuc 
247411be35a1SLionel Sambuc   if( c=='p' && strncmp(azArg[0], "prompt", n)==0 && (nArg==2 || nArg==3)){
247511be35a1SLionel Sambuc     if( nArg >= 2) {
247611be35a1SLionel Sambuc       strncpy(mainPrompt,azArg[1],(int)ArraySize(mainPrompt)-1);
247711be35a1SLionel Sambuc     }
247811be35a1SLionel Sambuc     if( nArg >= 3) {
247911be35a1SLionel Sambuc       strncpy(continuePrompt,azArg[2],(int)ArraySize(continuePrompt)-1);
248011be35a1SLionel Sambuc     }
248111be35a1SLionel Sambuc   }else
248211be35a1SLionel Sambuc 
248311be35a1SLionel Sambuc   if( c=='q' && strncmp(azArg[0], "quit", n)==0 && nArg==1 ){
248411be35a1SLionel Sambuc     rc = 2;
248511be35a1SLionel Sambuc   }else
248611be35a1SLionel Sambuc 
248711be35a1SLionel Sambuc   if( c=='r' && n>=3 && strncmp(azArg[0], "read", n)==0 && nArg==2 ){
248811be35a1SLionel Sambuc     FILE *alt = fopen(azArg[1], "rb");
248911be35a1SLionel Sambuc     if( alt==0 ){
249011be35a1SLionel Sambuc       fprintf(stderr,"Error: cannot open \"%s\"\n", azArg[1]);
249111be35a1SLionel Sambuc       rc = 1;
249211be35a1SLionel Sambuc     }else{
249311be35a1SLionel Sambuc       rc = process_input(p, alt);
249411be35a1SLionel Sambuc       fclose(alt);
249511be35a1SLionel Sambuc     }
249611be35a1SLionel Sambuc   }else
249711be35a1SLionel Sambuc 
249811be35a1SLionel Sambuc   if( c=='r' && n>=3 && strncmp(azArg[0], "restore", n)==0 && nArg>1 && nArg<4){
249911be35a1SLionel Sambuc     const char *zSrcFile;
250011be35a1SLionel Sambuc     const char *zDb;
250111be35a1SLionel Sambuc     sqlite3 *pSrc;
250211be35a1SLionel Sambuc     sqlite3_backup *pBackup;
250311be35a1SLionel Sambuc     int nTimeout = 0;
250411be35a1SLionel Sambuc 
250511be35a1SLionel Sambuc     if( nArg==2 ){
250611be35a1SLionel Sambuc       zSrcFile = azArg[1];
250711be35a1SLionel Sambuc       zDb = "main";
250811be35a1SLionel Sambuc     }else{
250911be35a1SLionel Sambuc       zSrcFile = azArg[2];
251011be35a1SLionel Sambuc       zDb = azArg[1];
251111be35a1SLionel Sambuc     }
251211be35a1SLionel Sambuc     rc = sqlite3_open(zSrcFile, &pSrc);
251311be35a1SLionel Sambuc     if( rc!=SQLITE_OK ){
251411be35a1SLionel Sambuc       fprintf(stderr, "Error: cannot open \"%s\"\n", zSrcFile);
251511be35a1SLionel Sambuc       sqlite3_close(pSrc);
251611be35a1SLionel Sambuc       return 1;
251711be35a1SLionel Sambuc     }
2518*0a6a1f1dSLionel Sambuc     open_db(p, 0);
251911be35a1SLionel Sambuc     pBackup = sqlite3_backup_init(p->db, zDb, pSrc, "main");
252011be35a1SLionel Sambuc     if( pBackup==0 ){
252111be35a1SLionel Sambuc       fprintf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
252211be35a1SLionel Sambuc       sqlite3_close(pSrc);
252311be35a1SLionel Sambuc       return 1;
252411be35a1SLionel Sambuc     }
252511be35a1SLionel Sambuc     while( (rc = sqlite3_backup_step(pBackup,100))==SQLITE_OK
252611be35a1SLionel Sambuc           || rc==SQLITE_BUSY  ){
252711be35a1SLionel Sambuc       if( rc==SQLITE_BUSY ){
252811be35a1SLionel Sambuc         if( nTimeout++ >= 3 ) break;
252911be35a1SLionel Sambuc         sqlite3_sleep(100);
253011be35a1SLionel Sambuc       }
253111be35a1SLionel Sambuc     }
253211be35a1SLionel Sambuc     sqlite3_backup_finish(pBackup);
253311be35a1SLionel Sambuc     if( rc==SQLITE_DONE ){
253411be35a1SLionel Sambuc       rc = 0;
253511be35a1SLionel Sambuc     }else if( rc==SQLITE_BUSY || rc==SQLITE_LOCKED ){
253611be35a1SLionel Sambuc       fprintf(stderr, "Error: source database is busy\n");
253711be35a1SLionel Sambuc       rc = 1;
253811be35a1SLionel Sambuc     }else{
253911be35a1SLionel Sambuc       fprintf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
254011be35a1SLionel Sambuc       rc = 1;
254111be35a1SLionel Sambuc     }
254211be35a1SLionel Sambuc     sqlite3_close(pSrc);
254311be35a1SLionel Sambuc   }else
254411be35a1SLionel Sambuc 
254511be35a1SLionel Sambuc   if( c=='s' && strncmp(azArg[0], "schema", n)==0 && nArg<3 ){
254611be35a1SLionel Sambuc     struct callback_data data;
254711be35a1SLionel Sambuc     char *zErrMsg = 0;
2548*0a6a1f1dSLionel Sambuc     open_db(p, 0);
254911be35a1SLionel Sambuc     memcpy(&data, p, sizeof(data));
255011be35a1SLionel Sambuc     data.showHeader = 0;
255111be35a1SLionel Sambuc     data.mode = MODE_Semi;
255211be35a1SLionel Sambuc     if( nArg>1 ){
255311be35a1SLionel Sambuc       int i;
255411be35a1SLionel Sambuc       for(i=0; azArg[1][i]; i++) azArg[1][i] = ToLower(azArg[1][i]);
255511be35a1SLionel Sambuc       if( strcmp(azArg[1],"sqlite_master")==0 ){
255611be35a1SLionel Sambuc         char *new_argv[2], *new_colv[2];
255711be35a1SLionel Sambuc         new_argv[0] = "CREATE TABLE sqlite_master (\n"
255811be35a1SLionel Sambuc                       "  type text,\n"
255911be35a1SLionel Sambuc                       "  name text,\n"
256011be35a1SLionel Sambuc                       "  tbl_name text,\n"
256111be35a1SLionel Sambuc                       "  rootpage integer,\n"
256211be35a1SLionel Sambuc                       "  sql text\n"
256311be35a1SLionel Sambuc                       ")";
256411be35a1SLionel Sambuc         new_argv[1] = 0;
256511be35a1SLionel Sambuc         new_colv[0] = "sql";
256611be35a1SLionel Sambuc         new_colv[1] = 0;
256711be35a1SLionel Sambuc         callback(&data, 1, new_argv, new_colv);
256811be35a1SLionel Sambuc         rc = SQLITE_OK;
256911be35a1SLionel Sambuc       }else if( strcmp(azArg[1],"sqlite_temp_master")==0 ){
257011be35a1SLionel Sambuc         char *new_argv[2], *new_colv[2];
257111be35a1SLionel Sambuc         new_argv[0] = "CREATE TEMP TABLE sqlite_temp_master (\n"
257211be35a1SLionel Sambuc                       "  type text,\n"
257311be35a1SLionel Sambuc                       "  name text,\n"
257411be35a1SLionel Sambuc                       "  tbl_name text,\n"
257511be35a1SLionel Sambuc                       "  rootpage integer,\n"
257611be35a1SLionel Sambuc                       "  sql text\n"
257711be35a1SLionel Sambuc                       ")";
257811be35a1SLionel Sambuc         new_argv[1] = 0;
257911be35a1SLionel Sambuc         new_colv[0] = "sql";
258011be35a1SLionel Sambuc         new_colv[1] = 0;
258111be35a1SLionel Sambuc         callback(&data, 1, new_argv, new_colv);
258211be35a1SLionel Sambuc         rc = SQLITE_OK;
258311be35a1SLionel Sambuc       }else{
258411be35a1SLionel Sambuc         zShellStatic = azArg[1];
258511be35a1SLionel Sambuc         rc = sqlite3_exec(p->db,
258611be35a1SLionel Sambuc           "SELECT sql FROM "
2587*0a6a1f1dSLionel Sambuc           "  (SELECT sql sql, type type, tbl_name tbl_name, name name, rowid x"
258811be35a1SLionel Sambuc           "     FROM sqlite_master UNION ALL"
2589*0a6a1f1dSLionel Sambuc           "   SELECT sql, type, tbl_name, name, rowid FROM sqlite_temp_master) "
259011be35a1SLionel Sambuc           "WHERE lower(tbl_name) LIKE shellstatic()"
259111be35a1SLionel Sambuc           "  AND type!='meta' AND sql NOTNULL "
2592*0a6a1f1dSLionel Sambuc           "ORDER BY rowid",
259311be35a1SLionel Sambuc           callback, &data, &zErrMsg);
259411be35a1SLionel Sambuc         zShellStatic = 0;
259511be35a1SLionel Sambuc       }
259611be35a1SLionel Sambuc     }else{
259711be35a1SLionel Sambuc       rc = sqlite3_exec(p->db,
259811be35a1SLionel Sambuc          "SELECT sql FROM "
2599*0a6a1f1dSLionel Sambuc          "  (SELECT sql sql, type type, tbl_name tbl_name, name name, rowid x"
260011be35a1SLionel Sambuc          "     FROM sqlite_master UNION ALL"
2601*0a6a1f1dSLionel Sambuc          "   SELECT sql, type, tbl_name, name, rowid FROM sqlite_temp_master) "
260211be35a1SLionel Sambuc          "WHERE type!='meta' AND sql NOTNULL AND name NOT LIKE 'sqlite_%'"
2603*0a6a1f1dSLionel Sambuc          "ORDER BY rowid",
260411be35a1SLionel Sambuc          callback, &data, &zErrMsg
260511be35a1SLionel Sambuc       );
260611be35a1SLionel Sambuc     }
260711be35a1SLionel Sambuc     if( zErrMsg ){
260811be35a1SLionel Sambuc       fprintf(stderr,"Error: %s\n", zErrMsg);
260911be35a1SLionel Sambuc       sqlite3_free(zErrMsg);
261011be35a1SLionel Sambuc       rc = 1;
261111be35a1SLionel Sambuc     }else if( rc != SQLITE_OK ){
261211be35a1SLionel Sambuc       fprintf(stderr,"Error: querying schema information\n");
261311be35a1SLionel Sambuc       rc = 1;
261411be35a1SLionel Sambuc     }else{
261511be35a1SLionel Sambuc       rc = 0;
261611be35a1SLionel Sambuc     }
261711be35a1SLionel Sambuc   }else
261811be35a1SLionel Sambuc 
2619*0a6a1f1dSLionel Sambuc #ifdef SQLITE_DEBUG
2620*0a6a1f1dSLionel Sambuc   /* Undocumented commands for internal testing.  Subject to change
2621*0a6a1f1dSLionel Sambuc   ** without notice. */
2622*0a6a1f1dSLionel Sambuc   if( c=='s' && n>=10 && strncmp(azArg[0], "selftest-", 9)==0 ){
2623*0a6a1f1dSLionel Sambuc     if( strncmp(azArg[0]+9, "boolean", n-9)==0 ){
2624*0a6a1f1dSLionel Sambuc       int i, v;
2625*0a6a1f1dSLionel Sambuc       for(i=1; i<nArg; i++){
2626*0a6a1f1dSLionel Sambuc         v = booleanValue(azArg[i]);
2627*0a6a1f1dSLionel Sambuc         fprintf(p->out, "%s: %d 0x%x\n", azArg[i], v, v);
2628*0a6a1f1dSLionel Sambuc       }
2629*0a6a1f1dSLionel Sambuc     }
2630*0a6a1f1dSLionel Sambuc     if( strncmp(azArg[0]+9, "integer", n-9)==0 ){
2631*0a6a1f1dSLionel Sambuc       int i; sqlite3_int64 v;
2632*0a6a1f1dSLionel Sambuc       for(i=1; i<nArg; i++){
2633*0a6a1f1dSLionel Sambuc         char zBuf[200];
2634*0a6a1f1dSLionel Sambuc         v = integerValue(azArg[i]);
2635*0a6a1f1dSLionel Sambuc         sqlite3_snprintf(sizeof(zBuf), zBuf, "%s: %lld 0x%llx\n", azArg[i], v, v);
2636*0a6a1f1dSLionel Sambuc         fprintf(p->out, "%s", zBuf);
2637*0a6a1f1dSLionel Sambuc       }
2638*0a6a1f1dSLionel Sambuc     }
2639*0a6a1f1dSLionel Sambuc   }else
2640*0a6a1f1dSLionel Sambuc #endif
2641*0a6a1f1dSLionel Sambuc 
264211be35a1SLionel Sambuc   if( c=='s' && strncmp(azArg[0], "separator", n)==0 && nArg==2 ){
264311be35a1SLionel Sambuc     sqlite3_snprintf(sizeof(p->separator), p->separator,
264411be35a1SLionel Sambuc                      "%.*s", (int)sizeof(p->separator)-1, azArg[1]);
264511be35a1SLionel Sambuc   }else
264611be35a1SLionel Sambuc 
264711be35a1SLionel Sambuc   if( c=='s' && strncmp(azArg[0], "show", n)==0 && nArg==1 ){
264811be35a1SLionel Sambuc     int i;
264911be35a1SLionel Sambuc     fprintf(p->out,"%9.9s: %s\n","echo", p->echoOn ? "on" : "off");
265011be35a1SLionel Sambuc     fprintf(p->out,"%9.9s: %s\n","explain", p->explainPrev.valid ? "on" :"off");
265111be35a1SLionel Sambuc     fprintf(p->out,"%9.9s: %s\n","headers", p->showHeader ? "on" : "off");
265211be35a1SLionel Sambuc     fprintf(p->out,"%9.9s: %s\n","mode", modeDescr[p->mode]);
265311be35a1SLionel Sambuc     fprintf(p->out,"%9.9s: ", "nullvalue");
265411be35a1SLionel Sambuc       output_c_string(p->out, p->nullvalue);
265511be35a1SLionel Sambuc       fprintf(p->out, "\n");
265611be35a1SLionel Sambuc     fprintf(p->out,"%9.9s: %s\n","output",
265711be35a1SLionel Sambuc             strlen30(p->outfile) ? p->outfile : "stdout");
265811be35a1SLionel Sambuc     fprintf(p->out,"%9.9s: ", "separator");
265911be35a1SLionel Sambuc       output_c_string(p->out, p->separator);
266011be35a1SLionel Sambuc       fprintf(p->out, "\n");
266111be35a1SLionel Sambuc     fprintf(p->out,"%9.9s: %s\n","stats", p->statsOn ? "on" : "off");
266211be35a1SLionel Sambuc     fprintf(p->out,"%9.9s: ","width");
266311be35a1SLionel Sambuc     for (i=0;i<(int)ArraySize(p->colWidth) && p->colWidth[i] != 0;i++) {
266411be35a1SLionel Sambuc       fprintf(p->out,"%d ",p->colWidth[i]);
266511be35a1SLionel Sambuc     }
266611be35a1SLionel Sambuc     fprintf(p->out,"\n");
266711be35a1SLionel Sambuc   }else
266811be35a1SLionel Sambuc 
266911be35a1SLionel Sambuc   if( c=='s' && strncmp(azArg[0], "stats", n)==0 && nArg>1 && nArg<3 ){
267011be35a1SLionel Sambuc     p->statsOn = booleanValue(azArg[1]);
267111be35a1SLionel Sambuc   }else
267211be35a1SLionel Sambuc 
267311be35a1SLionel Sambuc   if( c=='t' && n>1 && strncmp(azArg[0], "tables", n)==0 && nArg<3 ){
2674*0a6a1f1dSLionel Sambuc     sqlite3_stmt *pStmt;
267511be35a1SLionel Sambuc     char **azResult;
2676*0a6a1f1dSLionel Sambuc     int nRow, nAlloc;
2677*0a6a1f1dSLionel Sambuc     char *zSql = 0;
2678*0a6a1f1dSLionel Sambuc     int ii;
2679*0a6a1f1dSLionel Sambuc     open_db(p, 0);
2680*0a6a1f1dSLionel Sambuc     rc = sqlite3_prepare_v2(p->db, "PRAGMA database_list", -1, &pStmt, 0);
2681*0a6a1f1dSLionel Sambuc     if( rc ) return rc;
2682*0a6a1f1dSLionel Sambuc     zSql = sqlite3_mprintf(
268311be35a1SLionel Sambuc         "SELECT name FROM sqlite_master"
268411be35a1SLionel Sambuc         " WHERE type IN ('table','view')"
2685*0a6a1f1dSLionel Sambuc         "   AND name NOT LIKE 'sqlite_%%'"
2686*0a6a1f1dSLionel Sambuc         "   AND name LIKE ?1");
2687*0a6a1f1dSLionel Sambuc     while( sqlite3_step(pStmt)==SQLITE_ROW ){
2688*0a6a1f1dSLionel Sambuc       const char *zDbName = (const char*)sqlite3_column_text(pStmt, 1);
2689*0a6a1f1dSLionel Sambuc       if( zDbName==0 || strcmp(zDbName,"main")==0 ) continue;
2690*0a6a1f1dSLionel Sambuc       if( strcmp(zDbName,"temp")==0 ){
2691*0a6a1f1dSLionel Sambuc         zSql = sqlite3_mprintf(
2692*0a6a1f1dSLionel Sambuc                  "%z UNION ALL "
2693*0a6a1f1dSLionel Sambuc                  "SELECT 'temp.' || name FROM sqlite_temp_master"
2694*0a6a1f1dSLionel Sambuc                  " WHERE type IN ('table','view')"
2695*0a6a1f1dSLionel Sambuc                  "   AND name NOT LIKE 'sqlite_%%'"
2696*0a6a1f1dSLionel Sambuc                  "   AND name LIKE ?1", zSql);
269711be35a1SLionel Sambuc       }else{
2698*0a6a1f1dSLionel Sambuc         zSql = sqlite3_mprintf(
2699*0a6a1f1dSLionel Sambuc                  "%z UNION ALL "
2700*0a6a1f1dSLionel Sambuc                  "SELECT '%q.' || name FROM \"%w\".sqlite_master"
2701*0a6a1f1dSLionel Sambuc                  " WHERE type IN ('table','view')"
2702*0a6a1f1dSLionel Sambuc                  "   AND name NOT LIKE 'sqlite_%%'"
2703*0a6a1f1dSLionel Sambuc                  "   AND name LIKE ?1", zSql, zDbName, zDbName);
270411be35a1SLionel Sambuc       }
2705*0a6a1f1dSLionel Sambuc     }
2706*0a6a1f1dSLionel Sambuc     sqlite3_finalize(pStmt);
2707*0a6a1f1dSLionel Sambuc     zSql = sqlite3_mprintf("%z ORDER BY 1", zSql);
2708*0a6a1f1dSLionel Sambuc     rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
2709*0a6a1f1dSLionel Sambuc     sqlite3_free(zSql);
2710*0a6a1f1dSLionel Sambuc     if( rc ) return rc;
2711*0a6a1f1dSLionel Sambuc     nRow = nAlloc = 0;
2712*0a6a1f1dSLionel Sambuc     azResult = 0;
2713*0a6a1f1dSLionel Sambuc     if( nArg>1 ){
2714*0a6a1f1dSLionel Sambuc       sqlite3_bind_text(pStmt, 1, azArg[1], -1, SQLITE_TRANSIENT);
271511be35a1SLionel Sambuc     }else{
2716*0a6a1f1dSLionel Sambuc       sqlite3_bind_text(pStmt, 1, "%", -1, SQLITE_STATIC);
2717*0a6a1f1dSLionel Sambuc     }
2718*0a6a1f1dSLionel Sambuc     while( sqlite3_step(pStmt)==SQLITE_ROW ){
2719*0a6a1f1dSLionel Sambuc       if( nRow>=nAlloc ){
2720*0a6a1f1dSLionel Sambuc         char **azNew;
2721*0a6a1f1dSLionel Sambuc         int n = nAlloc*2 + 10;
2722*0a6a1f1dSLionel Sambuc         azNew = sqlite3_realloc(azResult, sizeof(azResult[0])*n);
2723*0a6a1f1dSLionel Sambuc         if( azNew==0 ){
2724*0a6a1f1dSLionel Sambuc           fprintf(stderr, "Error: out of memory\n");
2725*0a6a1f1dSLionel Sambuc           break;
2726*0a6a1f1dSLionel Sambuc         }
2727*0a6a1f1dSLionel Sambuc         nAlloc = n;
2728*0a6a1f1dSLionel Sambuc         azResult = azNew;
2729*0a6a1f1dSLionel Sambuc       }
2730*0a6a1f1dSLionel Sambuc       azResult[nRow] = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 0));
2731*0a6a1f1dSLionel Sambuc       if( azResult[nRow] ) nRow++;
2732*0a6a1f1dSLionel Sambuc     }
2733*0a6a1f1dSLionel Sambuc     sqlite3_finalize(pStmt);
2734*0a6a1f1dSLionel Sambuc     if( nRow>0 ){
273511be35a1SLionel Sambuc       int len, maxlen = 0;
273611be35a1SLionel Sambuc       int i, j;
273711be35a1SLionel Sambuc       int nPrintCol, nPrintRow;
2738*0a6a1f1dSLionel Sambuc       for(i=0; i<nRow; i++){
273911be35a1SLionel Sambuc         len = strlen30(azResult[i]);
274011be35a1SLionel Sambuc         if( len>maxlen ) maxlen = len;
274111be35a1SLionel Sambuc       }
274211be35a1SLionel Sambuc       nPrintCol = 80/(maxlen+2);
274311be35a1SLionel Sambuc       if( nPrintCol<1 ) nPrintCol = 1;
274411be35a1SLionel Sambuc       nPrintRow = (nRow + nPrintCol - 1)/nPrintCol;
274511be35a1SLionel Sambuc       for(i=0; i<nPrintRow; i++){
2746*0a6a1f1dSLionel Sambuc         for(j=i; j<nRow; j+=nPrintRow){
2747*0a6a1f1dSLionel Sambuc           char *zSp = j<nPrintRow ? "" : "  ";
2748*0a6a1f1dSLionel Sambuc           fprintf(p->out, "%s%-*s", zSp, maxlen, azResult[j] ? azResult[j] : "");
274911be35a1SLionel Sambuc         }
2750*0a6a1f1dSLionel Sambuc         fprintf(p->out, "\n");
275111be35a1SLionel Sambuc       }
275211be35a1SLionel Sambuc     }
2753*0a6a1f1dSLionel Sambuc     for(ii=0; ii<nRow; ii++) sqlite3_free(azResult[ii]);
2754*0a6a1f1dSLionel Sambuc     sqlite3_free(azResult);
275511be35a1SLionel Sambuc   }else
275611be35a1SLionel Sambuc 
275711be35a1SLionel Sambuc   if( c=='t' && n>=8 && strncmp(azArg[0], "testctrl", n)==0 && nArg>=2 ){
275811be35a1SLionel Sambuc     static const struct {
275911be35a1SLionel Sambuc        const char *zCtrlName;   /* Name of a test-control option */
276011be35a1SLionel Sambuc        int ctrlCode;            /* Integer code for that option */
276111be35a1SLionel Sambuc     } aCtrl[] = {
276211be35a1SLionel Sambuc       { "prng_save",             SQLITE_TESTCTRL_PRNG_SAVE              },
276311be35a1SLionel Sambuc       { "prng_restore",          SQLITE_TESTCTRL_PRNG_RESTORE           },
276411be35a1SLionel Sambuc       { "prng_reset",            SQLITE_TESTCTRL_PRNG_RESET             },
276511be35a1SLionel Sambuc       { "bitvec_test",           SQLITE_TESTCTRL_BITVEC_TEST            },
276611be35a1SLionel Sambuc       { "fault_install",         SQLITE_TESTCTRL_FAULT_INSTALL          },
276711be35a1SLionel Sambuc       { "benign_malloc_hooks",   SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS    },
276811be35a1SLionel Sambuc       { "pending_byte",          SQLITE_TESTCTRL_PENDING_BYTE           },
276911be35a1SLionel Sambuc       { "assert",                SQLITE_TESTCTRL_ASSERT                 },
277011be35a1SLionel Sambuc       { "always",                SQLITE_TESTCTRL_ALWAYS                 },
277111be35a1SLionel Sambuc       { "reserve",               SQLITE_TESTCTRL_RESERVE                },
277211be35a1SLionel Sambuc       { "optimizations",         SQLITE_TESTCTRL_OPTIMIZATIONS          },
277311be35a1SLionel Sambuc       { "iskeyword",             SQLITE_TESTCTRL_ISKEYWORD              },
277411be35a1SLionel Sambuc       { "scratchmalloc",         SQLITE_TESTCTRL_SCRATCHMALLOC          },
277511be35a1SLionel Sambuc     };
277611be35a1SLionel Sambuc     int testctrl = -1;
277711be35a1SLionel Sambuc     int rc = 0;
277811be35a1SLionel Sambuc     int i, n;
2779*0a6a1f1dSLionel Sambuc     open_db(p, 0);
278011be35a1SLionel Sambuc 
278111be35a1SLionel Sambuc     /* convert testctrl text option to value. allow any unique prefix
278211be35a1SLionel Sambuc     ** of the option name, or a numerical value. */
278311be35a1SLionel Sambuc     n = strlen30(azArg[1]);
278411be35a1SLionel Sambuc     for(i=0; i<(int)(sizeof(aCtrl)/sizeof(aCtrl[0])); i++){
278511be35a1SLionel Sambuc       if( strncmp(azArg[1], aCtrl[i].zCtrlName, n)==0 ){
278611be35a1SLionel Sambuc         if( testctrl<0 ){
278711be35a1SLionel Sambuc           testctrl = aCtrl[i].ctrlCode;
278811be35a1SLionel Sambuc         }else{
278911be35a1SLionel Sambuc           fprintf(stderr, "ambiguous option name: \"%s\"\n", azArg[1]);
279011be35a1SLionel Sambuc           testctrl = -1;
279111be35a1SLionel Sambuc           break;
279211be35a1SLionel Sambuc         }
279311be35a1SLionel Sambuc       }
279411be35a1SLionel Sambuc     }
2795*0a6a1f1dSLionel Sambuc     if( testctrl<0 ) testctrl = (int)integerValue(azArg[1]);
279611be35a1SLionel Sambuc     if( (testctrl<SQLITE_TESTCTRL_FIRST) || (testctrl>SQLITE_TESTCTRL_LAST) ){
279711be35a1SLionel Sambuc       fprintf(stderr,"Error: invalid testctrl option: %s\n", azArg[1]);
279811be35a1SLionel Sambuc     }else{
279911be35a1SLionel Sambuc       switch(testctrl){
280011be35a1SLionel Sambuc 
280111be35a1SLionel Sambuc         /* sqlite3_test_control(int, db, int) */
280211be35a1SLionel Sambuc         case SQLITE_TESTCTRL_OPTIMIZATIONS:
280311be35a1SLionel Sambuc         case SQLITE_TESTCTRL_RESERVE:
280411be35a1SLionel Sambuc           if( nArg==3 ){
280511be35a1SLionel Sambuc             int opt = (int)strtol(azArg[2], 0, 0);
280611be35a1SLionel Sambuc             rc = sqlite3_test_control(testctrl, p->db, opt);
2807*0a6a1f1dSLionel Sambuc             fprintf(p->out, "%d (0x%08x)\n", rc, rc);
280811be35a1SLionel Sambuc           } else {
280911be35a1SLionel Sambuc             fprintf(stderr,"Error: testctrl %s takes a single int option\n",
281011be35a1SLionel Sambuc                     azArg[1]);
281111be35a1SLionel Sambuc           }
281211be35a1SLionel Sambuc           break;
281311be35a1SLionel Sambuc 
281411be35a1SLionel Sambuc         /* sqlite3_test_control(int) */
281511be35a1SLionel Sambuc         case SQLITE_TESTCTRL_PRNG_SAVE:
281611be35a1SLionel Sambuc         case SQLITE_TESTCTRL_PRNG_RESTORE:
281711be35a1SLionel Sambuc         case SQLITE_TESTCTRL_PRNG_RESET:
281811be35a1SLionel Sambuc           if( nArg==2 ){
281911be35a1SLionel Sambuc             rc = sqlite3_test_control(testctrl);
2820*0a6a1f1dSLionel Sambuc             fprintf(p->out, "%d (0x%08x)\n", rc, rc);
282111be35a1SLionel Sambuc           } else {
282211be35a1SLionel Sambuc             fprintf(stderr,"Error: testctrl %s takes no options\n", azArg[1]);
282311be35a1SLionel Sambuc           }
282411be35a1SLionel Sambuc           break;
282511be35a1SLionel Sambuc 
282611be35a1SLionel Sambuc         /* sqlite3_test_control(int, uint) */
282711be35a1SLionel Sambuc         case SQLITE_TESTCTRL_PENDING_BYTE:
282811be35a1SLionel Sambuc           if( nArg==3 ){
2829*0a6a1f1dSLionel Sambuc             unsigned int opt = (unsigned int)integerValue(azArg[2]);
283011be35a1SLionel Sambuc             rc = sqlite3_test_control(testctrl, opt);
2831*0a6a1f1dSLionel Sambuc             fprintf(p->out, "%d (0x%08x)\n", rc, rc);
283211be35a1SLionel Sambuc           } else {
283311be35a1SLionel Sambuc             fprintf(stderr,"Error: testctrl %s takes a single unsigned"
283411be35a1SLionel Sambuc                            " int option\n", azArg[1]);
283511be35a1SLionel Sambuc           }
283611be35a1SLionel Sambuc           break;
283711be35a1SLionel Sambuc 
283811be35a1SLionel Sambuc         /* sqlite3_test_control(int, int) */
283911be35a1SLionel Sambuc         case SQLITE_TESTCTRL_ASSERT:
284011be35a1SLionel Sambuc         case SQLITE_TESTCTRL_ALWAYS:
284111be35a1SLionel Sambuc           if( nArg==3 ){
2842*0a6a1f1dSLionel Sambuc             int opt = booleanValue(azArg[2]);
284311be35a1SLionel Sambuc             rc = sqlite3_test_control(testctrl, opt);
2844*0a6a1f1dSLionel Sambuc             fprintf(p->out, "%d (0x%08x)\n", rc, rc);
284511be35a1SLionel Sambuc           } else {
284611be35a1SLionel Sambuc             fprintf(stderr,"Error: testctrl %s takes a single int option\n",
284711be35a1SLionel Sambuc                             azArg[1]);
284811be35a1SLionel Sambuc           }
284911be35a1SLionel Sambuc           break;
285011be35a1SLionel Sambuc 
285111be35a1SLionel Sambuc         /* sqlite3_test_control(int, char *) */
285211be35a1SLionel Sambuc #ifdef SQLITE_N_KEYWORD
285311be35a1SLionel Sambuc         case SQLITE_TESTCTRL_ISKEYWORD:
285411be35a1SLionel Sambuc           if( nArg==3 ){
285511be35a1SLionel Sambuc             const char *opt = azArg[2];
285611be35a1SLionel Sambuc             rc = sqlite3_test_control(testctrl, opt);
2857*0a6a1f1dSLionel Sambuc             fprintf(p->out, "%d (0x%08x)\n", rc, rc);
285811be35a1SLionel Sambuc           } else {
285911be35a1SLionel Sambuc             fprintf(stderr,"Error: testctrl %s takes a single char * option\n",
286011be35a1SLionel Sambuc                             azArg[1]);
286111be35a1SLionel Sambuc           }
286211be35a1SLionel Sambuc           break;
286311be35a1SLionel Sambuc #endif
286411be35a1SLionel Sambuc 
286511be35a1SLionel Sambuc         case SQLITE_TESTCTRL_BITVEC_TEST:
286611be35a1SLionel Sambuc         case SQLITE_TESTCTRL_FAULT_INSTALL:
286711be35a1SLionel Sambuc         case SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS:
286811be35a1SLionel Sambuc         case SQLITE_TESTCTRL_SCRATCHMALLOC:
286911be35a1SLionel Sambuc         default:
287011be35a1SLionel Sambuc           fprintf(stderr,"Error: CLI support for testctrl %s not implemented\n",
287111be35a1SLionel Sambuc                   azArg[1]);
287211be35a1SLionel Sambuc           break;
287311be35a1SLionel Sambuc       }
287411be35a1SLionel Sambuc     }
287511be35a1SLionel Sambuc   }else
287611be35a1SLionel Sambuc 
287711be35a1SLionel Sambuc   if( c=='t' && n>4 && strncmp(azArg[0], "timeout", n)==0 && nArg==2 ){
2878*0a6a1f1dSLionel Sambuc     open_db(p, 0);
2879*0a6a1f1dSLionel Sambuc     sqlite3_busy_timeout(p->db, (int)integerValue(azArg[1]));
288011be35a1SLionel Sambuc   }else
288111be35a1SLionel Sambuc 
288211be35a1SLionel Sambuc   if( HAS_TIMER && c=='t' && n>=5 && strncmp(azArg[0], "timer", n)==0
288311be35a1SLionel Sambuc    && nArg==2
288411be35a1SLionel Sambuc   ){
288511be35a1SLionel Sambuc     enableTimer = booleanValue(azArg[1]);
288611be35a1SLionel Sambuc   }else
288711be35a1SLionel Sambuc 
2888*0a6a1f1dSLionel Sambuc   if( c=='t' && strncmp(azArg[0], "trace", n)==0 && nArg>1 ){
2889*0a6a1f1dSLionel Sambuc     open_db(p, 0);
2890*0a6a1f1dSLionel Sambuc     output_file_close(p->traceOut);
2891*0a6a1f1dSLionel Sambuc     p->traceOut = output_file_open(azArg[1]);
2892*0a6a1f1dSLionel Sambuc #if !defined(SQLITE_OMIT_TRACE) && !defined(SQLITE_OMIT_FLOATING_POINT)
2893*0a6a1f1dSLionel Sambuc     if( p->traceOut==0 ){
2894*0a6a1f1dSLionel Sambuc       sqlite3_trace(p->db, 0, 0);
2895*0a6a1f1dSLionel Sambuc     }else{
2896*0a6a1f1dSLionel Sambuc       sqlite3_trace(p->db, sql_trace_callback, p->traceOut);
2897*0a6a1f1dSLionel Sambuc     }
2898*0a6a1f1dSLionel Sambuc #endif
2899*0a6a1f1dSLionel Sambuc   }else
2900*0a6a1f1dSLionel Sambuc 
290111be35a1SLionel Sambuc   if( c=='v' && strncmp(azArg[0], "version", n)==0 ){
2902*0a6a1f1dSLionel Sambuc     fprintf(p->out, "SQLite %s %s\n" /*extra-version-info*/,
290311be35a1SLionel Sambuc         sqlite3_libversion(), sqlite3_sourceid());
290411be35a1SLionel Sambuc   }else
290511be35a1SLionel Sambuc 
290611be35a1SLionel Sambuc   if( c=='v' && strncmp(azArg[0], "vfsname", n)==0 ){
290711be35a1SLionel Sambuc     const char *zDbName = nArg==2 ? azArg[1] : "main";
290811be35a1SLionel Sambuc     char *zVfsName = 0;
290911be35a1SLionel Sambuc     if( p->db ){
291011be35a1SLionel Sambuc       sqlite3_file_control(p->db, zDbName, SQLITE_FCNTL_VFSNAME, &zVfsName);
291111be35a1SLionel Sambuc       if( zVfsName ){
2912*0a6a1f1dSLionel Sambuc         fprintf(p->out, "%s\n", zVfsName);
291311be35a1SLionel Sambuc         sqlite3_free(zVfsName);
291411be35a1SLionel Sambuc       }
291511be35a1SLionel Sambuc     }
291611be35a1SLionel Sambuc   }else
291711be35a1SLionel Sambuc 
2918*0a6a1f1dSLionel Sambuc #if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_WHERETRACE)
2919*0a6a1f1dSLionel Sambuc   if( c=='w' && strncmp(azArg[0], "wheretrace", n)==0 ){
2920*0a6a1f1dSLionel Sambuc     extern int sqlite3WhereTrace;
2921*0a6a1f1dSLionel Sambuc     sqlite3WhereTrace = booleanValue(azArg[1]);
2922*0a6a1f1dSLionel Sambuc   }else
2923*0a6a1f1dSLionel Sambuc #endif
2924*0a6a1f1dSLionel Sambuc 
292511be35a1SLionel Sambuc   if( c=='w' && strncmp(azArg[0], "width", n)==0 && nArg>1 ){
292611be35a1SLionel Sambuc     int j;
292711be35a1SLionel Sambuc     assert( nArg<=ArraySize(azArg) );
292811be35a1SLionel Sambuc     for(j=1; j<nArg && j<ArraySize(p->colWidth); j++){
2929*0a6a1f1dSLionel Sambuc       p->colWidth[j-1] = (int)integerValue(azArg[j]);
293011be35a1SLionel Sambuc     }
293111be35a1SLionel Sambuc   }else
293211be35a1SLionel Sambuc 
293311be35a1SLionel Sambuc   {
293411be35a1SLionel Sambuc     fprintf(stderr, "Error: unknown command or invalid arguments: "
293511be35a1SLionel Sambuc       " \"%s\". Enter \".help\" for help\n", azArg[0]);
293611be35a1SLionel Sambuc     rc = 1;
293711be35a1SLionel Sambuc   }
293811be35a1SLionel Sambuc 
293911be35a1SLionel Sambuc   return rc;
294011be35a1SLionel Sambuc }
294111be35a1SLionel Sambuc 
294211be35a1SLionel Sambuc /*
294311be35a1SLionel Sambuc ** Return TRUE if a semicolon occurs anywhere in the first N characters
294411be35a1SLionel Sambuc ** of string z[].
294511be35a1SLionel Sambuc */
line_contains_semicolon(const char * z,int N)2946*0a6a1f1dSLionel Sambuc static int line_contains_semicolon(const char *z, int N){
294711be35a1SLionel Sambuc   int i;
294811be35a1SLionel Sambuc   for(i=0; i<N; i++){  if( z[i]==';' ) return 1; }
294911be35a1SLionel Sambuc   return 0;
295011be35a1SLionel Sambuc }
295111be35a1SLionel Sambuc 
295211be35a1SLionel Sambuc /*
295311be35a1SLionel Sambuc ** Test to see if a line consists entirely of whitespace.
295411be35a1SLionel Sambuc */
_all_whitespace(const char * z)295511be35a1SLionel Sambuc static int _all_whitespace(const char *z){
295611be35a1SLionel Sambuc   for(; *z; z++){
295711be35a1SLionel Sambuc     if( IsSpace(z[0]) ) continue;
295811be35a1SLionel Sambuc     if( *z=='/' && z[1]=='*' ){
295911be35a1SLionel Sambuc       z += 2;
296011be35a1SLionel Sambuc       while( *z && (*z!='*' || z[1]!='/') ){ z++; }
296111be35a1SLionel Sambuc       if( *z==0 ) return 0;
296211be35a1SLionel Sambuc       z++;
296311be35a1SLionel Sambuc       continue;
296411be35a1SLionel Sambuc     }
296511be35a1SLionel Sambuc     if( *z=='-' && z[1]=='-' ){
296611be35a1SLionel Sambuc       z += 2;
296711be35a1SLionel Sambuc       while( *z && *z!='\n' ){ z++; }
296811be35a1SLionel Sambuc       if( *z==0 ) return 1;
296911be35a1SLionel Sambuc       continue;
297011be35a1SLionel Sambuc     }
297111be35a1SLionel Sambuc     return 0;
297211be35a1SLionel Sambuc   }
297311be35a1SLionel Sambuc   return 1;
297411be35a1SLionel Sambuc }
297511be35a1SLionel Sambuc 
297611be35a1SLionel Sambuc /*
297711be35a1SLionel Sambuc ** Return TRUE if the line typed in is an SQL command terminator other
297811be35a1SLionel Sambuc ** than a semi-colon.  The SQL Server style "go" command is understood
297911be35a1SLionel Sambuc ** as is the Oracle "/".
298011be35a1SLionel Sambuc */
line_is_command_terminator(const char * zLine)2981*0a6a1f1dSLionel Sambuc static int line_is_command_terminator(const char *zLine){
298211be35a1SLionel Sambuc   while( IsSpace(zLine[0]) ){ zLine++; };
298311be35a1SLionel Sambuc   if( zLine[0]=='/' && _all_whitespace(&zLine[1]) ){
298411be35a1SLionel Sambuc     return 1;  /* Oracle */
298511be35a1SLionel Sambuc   }
298611be35a1SLionel Sambuc   if( ToLower(zLine[0])=='g' && ToLower(zLine[1])=='o'
298711be35a1SLionel Sambuc          && _all_whitespace(&zLine[2]) ){
298811be35a1SLionel Sambuc     return 1;  /* SQL Server */
298911be35a1SLionel Sambuc   }
299011be35a1SLionel Sambuc   return 0;
299111be35a1SLionel Sambuc }
299211be35a1SLionel Sambuc 
299311be35a1SLionel Sambuc /*
299411be35a1SLionel Sambuc ** Return true if zSql is a complete SQL statement.  Return false if it
299511be35a1SLionel Sambuc ** ends in the middle of a string literal or C-style comment.
299611be35a1SLionel Sambuc */
line_is_complete(char * zSql,int nSql)2997*0a6a1f1dSLionel Sambuc static int line_is_complete(char *zSql, int nSql){
299811be35a1SLionel Sambuc   int rc;
299911be35a1SLionel Sambuc   if( zSql==0 ) return 1;
300011be35a1SLionel Sambuc   zSql[nSql] = ';';
300111be35a1SLionel Sambuc   zSql[nSql+1] = 0;
300211be35a1SLionel Sambuc   rc = sqlite3_complete(zSql);
300311be35a1SLionel Sambuc   zSql[nSql] = 0;
300411be35a1SLionel Sambuc   return rc;
300511be35a1SLionel Sambuc }
300611be35a1SLionel Sambuc 
300711be35a1SLionel Sambuc /*
300811be35a1SLionel Sambuc ** Read input from *in and process it.  If *in==0 then input
300911be35a1SLionel Sambuc ** is interactive - the user is typing it it.  Otherwise, input
301011be35a1SLionel Sambuc ** is coming from a file or device.  A prompt is issued and history
301111be35a1SLionel Sambuc ** is saved only if input is interactive.  An interrupt signal will
301211be35a1SLionel Sambuc ** cause this routine to exit immediately, unless input is interactive.
301311be35a1SLionel Sambuc **
301411be35a1SLionel Sambuc ** Return the number of errors.
301511be35a1SLionel Sambuc */
process_input(struct callback_data * p,FILE * in)301611be35a1SLionel Sambuc static int process_input(struct callback_data *p, FILE *in){
3017*0a6a1f1dSLionel Sambuc   char *zLine = 0;          /* A single input line */
3018*0a6a1f1dSLionel Sambuc   char *zSql = 0;           /* Accumulated SQL text */
3019*0a6a1f1dSLionel Sambuc   int nLine;                /* Length of current line */
3020*0a6a1f1dSLionel Sambuc   int nSql = 0;             /* Bytes of zSql[] used */
3021*0a6a1f1dSLionel Sambuc   int nAlloc = 0;           /* Allocated zSql[] space */
3022*0a6a1f1dSLionel Sambuc   int nSqlPrior = 0;        /* Bytes of zSql[] used by prior line */
3023*0a6a1f1dSLionel Sambuc   char *zErrMsg;            /* Error message returned */
3024*0a6a1f1dSLionel Sambuc   int rc;                   /* Error code */
3025*0a6a1f1dSLionel Sambuc   int errCnt = 0;           /* Number of errors seen */
3026*0a6a1f1dSLionel Sambuc   int lineno = 0;           /* Current line number */
3027*0a6a1f1dSLionel Sambuc   int startline = 0;        /* Line number for start of current input */
302811be35a1SLionel Sambuc 
302911be35a1SLionel Sambuc   while( errCnt==0 || !bail_on_error || (in==0 && stdin_is_interactive) ){
303011be35a1SLionel Sambuc     fflush(p->out);
3031*0a6a1f1dSLionel Sambuc     zLine = one_input_line(in, zLine, nSql>0);
303211be35a1SLionel Sambuc     if( zLine==0 ){
3033*0a6a1f1dSLionel Sambuc       /* End of input */
3034*0a6a1f1dSLionel Sambuc       if( stdin_is_interactive ) printf("\n");
3035*0a6a1f1dSLionel Sambuc       break;
303611be35a1SLionel Sambuc     }
303711be35a1SLionel Sambuc     if( seenInterrupt ){
303811be35a1SLionel Sambuc       if( in!=0 ) break;
303911be35a1SLionel Sambuc       seenInterrupt = 0;
304011be35a1SLionel Sambuc     }
304111be35a1SLionel Sambuc     lineno++;
3042*0a6a1f1dSLionel Sambuc     if( nSql==0 && _all_whitespace(zLine) ){
3043*0a6a1f1dSLionel Sambuc       if( p->echoOn ) printf("%s\n", zLine);
3044*0a6a1f1dSLionel Sambuc       continue;
3045*0a6a1f1dSLionel Sambuc     }
304611be35a1SLionel Sambuc     if( zLine && zLine[0]=='.' && nSql==0 ){
304711be35a1SLionel Sambuc       if( p->echoOn ) printf("%s\n", zLine);
304811be35a1SLionel Sambuc       rc = do_meta_command(zLine, p);
304911be35a1SLionel Sambuc       if( rc==2 ){ /* exit requested */
305011be35a1SLionel Sambuc         break;
305111be35a1SLionel Sambuc       }else if( rc ){
305211be35a1SLionel Sambuc         errCnt++;
305311be35a1SLionel Sambuc       }
305411be35a1SLionel Sambuc       continue;
305511be35a1SLionel Sambuc     }
3056*0a6a1f1dSLionel Sambuc     if( line_is_command_terminator(zLine) && line_is_complete(zSql, nSql) ){
305711be35a1SLionel Sambuc       memcpy(zLine,";",2);
305811be35a1SLionel Sambuc     }
3059*0a6a1f1dSLionel Sambuc     nLine = strlen30(zLine);
3060*0a6a1f1dSLionel Sambuc     if( nSql+nLine+2>=nAlloc ){
3061*0a6a1f1dSLionel Sambuc       nAlloc = nSql+nLine+100;
3062*0a6a1f1dSLionel Sambuc       zSql = realloc(zSql, nAlloc);
306311be35a1SLionel Sambuc       if( zSql==0 ){
3064*0a6a1f1dSLionel Sambuc         fprintf(stderr, "Error: out of memory\n");
3065*0a6a1f1dSLionel Sambuc         exit(1);
3066*0a6a1f1dSLionel Sambuc       }
3067*0a6a1f1dSLionel Sambuc     }
3068*0a6a1f1dSLionel Sambuc     nSqlPrior = nSql;
3069*0a6a1f1dSLionel Sambuc     if( nSql==0 ){
307011be35a1SLionel Sambuc       int i;
307111be35a1SLionel Sambuc       for(i=0; zLine[i] && IsSpace(zLine[i]); i++){}
3072*0a6a1f1dSLionel Sambuc       assert( nAlloc>0 && zSql!=0 );
3073*0a6a1f1dSLionel Sambuc       memcpy(zSql, zLine+i, nLine+1-i);
307411be35a1SLionel Sambuc       startline = lineno;
3075*0a6a1f1dSLionel Sambuc       nSql = nLine-i;
307611be35a1SLionel Sambuc     }else{
307711be35a1SLionel Sambuc       zSql[nSql++] = '\n';
3078*0a6a1f1dSLionel Sambuc       memcpy(zSql+nSql, zLine, nLine+1);
3079*0a6a1f1dSLionel Sambuc       nSql += nLine;
308011be35a1SLionel Sambuc     }
3081*0a6a1f1dSLionel Sambuc     if( nSql && line_contains_semicolon(&zSql[nSqlPrior], nSql-nSqlPrior)
308211be35a1SLionel Sambuc                 && sqlite3_complete(zSql) ){
308311be35a1SLionel Sambuc       p->cnt = 0;
3084*0a6a1f1dSLionel Sambuc       open_db(p, 0);
308511be35a1SLionel Sambuc       BEGIN_TIMER;
308611be35a1SLionel Sambuc       rc = shell_exec(p->db, zSql, shell_callback, p, &zErrMsg);
308711be35a1SLionel Sambuc       END_TIMER;
308811be35a1SLionel Sambuc       if( rc || zErrMsg ){
308911be35a1SLionel Sambuc         char zPrefix[100];
309011be35a1SLionel Sambuc         if( in!=0 || !stdin_is_interactive ){
309111be35a1SLionel Sambuc           sqlite3_snprintf(sizeof(zPrefix), zPrefix,
309211be35a1SLionel Sambuc                            "Error: near line %d:", startline);
309311be35a1SLionel Sambuc         }else{
309411be35a1SLionel Sambuc           sqlite3_snprintf(sizeof(zPrefix), zPrefix, "Error:");
309511be35a1SLionel Sambuc         }
309611be35a1SLionel Sambuc         if( zErrMsg!=0 ){
309711be35a1SLionel Sambuc           fprintf(stderr, "%s %s\n", zPrefix, zErrMsg);
309811be35a1SLionel Sambuc           sqlite3_free(zErrMsg);
309911be35a1SLionel Sambuc           zErrMsg = 0;
310011be35a1SLionel Sambuc         }else{
310111be35a1SLionel Sambuc           fprintf(stderr, "%s %s\n", zPrefix, sqlite3_errmsg(p->db));
310211be35a1SLionel Sambuc         }
310311be35a1SLionel Sambuc         errCnt++;
310411be35a1SLionel Sambuc       }
3105*0a6a1f1dSLionel Sambuc       nSql = 0;
3106*0a6a1f1dSLionel Sambuc     }else if( nSql && _all_whitespace(zSql) ){
3107*0a6a1f1dSLionel Sambuc       if( p->echoOn ) printf("%s\n", zSql);
310811be35a1SLionel Sambuc       nSql = 0;
310911be35a1SLionel Sambuc     }
311011be35a1SLionel Sambuc   }
3111*0a6a1f1dSLionel Sambuc   if( nSql ){
311211be35a1SLionel Sambuc     if( !_all_whitespace(zSql) ){
311311be35a1SLionel Sambuc       fprintf(stderr, "Error: incomplete SQL: %s\n", zSql);
311411be35a1SLionel Sambuc     }
311511be35a1SLionel Sambuc     free(zSql);
311611be35a1SLionel Sambuc   }
311711be35a1SLionel Sambuc   free(zLine);
3118*0a6a1f1dSLionel Sambuc   return errCnt>0;
311911be35a1SLionel Sambuc }
312011be35a1SLionel Sambuc 
312111be35a1SLionel Sambuc /*
312211be35a1SLionel Sambuc ** Return a pathname which is the user's home directory.  A
3123*0a6a1f1dSLionel Sambuc ** 0 return indicates an error of some kind.
312411be35a1SLionel Sambuc */
find_home_dir(void)312511be35a1SLionel Sambuc static char *find_home_dir(void){
3126*0a6a1f1dSLionel Sambuc   static char *home_dir = NULL;
3127*0a6a1f1dSLionel Sambuc   if( home_dir ) return home_dir;
312811be35a1SLionel Sambuc 
3129*0a6a1f1dSLionel Sambuc #if !defined(_WIN32) && !defined(WIN32) && !defined(_WIN32_WCE) && !defined(__RTP__) && !defined(_WRS_KERNEL)
3130*0a6a1f1dSLionel Sambuc   {
313111be35a1SLionel Sambuc     struct passwd *pwent;
313211be35a1SLionel Sambuc     uid_t uid = getuid();
313311be35a1SLionel Sambuc     if( (pwent=getpwuid(uid)) != NULL) {
313411be35a1SLionel Sambuc       home_dir = pwent->pw_dir;
313511be35a1SLionel Sambuc     }
3136*0a6a1f1dSLionel Sambuc   }
313711be35a1SLionel Sambuc #endif
313811be35a1SLionel Sambuc 
313911be35a1SLionel Sambuc #if defined(_WIN32_WCE)
314011be35a1SLionel Sambuc   /* Windows CE (arm-wince-mingw32ce-gcc) does not provide getenv()
314111be35a1SLionel Sambuc    */
3142*0a6a1f1dSLionel Sambuc   home_dir = "/";
314311be35a1SLionel Sambuc #else
314411be35a1SLionel Sambuc 
3145*0a6a1f1dSLionel Sambuc #if defined(_WIN32) || defined(WIN32)
314611be35a1SLionel Sambuc   if (!home_dir) {
314711be35a1SLionel Sambuc     home_dir = getenv("USERPROFILE");
314811be35a1SLionel Sambuc   }
314911be35a1SLionel Sambuc #endif
315011be35a1SLionel Sambuc 
315111be35a1SLionel Sambuc   if (!home_dir) {
315211be35a1SLionel Sambuc     home_dir = getenv("HOME");
315311be35a1SLionel Sambuc   }
315411be35a1SLionel Sambuc 
3155*0a6a1f1dSLionel Sambuc #if defined(_WIN32) || defined(WIN32)
315611be35a1SLionel Sambuc   if (!home_dir) {
315711be35a1SLionel Sambuc     char *zDrive, *zPath;
315811be35a1SLionel Sambuc     int n;
315911be35a1SLionel Sambuc     zDrive = getenv("HOMEDRIVE");
316011be35a1SLionel Sambuc     zPath = getenv("HOMEPATH");
316111be35a1SLionel Sambuc     if( zDrive && zPath ){
316211be35a1SLionel Sambuc       n = strlen30(zDrive) + strlen30(zPath) + 1;
316311be35a1SLionel Sambuc       home_dir = malloc( n );
316411be35a1SLionel Sambuc       if( home_dir==0 ) return 0;
316511be35a1SLionel Sambuc       sqlite3_snprintf(n, home_dir, "%s%s", zDrive, zPath);
316611be35a1SLionel Sambuc       return home_dir;
316711be35a1SLionel Sambuc     }
316811be35a1SLionel Sambuc     home_dir = "c:\\";
316911be35a1SLionel Sambuc   }
317011be35a1SLionel Sambuc #endif
317111be35a1SLionel Sambuc 
317211be35a1SLionel Sambuc #endif /* !_WIN32_WCE */
317311be35a1SLionel Sambuc 
317411be35a1SLionel Sambuc   if( home_dir ){
317511be35a1SLionel Sambuc     int n = strlen30(home_dir) + 1;
317611be35a1SLionel Sambuc     char *z = malloc( n );
317711be35a1SLionel Sambuc     if( z ) memcpy(z, home_dir, n);
317811be35a1SLionel Sambuc     home_dir = z;
317911be35a1SLionel Sambuc   }
318011be35a1SLionel Sambuc 
318111be35a1SLionel Sambuc   return home_dir;
318211be35a1SLionel Sambuc }
318311be35a1SLionel Sambuc 
318411be35a1SLionel Sambuc /*
318511be35a1SLionel Sambuc ** Read input from the file given by sqliterc_override.  Or if that
318611be35a1SLionel Sambuc ** parameter is NULL, take input from ~/.sqliterc
318711be35a1SLionel Sambuc **
318811be35a1SLionel Sambuc ** Returns the number of errors.
318911be35a1SLionel Sambuc */
process_sqliterc(struct callback_data * p,const char * sqliterc_override)319011be35a1SLionel Sambuc static int process_sqliterc(
319111be35a1SLionel Sambuc   struct callback_data *p,        /* Configuration data */
319211be35a1SLionel Sambuc   const char *sqliterc_override   /* Name of config file. NULL to use default */
319311be35a1SLionel Sambuc ){
319411be35a1SLionel Sambuc   char *home_dir = NULL;
319511be35a1SLionel Sambuc   const char *sqliterc = sqliterc_override;
319611be35a1SLionel Sambuc   char *zBuf = 0;
319711be35a1SLionel Sambuc   FILE *in = NULL;
319811be35a1SLionel Sambuc   int rc = 0;
319911be35a1SLionel Sambuc 
320011be35a1SLionel Sambuc   if (sqliterc == NULL) {
320111be35a1SLionel Sambuc     home_dir = find_home_dir();
320211be35a1SLionel Sambuc     if( home_dir==0 ){
320311be35a1SLionel Sambuc #if !defined(__RTP__) && !defined(_WRS_KERNEL)
320411be35a1SLionel Sambuc       fprintf(stderr,"%s: Error: cannot locate your home directory\n", Argv0);
320511be35a1SLionel Sambuc #endif
320611be35a1SLionel Sambuc       return 1;
320711be35a1SLionel Sambuc     }
3208*0a6a1f1dSLionel Sambuc     sqlite3_initialize();
3209*0a6a1f1dSLionel Sambuc     zBuf = sqlite3_mprintf("%s/.sqliterc",home_dir);
3210*0a6a1f1dSLionel Sambuc     sqliterc = zBuf;
321111be35a1SLionel Sambuc   }
321211be35a1SLionel Sambuc   in = fopen(sqliterc,"rb");
321311be35a1SLionel Sambuc   if( in ){
321411be35a1SLionel Sambuc     if( stdin_is_interactive ){
321511be35a1SLionel Sambuc       fprintf(stderr,"-- Loading resources from %s\n",sqliterc);
321611be35a1SLionel Sambuc     }
321711be35a1SLionel Sambuc     rc = process_input(p,in);
321811be35a1SLionel Sambuc     fclose(in);
321911be35a1SLionel Sambuc   }
3220*0a6a1f1dSLionel Sambuc   sqlite3_free(zBuf);
322111be35a1SLionel Sambuc   return rc;
322211be35a1SLionel Sambuc }
322311be35a1SLionel Sambuc 
322411be35a1SLionel Sambuc /*
322511be35a1SLionel Sambuc ** Show available command line options
322611be35a1SLionel Sambuc */
322711be35a1SLionel Sambuc static const char zOptions[] =
322811be35a1SLionel Sambuc   "   -bail                stop after hitting an error\n"
322911be35a1SLionel Sambuc   "   -batch               force batch I/O\n"
323011be35a1SLionel Sambuc   "   -column              set output mode to 'column'\n"
3231*0a6a1f1dSLionel Sambuc   "   -cmd COMMAND         run \"COMMAND\" before reading stdin\n"
323211be35a1SLionel Sambuc   "   -csv                 set output mode to 'csv'\n"
3233*0a6a1f1dSLionel Sambuc   "   -echo                print commands before execution\n"
3234*0a6a1f1dSLionel Sambuc   "   -init FILENAME       read/process named file\n"
3235*0a6a1f1dSLionel Sambuc   "   -[no]header          turn headers on or off\n"
3236*0a6a1f1dSLionel Sambuc #if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5)
3237*0a6a1f1dSLionel Sambuc   "   -heap SIZE           Size of heap for memsys3 or memsys5\n"
3238*0a6a1f1dSLionel Sambuc #endif
3239*0a6a1f1dSLionel Sambuc   "   -help                show this message\n"
324011be35a1SLionel Sambuc   "   -html                set output mode to HTML\n"
3241*0a6a1f1dSLionel Sambuc   "   -interactive         force interactive I/O\n"
324211be35a1SLionel Sambuc   "   -line                set output mode to 'line'\n"
324311be35a1SLionel Sambuc   "   -list                set output mode to 'list'\n"
3244*0a6a1f1dSLionel Sambuc   "   -mmap N              default mmap size set to N\n"
3245*0a6a1f1dSLionel Sambuc #ifdef SQLITE_ENABLE_MULTIPLEX
3246*0a6a1f1dSLionel Sambuc   "   -multiplex           enable the multiplexor VFS\n"
3247*0a6a1f1dSLionel Sambuc #endif
3248*0a6a1f1dSLionel Sambuc   "   -nullvalue TEXT      set text string for NULL values. Default ''\n"
3249*0a6a1f1dSLionel Sambuc   "   -separator SEP       set output field separator. Default: '|'\n"
325011be35a1SLionel Sambuc   "   -stats               print memory stats before each finalize\n"
325111be35a1SLionel Sambuc   "   -version             show SQLite version\n"
325211be35a1SLionel Sambuc   "   -vfs NAME            use NAME as the default VFS\n"
325311be35a1SLionel Sambuc #ifdef SQLITE_ENABLE_VFSTRACE
325411be35a1SLionel Sambuc   "   -vfstrace            enable tracing of all VFS calls\n"
325511be35a1SLionel Sambuc #endif
325611be35a1SLionel Sambuc ;
usage(int showDetail)325711be35a1SLionel Sambuc static void usage(int showDetail){
325811be35a1SLionel Sambuc   fprintf(stderr,
325911be35a1SLionel Sambuc       "Usage: %s [OPTIONS] FILENAME [SQL]\n"
326011be35a1SLionel Sambuc       "FILENAME is the name of an SQLite database. A new database is created\n"
326111be35a1SLionel Sambuc       "if the file does not previously exist.\n", Argv0);
326211be35a1SLionel Sambuc   if( showDetail ){
326311be35a1SLionel Sambuc     fprintf(stderr, "OPTIONS include:\n%s", zOptions);
326411be35a1SLionel Sambuc   }else{
326511be35a1SLionel Sambuc     fprintf(stderr, "Use the -help option for additional information\n");
326611be35a1SLionel Sambuc   }
326711be35a1SLionel Sambuc   exit(1);
326811be35a1SLionel Sambuc }
326911be35a1SLionel Sambuc 
327011be35a1SLionel Sambuc /*
327111be35a1SLionel Sambuc ** Initialize the state information in data
327211be35a1SLionel Sambuc */
main_init(struct callback_data * data)327311be35a1SLionel Sambuc static void main_init(struct callback_data *data) {
327411be35a1SLionel Sambuc   memset(data, 0, sizeof(*data));
327511be35a1SLionel Sambuc   data->mode = MODE_List;
327611be35a1SLionel Sambuc   memcpy(data->separator,"|", 2);
327711be35a1SLionel Sambuc   data->showHeader = 0;
327811be35a1SLionel Sambuc   sqlite3_config(SQLITE_CONFIG_URI, 1);
327911be35a1SLionel Sambuc   sqlite3_config(SQLITE_CONFIG_LOG, shellLog, data);
328011be35a1SLionel Sambuc   sqlite3_snprintf(sizeof(mainPrompt), mainPrompt,"sqlite> ");
328111be35a1SLionel Sambuc   sqlite3_snprintf(sizeof(continuePrompt), continuePrompt,"   ...> ");
328211be35a1SLionel Sambuc   sqlite3_config(SQLITE_CONFIG_SINGLETHREAD);
328311be35a1SLionel Sambuc }
328411be35a1SLionel Sambuc 
3285*0a6a1f1dSLionel Sambuc /*
3286*0a6a1f1dSLionel Sambuc ** Get the argument to an --option.  Throw an error and die if no argument
3287*0a6a1f1dSLionel Sambuc ** is available.
3288*0a6a1f1dSLionel Sambuc */
cmdline_option_value(int argc,char ** argv,int i)3289*0a6a1f1dSLionel Sambuc static char *cmdline_option_value(int argc, char **argv, int i){
3290*0a6a1f1dSLionel Sambuc   if( i==argc ){
3291*0a6a1f1dSLionel Sambuc     fprintf(stderr, "%s: Error: missing argument to %s\n",
3292*0a6a1f1dSLionel Sambuc             argv[0], argv[argc-1]);
3293*0a6a1f1dSLionel Sambuc     exit(1);
3294*0a6a1f1dSLionel Sambuc   }
3295*0a6a1f1dSLionel Sambuc   return argv[i];
3296*0a6a1f1dSLionel Sambuc }
3297*0a6a1f1dSLionel Sambuc 
main(int argc,char ** argv)329811be35a1SLionel Sambuc int main(int argc, char **argv){
329911be35a1SLionel Sambuc   char *zErrMsg = 0;
330011be35a1SLionel Sambuc   struct callback_data data;
330111be35a1SLionel Sambuc   const char *zInitFile = 0;
330211be35a1SLionel Sambuc   char *zFirstCmd = 0;
330311be35a1SLionel Sambuc   int i;
330411be35a1SLionel Sambuc   int rc = 0;
330511be35a1SLionel Sambuc 
330611be35a1SLionel Sambuc   if( strcmp(sqlite3_sourceid(),SQLITE_SOURCE_ID)!=0 ){
330711be35a1SLionel Sambuc     fprintf(stderr, "SQLite header and source version mismatch\n%s\n%s\n",
330811be35a1SLionel Sambuc             sqlite3_sourceid(), SQLITE_SOURCE_ID);
330911be35a1SLionel Sambuc     exit(1);
331011be35a1SLionel Sambuc   }
331111be35a1SLionel Sambuc   Argv0 = argv[0];
331211be35a1SLionel Sambuc   main_init(&data);
331311be35a1SLionel Sambuc   stdin_is_interactive = isatty(0);
331411be35a1SLionel Sambuc 
331511be35a1SLionel Sambuc   /* Make sure we have a valid signal handler early, before anything
331611be35a1SLionel Sambuc   ** else is done.
331711be35a1SLionel Sambuc   */
331811be35a1SLionel Sambuc #ifdef SIGINT
331911be35a1SLionel Sambuc   signal(SIGINT, interrupt_handler);
332011be35a1SLionel Sambuc #endif
332111be35a1SLionel Sambuc 
332211be35a1SLionel Sambuc   /* Do an initial pass through the command-line argument to locate
332311be35a1SLionel Sambuc   ** the name of the database file, the name of the initialization file,
332411be35a1SLionel Sambuc   ** the size of the alternative malloc heap,
332511be35a1SLionel Sambuc   ** and the first command to execute.
332611be35a1SLionel Sambuc   */
3327*0a6a1f1dSLionel Sambuc   for(i=1; i<argc; i++){
332811be35a1SLionel Sambuc     char *z;
332911be35a1SLionel Sambuc     z = argv[i];
3330*0a6a1f1dSLionel Sambuc     if( z[0]!='-' ){
3331*0a6a1f1dSLionel Sambuc       if( data.zDbFilename==0 ){
3332*0a6a1f1dSLionel Sambuc         data.zDbFilename = z;
3333*0a6a1f1dSLionel Sambuc         continue;
3334*0a6a1f1dSLionel Sambuc       }
3335*0a6a1f1dSLionel Sambuc       if( zFirstCmd==0 ){
3336*0a6a1f1dSLionel Sambuc         zFirstCmd = z;
3337*0a6a1f1dSLionel Sambuc         continue;
3338*0a6a1f1dSLionel Sambuc       }
3339*0a6a1f1dSLionel Sambuc       fprintf(stderr,"%s: Error: too many options: \"%s\"\n", Argv0, argv[i]);
3340*0a6a1f1dSLionel Sambuc       fprintf(stderr,"Use -help for a list of options.\n");
3341*0a6a1f1dSLionel Sambuc       return 1;
3342*0a6a1f1dSLionel Sambuc     }
3343*0a6a1f1dSLionel Sambuc     if( z[1]=='-' ) z++;
3344*0a6a1f1dSLionel Sambuc     if( strcmp(z,"-separator")==0
3345*0a6a1f1dSLionel Sambuc      || strcmp(z,"-nullvalue")==0
3346*0a6a1f1dSLionel Sambuc      || strcmp(z,"-cmd")==0
3347*0a6a1f1dSLionel Sambuc     ){
3348*0a6a1f1dSLionel Sambuc       (void)cmdline_option_value(argc, argv, ++i);
3349*0a6a1f1dSLionel Sambuc     }else if( strcmp(z,"-init")==0 ){
3350*0a6a1f1dSLionel Sambuc       zInitFile = cmdline_option_value(argc, argv, ++i);
3351*0a6a1f1dSLionel Sambuc     }else if( strcmp(z,"-batch")==0 ){
335211be35a1SLionel Sambuc       /* Need to check for batch mode here to so we can avoid printing
335311be35a1SLionel Sambuc       ** informational messages (like from process_sqliterc) before
335411be35a1SLionel Sambuc       ** we do the actual processing of arguments later in a second pass.
335511be35a1SLionel Sambuc       */
335611be35a1SLionel Sambuc       stdin_is_interactive = 0;
3357*0a6a1f1dSLionel Sambuc     }else if( strcmp(z,"-heap")==0 ){
335811be35a1SLionel Sambuc #if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5)
335911be35a1SLionel Sambuc       const char *zSize;
336011be35a1SLionel Sambuc       sqlite3_int64 szHeap;
336111be35a1SLionel Sambuc 
3362*0a6a1f1dSLionel Sambuc       zSize = cmdline_option_value(argc, argv, ++i);
3363*0a6a1f1dSLionel Sambuc       szHeap = integerValue(zSize);
336411be35a1SLionel Sambuc       if( szHeap>0x7fff0000 ) szHeap = 0x7fff0000;
336511be35a1SLionel Sambuc       sqlite3_config(SQLITE_CONFIG_HEAP, malloc((int)szHeap), (int)szHeap, 64);
336611be35a1SLionel Sambuc #endif
336711be35a1SLionel Sambuc #ifdef SQLITE_ENABLE_VFSTRACE
3368*0a6a1f1dSLionel Sambuc     }else if( strcmp(z,"-vfstrace")==0 ){
336911be35a1SLionel Sambuc       extern int vfstrace_register(
337011be35a1SLionel Sambuc          const char *zTraceName,
337111be35a1SLionel Sambuc          const char *zOldVfsName,
337211be35a1SLionel Sambuc          int (*xOut)(const char*,void*),
337311be35a1SLionel Sambuc          void *pOutArg,
337411be35a1SLionel Sambuc          int makeDefault
337511be35a1SLionel Sambuc       );
337611be35a1SLionel Sambuc       vfstrace_register("trace",0,(int(*)(const char*,void*))fputs,stderr,1);
337711be35a1SLionel Sambuc #endif
337811be35a1SLionel Sambuc #ifdef SQLITE_ENABLE_MULTIPLEX
3379*0a6a1f1dSLionel Sambuc     }else if( strcmp(z,"-multiplex")==0 ){
338011be35a1SLionel Sambuc       extern int sqlite3_multiple_initialize(const char*,int);
338111be35a1SLionel Sambuc       sqlite3_multiplex_initialize(0, 1);
338211be35a1SLionel Sambuc #endif
3383*0a6a1f1dSLionel Sambuc     }else if( strcmp(z,"-mmap")==0 ){
3384*0a6a1f1dSLionel Sambuc       sqlite3_int64 sz = integerValue(cmdline_option_value(argc,argv,++i));
3385*0a6a1f1dSLionel Sambuc       sqlite3_config(SQLITE_CONFIG_MMAP_SIZE, sz, sz);
3386*0a6a1f1dSLionel Sambuc     }else if( strcmp(z,"-vfs")==0 ){
3387*0a6a1f1dSLionel Sambuc       sqlite3_vfs *pVfs = sqlite3_vfs_find(cmdline_option_value(argc,argv,++i));
338811be35a1SLionel Sambuc       if( pVfs ){
338911be35a1SLionel Sambuc         sqlite3_vfs_register(pVfs, 1);
339011be35a1SLionel Sambuc       }else{
339111be35a1SLionel Sambuc         fprintf(stderr, "no such VFS: \"%s\"\n", argv[i]);
339211be35a1SLionel Sambuc         exit(1);
339311be35a1SLionel Sambuc       }
339411be35a1SLionel Sambuc     }
339511be35a1SLionel Sambuc   }
3396*0a6a1f1dSLionel Sambuc   if( data.zDbFilename==0 ){
339711be35a1SLionel Sambuc #ifndef SQLITE_OMIT_MEMORYDB
339811be35a1SLionel Sambuc     data.zDbFilename = ":memory:";
339911be35a1SLionel Sambuc #else
340011be35a1SLionel Sambuc     fprintf(stderr,"%s: Error: no database filename specified\n", Argv0);
340111be35a1SLionel Sambuc     return 1;
340211be35a1SLionel Sambuc #endif
3403*0a6a1f1dSLionel Sambuc   }
3404*0a6a1f1dSLionel Sambuc   data.out = stdout;
340511be35a1SLionel Sambuc 
340611be35a1SLionel Sambuc   /* Go ahead and open the database file if it already exists.  If the
340711be35a1SLionel Sambuc   ** file does not exist, delay opening it.  This prevents empty database
340811be35a1SLionel Sambuc   ** files from being created if a user mistypes the database name argument
340911be35a1SLionel Sambuc   ** to the sqlite command-line tool.
341011be35a1SLionel Sambuc   */
341111be35a1SLionel Sambuc   if( access(data.zDbFilename, 0)==0 ){
3412*0a6a1f1dSLionel Sambuc     open_db(&data, 0);
341311be35a1SLionel Sambuc   }
341411be35a1SLionel Sambuc 
341511be35a1SLionel Sambuc   /* Process the initialization file if there is one.  If no -init option
341611be35a1SLionel Sambuc   ** is given on the command line, look for a file named ~/.sqliterc and
341711be35a1SLionel Sambuc   ** try to process it.
341811be35a1SLionel Sambuc   */
341911be35a1SLionel Sambuc   rc = process_sqliterc(&data,zInitFile);
342011be35a1SLionel Sambuc   if( rc>0 ){
342111be35a1SLionel Sambuc     return rc;
342211be35a1SLionel Sambuc   }
342311be35a1SLionel Sambuc 
342411be35a1SLionel Sambuc   /* Make a second pass through the command-line argument and set
342511be35a1SLionel Sambuc   ** options.  This second pass is delayed until after the initialization
342611be35a1SLionel Sambuc   ** file is processed so that the command-line arguments will override
342711be35a1SLionel Sambuc   ** settings in the initialization file.
342811be35a1SLionel Sambuc   */
3429*0a6a1f1dSLionel Sambuc   for(i=1; i<argc; i++){
343011be35a1SLionel Sambuc     char *z = argv[i];
3431*0a6a1f1dSLionel Sambuc     if( z[0]!='-' ) continue;
343211be35a1SLionel Sambuc     if( z[1]=='-' ){ z++; }
343311be35a1SLionel Sambuc     if( strcmp(z,"-init")==0 ){
343411be35a1SLionel Sambuc       i++;
343511be35a1SLionel Sambuc     }else if( strcmp(z,"-html")==0 ){
343611be35a1SLionel Sambuc       data.mode = MODE_Html;
343711be35a1SLionel Sambuc     }else if( strcmp(z,"-list")==0 ){
343811be35a1SLionel Sambuc       data.mode = MODE_List;
343911be35a1SLionel Sambuc     }else if( strcmp(z,"-line")==0 ){
344011be35a1SLionel Sambuc       data.mode = MODE_Line;
344111be35a1SLionel Sambuc     }else if( strcmp(z,"-column")==0 ){
344211be35a1SLionel Sambuc       data.mode = MODE_Column;
344311be35a1SLionel Sambuc     }else if( strcmp(z,"-csv")==0 ){
344411be35a1SLionel Sambuc       data.mode = MODE_Csv;
344511be35a1SLionel Sambuc       memcpy(data.separator,",",2);
344611be35a1SLionel Sambuc     }else if( strcmp(z,"-separator")==0 ){
344711be35a1SLionel Sambuc       sqlite3_snprintf(sizeof(data.separator), data.separator,
3448*0a6a1f1dSLionel Sambuc                        "%s",cmdline_option_value(argc,argv,++i));
344911be35a1SLionel Sambuc     }else if( strcmp(z,"-nullvalue")==0 ){
345011be35a1SLionel Sambuc       sqlite3_snprintf(sizeof(data.nullvalue), data.nullvalue,
3451*0a6a1f1dSLionel Sambuc                        "%s",cmdline_option_value(argc,argv,++i));
345211be35a1SLionel Sambuc     }else if( strcmp(z,"-header")==0 ){
345311be35a1SLionel Sambuc       data.showHeader = 1;
345411be35a1SLionel Sambuc     }else if( strcmp(z,"-noheader")==0 ){
345511be35a1SLionel Sambuc       data.showHeader = 0;
345611be35a1SLionel Sambuc     }else if( strcmp(z,"-echo")==0 ){
345711be35a1SLionel Sambuc       data.echoOn = 1;
345811be35a1SLionel Sambuc     }else if( strcmp(z,"-stats")==0 ){
345911be35a1SLionel Sambuc       data.statsOn = 1;
346011be35a1SLionel Sambuc     }else if( strcmp(z,"-bail")==0 ){
346111be35a1SLionel Sambuc       bail_on_error = 1;
346211be35a1SLionel Sambuc     }else if( strcmp(z,"-version")==0 ){
346311be35a1SLionel Sambuc       printf("%s %s\n", sqlite3_libversion(), sqlite3_sourceid());
346411be35a1SLionel Sambuc       return 0;
346511be35a1SLionel Sambuc     }else if( strcmp(z,"-interactive")==0 ){
346611be35a1SLionel Sambuc       stdin_is_interactive = 1;
346711be35a1SLionel Sambuc     }else if( strcmp(z,"-batch")==0 ){
346811be35a1SLionel Sambuc       stdin_is_interactive = 0;
346911be35a1SLionel Sambuc     }else if( strcmp(z,"-heap")==0 ){
347011be35a1SLionel Sambuc       i++;
3471*0a6a1f1dSLionel Sambuc     }else if( strcmp(z,"-mmap")==0 ){
3472*0a6a1f1dSLionel Sambuc       i++;
347311be35a1SLionel Sambuc     }else if( strcmp(z,"-vfs")==0 ){
347411be35a1SLionel Sambuc       i++;
347511be35a1SLionel Sambuc #ifdef SQLITE_ENABLE_VFSTRACE
347611be35a1SLionel Sambuc     }else if( strcmp(z,"-vfstrace")==0 ){
347711be35a1SLionel Sambuc       i++;
347811be35a1SLionel Sambuc #endif
347911be35a1SLionel Sambuc #ifdef SQLITE_ENABLE_MULTIPLEX
348011be35a1SLionel Sambuc     }else if( strcmp(z,"-multiplex")==0 ){
348111be35a1SLionel Sambuc       i++;
348211be35a1SLionel Sambuc #endif
3483*0a6a1f1dSLionel Sambuc     }else if( strcmp(z,"-help")==0 ){
348411be35a1SLionel Sambuc       usage(1);
3485*0a6a1f1dSLionel Sambuc     }else if( strcmp(z,"-cmd")==0 ){
3486*0a6a1f1dSLionel Sambuc       if( i==argc-1 ) break;
3487*0a6a1f1dSLionel Sambuc       z = cmdline_option_value(argc,argv,++i);
3488*0a6a1f1dSLionel Sambuc       if( z[0]=='.' ){
3489*0a6a1f1dSLionel Sambuc         rc = do_meta_command(z, &data);
3490*0a6a1f1dSLionel Sambuc         if( rc && bail_on_error ) return rc==2 ? 0 : rc;
3491*0a6a1f1dSLionel Sambuc       }else{
3492*0a6a1f1dSLionel Sambuc         open_db(&data, 0);
3493*0a6a1f1dSLionel Sambuc         rc = shell_exec(data.db, z, shell_callback, &data, &zErrMsg);
3494*0a6a1f1dSLionel Sambuc         if( zErrMsg!=0 ){
3495*0a6a1f1dSLionel Sambuc           fprintf(stderr,"Error: %s\n", zErrMsg);
3496*0a6a1f1dSLionel Sambuc           if( bail_on_error ) return rc!=0 ? rc : 1;
3497*0a6a1f1dSLionel Sambuc         }else if( rc!=0 ){
3498*0a6a1f1dSLionel Sambuc           fprintf(stderr,"Error: unable to process SQL \"%s\"\n", z);
3499*0a6a1f1dSLionel Sambuc           if( bail_on_error ) return rc;
3500*0a6a1f1dSLionel Sambuc         }
3501*0a6a1f1dSLionel Sambuc       }
350211be35a1SLionel Sambuc     }else{
350311be35a1SLionel Sambuc       fprintf(stderr,"%s: Error: unknown option: %s\n", Argv0, z);
350411be35a1SLionel Sambuc       fprintf(stderr,"Use -help for a list of options.\n");
350511be35a1SLionel Sambuc       return 1;
350611be35a1SLionel Sambuc     }
350711be35a1SLionel Sambuc   }
350811be35a1SLionel Sambuc 
350911be35a1SLionel Sambuc   if( zFirstCmd ){
351011be35a1SLionel Sambuc     /* Run just the command that follows the database name
351111be35a1SLionel Sambuc     */
351211be35a1SLionel Sambuc     if( zFirstCmd[0]=='.' ){
351311be35a1SLionel Sambuc       rc = do_meta_command(zFirstCmd, &data);
3514*0a6a1f1dSLionel Sambuc       if( rc==2 ) rc = 0;
351511be35a1SLionel Sambuc     }else{
3516*0a6a1f1dSLionel Sambuc       open_db(&data, 0);
351711be35a1SLionel Sambuc       rc = shell_exec(data.db, zFirstCmd, shell_callback, &data, &zErrMsg);
351811be35a1SLionel Sambuc       if( zErrMsg!=0 ){
351911be35a1SLionel Sambuc         fprintf(stderr,"Error: %s\n", zErrMsg);
352011be35a1SLionel Sambuc         return rc!=0 ? rc : 1;
352111be35a1SLionel Sambuc       }else if( rc!=0 ){
352211be35a1SLionel Sambuc         fprintf(stderr,"Error: unable to process SQL \"%s\"\n", zFirstCmd);
352311be35a1SLionel Sambuc         return rc;
352411be35a1SLionel Sambuc       }
352511be35a1SLionel Sambuc     }
352611be35a1SLionel Sambuc   }else{
352711be35a1SLionel Sambuc     /* Run commands received from standard input
352811be35a1SLionel Sambuc     */
352911be35a1SLionel Sambuc     if( stdin_is_interactive ){
353011be35a1SLionel Sambuc       char *zHome;
353111be35a1SLionel Sambuc       char *zHistory = 0;
353211be35a1SLionel Sambuc       int nHistory;
353311be35a1SLionel Sambuc       printf(
353411be35a1SLionel Sambuc         "SQLite version %s %.19s\n" /*extra-version-info*/
353511be35a1SLionel Sambuc         "Enter \".help\" for instructions\n"
353611be35a1SLionel Sambuc         "Enter SQL statements terminated with a \";\"\n",
353711be35a1SLionel Sambuc         sqlite3_libversion(), sqlite3_sourceid()
353811be35a1SLionel Sambuc       );
353911be35a1SLionel Sambuc       zHome = find_home_dir();
354011be35a1SLionel Sambuc       if( zHome ){
354111be35a1SLionel Sambuc         nHistory = strlen30(zHome) + 20;
354211be35a1SLionel Sambuc         if( (zHistory = malloc(nHistory))!=0 ){
354311be35a1SLionel Sambuc           sqlite3_snprintf(nHistory, zHistory,"%s/.sqlite_history", zHome);
354411be35a1SLionel Sambuc         }
354511be35a1SLionel Sambuc       }
354611be35a1SLionel Sambuc #if defined(HAVE_READLINE) && HAVE_READLINE==1
354711be35a1SLionel Sambuc       if( zHistory ) read_history(zHistory);
354811be35a1SLionel Sambuc #endif
354911be35a1SLionel Sambuc       rc = process_input(&data, 0);
355011be35a1SLionel Sambuc       if( zHistory ){
355111be35a1SLionel Sambuc         stifle_history(100);
355211be35a1SLionel Sambuc         write_history(zHistory);
355311be35a1SLionel Sambuc         free(zHistory);
355411be35a1SLionel Sambuc       }
355511be35a1SLionel Sambuc     }else{
355611be35a1SLionel Sambuc       rc = process_input(&data, stdin);
355711be35a1SLionel Sambuc     }
355811be35a1SLionel Sambuc   }
355911be35a1SLionel Sambuc   set_table_name(&data, 0);
356011be35a1SLionel Sambuc   if( data.db ){
356111be35a1SLionel Sambuc     sqlite3_close(data.db);
356211be35a1SLionel Sambuc   }
3563*0a6a1f1dSLionel Sambuc   sqlite3_free(data.zFreeOnClose);
356411be35a1SLionel Sambuc   return rc;
356511be35a1SLionel Sambuc }
3566