3166 lines · 95.3 KB · C
RawDownload
/*** 2001 September 15**** The author disclaims copyright to this source code.  In place of** a legal notice, here is a blessing:****    May you do good and not evil.**    May you find forgiveness for yourself and forgive others.**    May you share freely, never taking more than you give. RUSAGE_SELF***************************************************************************** This file contains code to implement the "sqlite" command line** utility for accessing SQLite databases.*/#if (defined(_WIN32) || defined(WIN32)) && !defined(_CRT_SECURE_NO_WARNINGS)/* This needs to come before any includes for MSVC compiler */#define _CRT_SECURE_NO_WARNINGS#endif /*** Enable large-file support for fopen() and friends on unix.*/#ifndef SQLITE_DISABLE_LFS# define _LARGE_FILE       1# ifndef _FILE_OFFSET_BITS#   define _FILE_OFFSET_BITS 64# endif# define _LARGEFILE_SOURCE 1#endif #include <stdlib.h>#include <string.h>#include <stdio.h>#include <assert.h>#include "sqlite3.h"#include <ctype.h>#include <stdarg.h> #if !defined(_WIN32) && !defined(WIN32)# include <signal.h># if !defined(__RTP__) && !defined(_WRS_KERNEL)#  include <pwd.h># endif# include <unistd.h># include <sys/types.h>#endif #ifdef HAVE_EDITLINE/* changed to reflect modern header structure */# include <editline/readline.h># include <histedit.h>#endif/*#if defined(HAVE_READLINE) && HAVE_READLINE==1# include <readline/readline.h># include <readline/history.h>#endif */#if !defined(HAVE_EDITLINE) && (!defined(HAVE_READLINE) || HAVE_READLINE!=1)# define readline(p) local_getline(p,stdin,0)# define add_history(X)# define read_history(X)# define write_history(X)# define stifle_history(X)#endif #if defined(_WIN32) || defined(WIN32)# include <io.h>#define isatty(h) _isatty(h)#define access(f,m) _access((f),(m))#undef popen#define popen(a,b) _popen((a),(b))#undef pclose#define pclose(x) _pclose(x)#else/* Make sure isatty() has a prototype.*/extern int isatty(int);#endif #if defined(_WIN32_WCE)/* Windows CE (arm-wince-mingw32ce-gcc) does not provide isatty() * thus we always assume that we have a console. That can be * overridden with the -batch command line option. */#define isatty(x) 1#endif /* True if the timer is enabled */static int enableTimer = 0; /* ctype macros that work with signed characters */#define IsSpace(X)  isspace((unsigned char)X)#define IsDigit(X)  isdigit((unsigned char)X)#define ToLower(X)  (char)tolower((unsigned char)X) #if !defined(_WIN32) && !defined(WIN32) && !defined(_WRS_KERNEL) && !defined(PLAN9)#include <sys/time.h>#include <sys/resource.h> /* Saved resource information for the beginning of an operation */static struct rusage sBegin; /*** Begin timing an operation*/static void beginTimer(void){  if( enableTimer ){    getrusage(RUSAGE_SELF, &sBegin);  }} /* Return the difference of two time_structs in seconds */static double timeDiff(struct timeval *pStart, struct timeval *pEnd){  return (pEnd->tv_usec - pStart->tv_usec)*0.000001 +          (double)(pEnd->tv_sec - pStart->tv_sec);} /*** Print the timing results.*/static void endTimer(void){  if( enableTimer ){    struct rusage sEnd;    getrusage(RUSAGE_SELF, &sEnd);    printf("CPU Time: user %f sys %f\n",       timeDiff(&sBegin.ru_utime, &sEnd.ru_utime),       timeDiff(&sBegin.ru_stime, &sEnd.ru_stime));  }} #define BEGIN_TIMER beginTimer()#define END_TIMER endTimer()#define HAS_TIMER 1 #elif (defined(_WIN32) || defined(WIN32)) #include <windows.h> /* Saved resource information for the beginning of an operation */static HANDLE hProcess;static FILETIME ftKernelBegin;static FILETIME ftUserBegin;typedef BOOL (WINAPI *GETPROCTIMES)(HANDLE, LPFILETIME, LPFILETIME, LPFILETIME, LPFILETIME);static GETPROCTIMES getProcessTimesAddr = NULL; /*** Check to see if we have timer support.  Return 1 if necessary** support found (or found previously).*/static int hasTimer(void){  if( getProcessTimesAddr ){    return 1;  } else {    /* GetProcessTimes() isn't supported in WIN95 and some other Windows versions.    ** See if the version we are running on has it, and if it does, save off    ** a pointer to it and the current process handle.    */    hProcess = GetCurrentProcess();    if( hProcess ){      HINSTANCE hinstLib = LoadLibrary(TEXT("Kernel32.dll"));      if( NULL != hinstLib ){        getProcessTimesAddr = (GETPROCTIMES) GetProcAddress(hinstLib, "GetProcessTimes");        if( NULL != getProcessTimesAddr ){          return 1;        }        FreeLibrary(hinstLib);       }    }  }  return 0;} /*** Begin timing an operation*/static void beginTimer(void){  if( enableTimer && getProcessTimesAddr ){    FILETIME ftCreation, ftExit;    getProcessTimesAddr(hProcess, &ftCreation, &ftExit, &ftKernelBegin, &ftUserBegin);  }} /* Return the difference of two FILETIME structs in seconds */static double timeDiff(FILETIME *pStart, FILETIME *pEnd){  sqlite_int64 i64Start = *((sqlite_int64 *) pStart);  sqlite_int64 i64End = *((sqlite_int64 *) pEnd);  return (double) ((i64End - i64Start) / 10000000.0);} /*** Print the timing results.*/static void endTimer(void){  if( enableTimer && getProcessTimesAddr){    FILETIME ftCreation, ftExit, ftKernelEnd, ftUserEnd;    getProcessTimesAddr(hProcess, &ftCreation, &ftExit, &ftKernelEnd, &ftUserEnd);    printf("CPU Time: user %f sys %f\n",       timeDiff(&ftUserBegin, &ftUserEnd),       timeDiff(&ftKernelBegin, &ftKernelEnd));  }} #define BEGIN_TIMER beginTimer()#define END_TIMER endTimer()#define HAS_TIMER hasTimer() #else#define BEGIN_TIMER #define END_TIMER#define HAS_TIMER 0#endif /*** Used to prevent warnings about unused parameters*/#define UNUSED_PARAMETER(x) (void)(x) /*** If the following flag is set, then command execution stops** at an error if we are not interactive.*/static int bail_on_error = 0; /*** Threat stdin as an interactive input if the following variable** is true.  Otherwise, assume stdin is connected to a file or pipe.*/static int stdin_is_interactive = 1; /*** The following is the open SQLite database.  We make a pointer** to this database a static variable so that it can be accessed** by the SIGINT handler to interrupt database processing.*/static sqlite3 *db = 0; /*** True if an interrupt (Control-C) has been received.*/static volatile int seenInterrupt = 0; /*** This is the name of our program. It is set in main(), used** in a number of other places, mostly for error messages.*/static char *Argv0; /*** Prompt strings. Initialized in main. Settable with**   .prompt main continue*/static char mainPrompt[20];     /* First line prompt. default: "sqlite> "*/static char continuePrompt[20]; /* Continuation prompt. default: "   ...> " */ /*** Write I/O traces to the following stream.*/#ifdef SQLITE_ENABLE_IOTRACEstatic FILE *iotrace = 0;#endif /*** This routine works like printf in that its first argument is a** format string and subsequent arguments are values to be substituted** in place of % fields.  The result of formatting this string** is written to iotrace.*/#ifdef SQLITE_ENABLE_IOTRACEstatic void iotracePrintf(const char *zFormat, ...){  va_list ap;  char *z;  if( iotrace==0 ) return;  va_start(ap, zFormat);  z = sqlite3_vmprintf(zFormat, ap);  va_end(ap);  fprintf(iotrace, "%s", z);  sqlite3_free(z);}#endif  /*** Determines if a string is a number of not.*/static int isNumber(const char *z, int *realnum){  if( *z=='-' || *z=='+' ) z++;  if( !IsDigit(*z) ){    return 0;  }  z++;  if( realnum ) *realnum = 0;  while( IsDigit(*z) ){ z++; }  if( *z=='.' ){    z++;    if( !IsDigit(*z) ) return 0;    while( IsDigit(*z) ){ z++; }    if( realnum ) *realnum = 1;  }  if( *z=='e' || *z=='E' ){    z++;    if( *z=='+' || *z=='-' ) z++;    if( !IsDigit(*z) ) return 0;    while( IsDigit(*z) ){ z++; }    if( realnum ) *realnum = 1;  }  return *z==0;} /*** A global char* and an SQL function to access its current value ** from within an SQL statement. This program used to use the ** sqlite_exec_printf() API to substitue a string into an SQL statement.** The correct way to do this with sqlite3 is to use the bind API, but** since the shell is built around the callback paradigm it would be a lot** of work. Instead just use this hack, which is quite harmless.*/static const char *zShellStatic = 0;static void shellstaticFunc(  sqlite3_context *context,  int argc,  sqlite3_value **argv){  assert( 0==argc );  assert( zShellStatic );  UNUSED_PARAMETER(argc);  UNUSED_PARAMETER(argv);  sqlite3_result_text(context, zShellStatic, -1, SQLITE_STATIC);}  /*** This routine reads a line of text from FILE in, stores** the text in memory obtained from malloc() and returns a pointer** to the text.  NULL is returned at end of file, or if malloc()** fails.**** The interface is like "readline" but no command-line editing** is done.*/static char *local_getline(char *zPrompt, FILE *in, int csvFlag){  char *zLine;  int nLine;  int n;  int inQuote = 0;   if( zPrompt && *zPrompt ){    printf("%s",zPrompt);    fflush(stdout);  }  nLine = 100;  zLine = malloc( nLine );  if( zLine==0 ) return 0;  n = 0;  while( 1 ){    if( n+100>nLine ){      nLine = nLine*2 + 100;      zLine = realloc(zLine, nLine);      if( zLine==0 ) return 0;    }    if( fgets(&zLine[n], nLine - n, in)==0 ){      if( n==0 ){        free(zLine);        return 0;      }      zLine[n] = 0;      break;    }    while( zLine[n] ){      if( zLine[n]=='"' ) inQuote = !inQuote;      n++;    }    if( n>0 && zLine[n-1]=='\n' && (!inQuote || !csvFlag) ){      n--;      if( n>0 && zLine[n-1]=='\r' ) n--;      zLine[n] = 0;      break;    }  }  zLine = realloc( zLine, n+1 );  return zLine;} /*** Retrieve a single line of input text.**** zPrior is a string of prior text retrieved.  If not the empty** string, then issue a continuation prompt.*/static char *one_input_line(const char *zPrior, FILE *in){  char *zPrompt;  char *zResult;  if( in!=0 ){    return local_getline(0, in, 0);  }  if( zPrior && zPrior[0] ){    zPrompt = continuePrompt;  }else{    zPrompt = mainPrompt;  }  zResult = readline(zPrompt);#if defined(HAVE_READLINE) && HAVE_READLINE==1  if( zResult && *zResult ) add_history(zResult);#endif  return zResult;} struct previous_mode_data {  int valid;        /* Is there legit data in here? */  int mode;  int showHeader;  int colWidth[100];}; /*** An pointer to an instance of this structure is passed from** the main program to the callback.  This is used to communicate** state and mode information.*/struct callback_data {  sqlite3 *db;           /* The database */  int echoOn;            /* True to echo input commands */  int statsOn;           /* True to display memory stats before each finalize */  int cnt;               /* Number of records displayed so far */  FILE *out;             /* Write results here */  FILE *traceOut;        /* Output for sqlite3_trace() */  int nErr;              /* Number of errors seen */  int mode;              /* An output mode setting */  int writableSchema;    /* True if PRAGMA writable_schema=ON */  int showHeader;        /* True to show column names in List or Column mode */  char *zDestTable;      /* Name of destination table when MODE_Insert */  char separator[20];    /* Separator character for MODE_List */  int colWidth[100];     /* Requested width of each column when in column mode*/  int actualWidth[100];  /* Actual width of each column */  char nullvalue[20];    /* The text to print when a NULL comes back from                         ** the database */  struct previous_mode_data explainPrev;                         /* Holds the mode information just before                         ** .explain ON */  char outfile[FILENAME_MAX]; /* Filename for *out */  const char *zDbFilename;    /* name of the database file */  const char *zVfs;           /* Name of VFS to use */  sqlite3_stmt *pStmt;   /* Current statement if any. */  FILE *pLog;            /* Write log output here */}; /*** These are the allowed modes.*/#define MODE_Line     0  /* One column per line.  Blank line between records */#define MODE_Column   1  /* One record per line in neat columns */#define MODE_List     2  /* One record per line with a separator */#define MODE_Semi     3  /* Same as MODE_List but append ";" to each line */#define MODE_Html     4  /* Generate an XHTML table */#define MODE_Insert   5  /* Generate SQL "insert" statements */#define MODE_Tcl      6  /* Generate ANSI-C or TCL quoted elements */#define MODE_Csv      7  /* Quote strings, numbers are plain */#define MODE_Explain  8  /* Like MODE_Column, but do not truncate data */ static const char *modeDescr[] = {  "line",  "column",  "list",  "semi",  "html",  "insert",  "tcl",  "csv",  "explain",}; /*** Number of elements in an array*/#define ArraySize(X)  (int)(sizeof(X)/sizeof(X[0])) /*** Compute a string length that is limited to what can be stored in** lower 30 bits of a 32-bit signed integer.*/static int strlen30(const char *z){  const char *z2 = z;  while( *z2 ){ z2++; }  return 0x3fffffff & (int)(z2 - z);} /*** A callback for the sqlite3_log() interface.*/static void shellLog(void *pArg, int iErrCode, const char *zMsg){  struct callback_data *p = (struct callback_data*)pArg;  if( p->pLog==0 ) return;  fprintf(p->pLog, "(%d) %s\n", iErrCode, zMsg);  fflush(p->pLog);} /*** Output the given string as a hex-encoded blob (eg. X'1234' )*/static void output_hex_blob(FILE *out, const void *pBlob, int nBlob){  int i;

Lines 1–500 of 3166.