Main Page | Directories | File List

shell.c

00001 /*
00002 ** 2001 September 15
00003 **
00004 ** The author disclaims copyright to this source code.  In place of
00005 ** a legal notice, here is a blessing:
00006 **
00007 **    May you do good and not evil.
00008 **    May you find forgiveness for yourself and forgive others.
00009 **    May you share freely, never taking more than you give.
00010 **
00011 *************************************************************************
00012 ** This file contains code to implement the "sqlite" command line
00013 ** utility for accessing SQLite databases.
00014 **
00015 ** $Id: shell.c,v 1.93.2.1 2005/02/16 03:53:11 drh Exp $
00016 */
00017 #include <stdlib.h>
00018 #include <string.h>
00019 #include <stdio.h>
00020 #include "sqlite.h"
00021 #include <ctype.h>
00022 
00023 #if !defined(_WIN32) && !defined(WIN32) && !defined(__MACOS__)
00024 # include <signal.h>
00025 # include <pwd.h>
00026 # include <unistd.h>
00027 # include <sys/types.h>
00028 #endif
00029 
00030 #ifdef __MACOS__
00031 # include <console.h>
00032 # include <signal.h>
00033 # include <unistd.h>
00034 # include <extras.h>
00035 # include <Files.h>
00036 # include <Folders.h>
00037 #endif
00038 
00039 #if defined(HAVE_READLINE) && HAVE_READLINE==1
00040 # include <readline/readline.h>
00041 # include <readline/history.h>
00042 #else
00043 # define readline(p) local_getline(p,stdin)
00044 # define add_history(X)
00045 # define read_history(X)
00046 # define write_history(X)
00047 # define stifle_history(X)
00048 #endif
00049 
00050 /* Make sure isatty() has a prototype.
00051 */
00052 extern int isatty();
00053 
00054 /*
00055 ** The following is the open SQLite database.  We make a pointer
00056 ** to this database a static variable so that it can be accessed
00057 ** by the SIGINT handler to interrupt database processing.
00058 */
00059 static sqlite *db = 0;
00060 
00061 /*
00062 ** True if an interrupt (Control-C) has been received.
00063 */
00064 static int seenInterrupt = 0;
00065 
00066 /*
00067 ** This is the name of our program. It is set in main(), used
00068 ** in a number of other places, mostly for error messages.
00069 */
00070 static char *Argv0;
00071 
00072 /*
00073 ** Prompt strings. Initialized in main. Settable with
00074 **   .prompt main continue
00075 */
00076 static char mainPrompt[20];     /* First line prompt. default: "sqlite> "*/
00077 static char continuePrompt[20]; /* Continuation prompt. default: "   ...> " */
00078 
00079 
00080 /*
00081 ** Determines if a string is a number of not.
00082 */
00083 extern int sqliteIsNumber(const char*);
00084 
00085 /*
00086 ** This routine reads a line of text from standard input, stores
00087 ** the text in memory obtained from malloc() and returns a pointer
00088 ** to the text.  NULL is returned at end of file, or if malloc()
00089 ** fails.
00090 **
00091 ** The interface is like "readline" but no command-line editing
00092 ** is done.
00093 */
00094 static char *local_getline(char *zPrompt, FILE *in){
00095   char *zLine;
00096   int nLine;
00097   int n;
00098   int eol;
00099 
00100   if( zPrompt && *zPrompt ){
00101     printf("%s",zPrompt);
00102     fflush(stdout);
00103   }
00104   nLine = 100;
00105   zLine = malloc( nLine );
00106   if( zLine==0 ) return 0;
00107   n = 0;
00108   eol = 0;
00109   while( !eol ){
00110     if( n+100>nLine ){
00111       nLine = nLine*2 + 100;
00112       zLine = realloc(zLine, nLine);
00113       if( zLine==0 ) return 0;
00114     }
00115     if( fgets(&zLine[n], nLine - n, in)==0 ){
00116       if( n==0 ){
00117         free(zLine);
00118         return 0;
00119       }
00120       zLine[n] = 0;
00121       eol = 1;
00122       break;
00123     }
00124     while( zLine[n] ){ n++; }
00125     if( n>0 && zLine[n-1]=='\n' ){
00126       n--;
00127       zLine[n] = 0;
00128       eol = 1;
00129     }
00130   }
00131   zLine = realloc( zLine, n+1 );
00132   return zLine;
00133 }
00134 
00135 /*
00136 ** Retrieve a single line of input text.  "isatty" is true if text
00137 ** is coming from a terminal.  In that case, we issue a prompt and
00138 ** attempt to use "readline" for command-line editing.  If "isatty"
00139 ** is false, use "local_getline" instead of "readline" and issue no prompt.
00140 **
00141 ** zPrior is a string of prior text retrieved.  If not the empty
00142 ** string, then issue a continuation prompt.
00143 */
00144 static char *one_input_line(const char *zPrior, FILE *in){
00145   char *zPrompt;
00146   char *zResult;
00147   if( in!=0 ){
00148     return local_getline(0, in);
00149   }
00150   if( zPrior && zPrior[0] ){
00151     zPrompt = continuePrompt;
00152   }else{
00153     zPrompt = mainPrompt;
00154   }
00155   zResult = readline(zPrompt);
00156   if( zResult ) add_history(zResult);
00157   return zResult;
00158 }
00159 
00160 struct previous_mode_data {
00161   int valid;        /* Is there legit data in here? */
00162   int mode;
00163   int showHeader;
00164   int colWidth[100];
00165 };
00166 /*
00167 ** An pointer to an instance of this structure is passed from
00168 ** the main program to the callback.  This is used to communicate
00169 ** state and mode information.
00170 */
00171 struct callback_data {
00172   sqlite *db;            /* The database */
00173   int echoOn;            /* True to echo input commands */
00174   int cnt;               /* Number of records displayed so far */
00175   FILE *out;             /* Write results here */
00176   int mode;              /* An output mode setting */
00177   int showHeader;        /* True to show column names in List or Column mode */
00178   char *zDestTable;      /* Name of destination table when MODE_Insert */
00179   char separator[20];    /* Separator character for MODE_List */
00180   int colWidth[100];     /* Requested width of each column when in column mode*/
00181   int actualWidth[100];  /* Actual width of each column */
00182   char nullvalue[20];    /* The text to print when a NULL comes back from
00183                          ** the database */
00184   struct previous_mode_data explainPrev;
00185                          /* Holds the mode information just before
00186                          ** .explain ON */
00187   char outfile[FILENAME_MAX]; /* Filename for *out */
00188   const char *zDbFilename;    /* name of the database file */
00189   char *zKey;                 /* Encryption key */
00190 };
00191 
00192 /*
00193 ** These are the allowed modes.
00194 */
00195 #define MODE_Line     0  /* One column per line.  Blank line between records */
00196 #define MODE_Column   1  /* One record per line in neat columns */
00197 #define MODE_List     2  /* One record per line with a separator */
00198 #define MODE_Semi     3  /* Same as MODE_List but append ";" to each line */
00199 #define MODE_Html     4  /* Generate an XHTML table */
00200 #define MODE_Insert   5  /* Generate SQL "insert" statements */
00201 #define MODE_NUM_OF   6  /* The number of modes (not a mode itself) */
00202 
00203 char *modeDescr[MODE_NUM_OF] = {
00204   "line",
00205   "column",
00206   "list",
00207   "semi",
00208   "html",
00209   "insert"
00210 };
00211 
00212 /*
00213 ** Number of elements in an array
00214 */
00215 #define ArraySize(X)  (sizeof(X)/sizeof(X[0]))
00216 
00217 /*
00218 ** Output the given string as a quoted string using SQL quoting conventions.
00219 */
00220 static void output_quoted_string(FILE *out, const char *z){
00221   int i;
00222   int nSingle = 0;
00223   for(i=0; z[i]; i++){
00224     if( z[i]=='\'' ) nSingle++;
00225   }
00226   if( nSingle==0 ){
00227     fprintf(out,"'%s'",z);
00228   }else{
00229     fprintf(out,"'");
00230     while( *z ){
00231       for(i=0; z[i] && z[i]!='\''; i++){}
00232       if( i==0 ){
00233         fprintf(out,"''");
00234         z++;
00235       }else if( z[i]=='\'' ){
00236         fprintf(out,"%.*s''",i,z);
00237         z += i+1;
00238       }else{
00239         fprintf(out,"%s",z);
00240         break;
00241       }
00242     }
00243     fprintf(out,"'");
00244   }
00245 }
00246 
00247 /*
00248 ** Output the given string with characters that are special to
00249 ** HTML escaped.
00250 */
00251 static void output_html_string(FILE *out, const char *z){
00252   int i;
00253   while( *z ){
00254     for(i=0; z[i] && z[i]!='<' && z[i]!='&'; i++){}
00255     if( i>0 ){
00256       fprintf(out,"%.*s",i,z);
00257     }
00258     if( z[i]=='<' ){
00259       fprintf(out,"&lt;");
00260     }else if( z[i]=='&' ){
00261       fprintf(out,"&amp;");
00262     }else{
00263       break;
00264     }
00265     z += i + 1;
00266   }
00267 }
00268 
00269 /*
00270 ** This routine runs when the user presses Ctrl-C
00271 */
00272 static void interrupt_handler(int NotUsed){
00273   seenInterrupt = 1;
00274   if( db ) sqlite_interrupt(db);
00275 }
00276 
00277 /*
00278 ** This is the callback routine that the SQLite library
00279 ** invokes for each row of a query result.
00280 */
00281 static int callback(void *pArg, int nArg, char **azArg, char **azCol){
00282   int i;
00283   struct callback_data *p = (struct callback_data*)pArg;
00284   switch( p->mode ){
00285     case MODE_Line: {
00286       int w = 5;
00287       if( azArg==0 ) break;
00288       for(i=0; i<nArg; i++){
00289         int len = strlen(azCol[i]);
00290         if( len>w ) w = len;
00291       }
00292       if( p->cnt++>0 ) fprintf(p->out,"\n");
00293       for(i=0; i<nArg; i++){
00294         fprintf(p->out,"%*s = %s\n", w, azCol[i], 
00295                 azArg[i] ? azArg[i] : p->nullvalue);
00296       }
00297       break;
00298     }
00299     case MODE_Column: {
00300       if( p->cnt++==0 ){
00301         for(i=0; i<nArg; i++){
00302           int w, n;
00303           if( i<ArraySize(p->colWidth) ){
00304              w = p->colWidth[i];
00305           }else{
00306              w = 0;
00307           }
00308           if( w<=0 ){
00309             w = strlen(azCol[i] ? azCol[i] : "");
00310             if( w<10 ) w = 10;
00311             n = strlen(azArg && azArg[i] ? azArg[i] : p->nullvalue);
00312             if( w<n ) w = n;
00313           }
00314           if( i<ArraySize(p->actualWidth) ){
00315             p->actualWidth[i] = w;
00316           }
00317           if( p->showHeader ){
00318             fprintf(p->out,"%-*.*s%s",w,w,azCol[i], i==nArg-1 ? "\n": "  ");
00319           }
00320         }
00321         if( p->showHeader ){
00322           for(i=0; i<nArg; i++){
00323             int w;
00324             if( i<ArraySize(p->actualWidth) ){
00325                w = p->actualWidth[i];
00326             }else{
00327                w = 10;
00328             }
00329             fprintf(p->out,"%-*.*s%s",w,w,"-----------------------------------"
00330                    "----------------------------------------------------------",
00331                     i==nArg-1 ? "\n": "  ");
00332           }
00333         }
00334       }
00335       if( azArg==0 ) break;
00336       for(i=0; i<nArg; i++){
00337         int w;
00338         if( i<ArraySize(p->actualWidth) ){
00339            w = p->actualWidth[i];
00340         }else{
00341            w = 10;
00342         }
00343         fprintf(p->out,"%-*.*s%s",w,w,
00344             azArg[i] ? azArg[i] : p->nullvalue, i==nArg-1 ? "\n": "  ");
00345       }
00346       break;
00347     }
00348     case MODE_Semi:
00349     case MODE_List: {
00350       if( p->cnt++==0 && p->showHeader ){
00351         for(i=0; i<nArg; i++){
00352           fprintf(p->out,"%s%s",azCol[i], i==nArg-1 ? "\n" : p->separator);
00353         }
00354       }
00355       if( azArg==0 ) break;
00356       for(i=0; i<nArg; i++){
00357         char *z = azArg[i];
00358         if( z==0 ) z = p->nullvalue;
00359         fprintf(p->out, "%s", z);
00360         if( i<nArg-1 ){
00361           fprintf(p->out, "%s", p->separator);
00362         }else if( p->mode==MODE_Semi ){
00363           fprintf(p->out, ";\n");
00364         }else{
00365           fprintf(p->out, "\n");
00366         }
00367       }
00368       break;
00369     }
00370     case MODE_Html: {
00371       if( p->cnt++==0 && p->showHeader ){
00372         fprintf(p->out,"<TR>");
00373         for(i=0; i<nArg; i++){
00374           fprintf(p->out,"<TH>%s</TH>",azCol[i]);
00375         }
00376         fprintf(p->out,"</TR>\n");
00377       }
00378       if( azArg==0 ) break;
00379       fprintf(p->out,"<TR>");
00380       for(i=0; i<nArg; i++){
00381         fprintf(p->out,"<TD>");
00382         output_html_string(p->out, azArg[i] ? azArg[i] : p->nullvalue);
00383         fprintf(p->out,"</TD>\n");
00384       }
00385       fprintf(p->out,"</TR>\n");
00386       break;
00387     }
00388     case MODE_Insert: {
00389       if( azArg==0 ) break;
00390       fprintf(p->out,"INSERT INTO %s VALUES(",p->zDestTable);
00391       for(i=0; i<nArg; i++){
00392         char *zSep = i>0 ? ",": "";
00393         if( azArg[i]==0 ){
00394           fprintf(p->out,"%sNULL",zSep);
00395         }else if( sqliteIsNumber(azArg[i]) ){
00396           fprintf(p->out,"%s%s",zSep, azArg[i]);
00397         }else{
00398           if( zSep[0] ) fprintf(p->out,"%s",zSep);
00399           output_quoted_string(p->out, azArg[i]);
00400         }
00401       }
00402       fprintf(p->out,");\n");
00403       break;
00404     }
00405   }
00406   return 0;
00407 }
00408 
00409 /*
00410 ** Set the destination table field of the callback_data structure to
00411 ** the name of the table given.  Escape any quote characters in the
00412 ** table name.
00413 */
00414 static void set_table_name(struct callback_data *p, const char *zName){
00415   int i, n;
00416   int needQuote;
00417   char *z;
00418 
00419   if( p->zDestTable ){
00420     free(p->zDestTable);
00421     p->zDestTable = 0;
00422   }
00423   if( zName==0 ) return;
00424   needQuote = !isalpha(*zName) && *zName!='_';
00425   for(i=n=0; zName[i]; i++, n++){
00426     if( !isalnum(zName[i]) && zName[i]!='_' ){
00427       needQuote = 1;
00428       if( zName[i]=='\'' ) n++;
00429     }
00430   }
00431   if( needQuote ) n += 2;
00432   z = p->zDestTable = malloc( n+1 );
00433   if( z==0 ){
00434     fprintf(stderr,"Out of memory!\n");
00435     exit(1);
00436   }
00437   n = 0;
00438   if( needQuote ) z[n++] = '\'';
00439   for(i=0; zName[i]; i++){
00440     z[n++] = zName[i];
00441     if( zName[i]=='\'' ) z[n++] = '\'';
00442   }
00443   if( needQuote ) z[n++] = '\'';
00444   z[n] = 0;
00445 }
00446 
00447 /*
00448 ** This is a different callback routine used for dumping the database.
00449 ** Each row received by this callback consists of a table name,
00450 ** the table type ("index" or "table") and SQL to create the table.
00451 ** This routine should print text sufficient to recreate the table.
00452 */
00453 static int dump_callback(void *pArg, int nArg, char **azArg, char **azCol){
00454   struct callback_data *p = (struct callback_data *)pArg;
00455   if( nArg!=3 ) return 1;
00456   fprintf(p->out, "%s;\n", azArg[2]);
00457   if( strcmp(azArg[1],"table")==0 ){
00458     struct callback_data d2;
00459     d2 = *p;
00460     d2.mode = MODE_Insert;
00461     d2.zDestTable = 0;
00462     set_table_name(&d2, azArg[0]);
00463     sqlite_exec_printf(p->db,
00464        "SELECT * FROM '%q'",
00465        callback, &d2, 0, azArg[0]
00466     );
00467     set_table_name(&d2, 0);
00468   }
00469   return 0;
00470 }
00471 
00472 /*
00473 ** Text of a help message
00474 */
00475 static char zHelp[] =
00476   ".databases             List names and files of attached databases\n"
00477   ".dump ?TABLE? ...      Dump the database in a text format\n"
00478   ".echo ON|OFF           Turn command echo on or off\n"
00479   ".exit                  Exit this program\n"
00480   ".explain ON|OFF        Turn output mode suitable for EXPLAIN on or off.\n"
00481   ".header(s) ON|OFF      Turn display of headers on or off\n"
00482   ".help                  Show this message\n"
00483   ".indices TABLE         Show names of all indices on TABLE\n"
00484   ".mode MODE             Set mode to one of \"line(s)\", \"column(s)\", \n"
00485   "                       \"insert\", \"list\", or \"html\"\n"
00486   ".mode insert TABLE     Generate SQL insert statements for TABLE\n"
00487   ".nullvalue STRING      Print STRING instead of nothing for NULL data\n"
00488   ".output FILENAME       Send output to FILENAME\n"
00489   ".output stdout         Send output to the screen\n"
00490   ".prompt MAIN CONTINUE  Replace the standard prompts\n"
00491   ".quit                  Exit this program\n"
00492   ".read FILENAME         Execute SQL in FILENAME\n"
00493 #ifdef SQLITE_HAS_CODEC
00494   ".rekey OLD NEW NEW     Change the encryption key\n"
00495 #endif
00496   ".schema ?TABLE?        Show the CREATE statements\n"
00497   ".separator STRING      Change separator string for \"list\" mode\n"
00498   ".show                  Show the current values for various settings\n"
00499   ".tables ?PATTERN?      List names of tables matching a pattern\n"
00500   ".timeout MS            Try opening locked tables for MS milliseconds\n"
00501   ".width NUM NUM ...     Set column widths for \"column\" mode\n"
00502 ;
00503 
00504 /* Forward reference */
00505 static void process_input(struct callback_data *p, FILE *in);
00506 
00507 /*
00508 ** Make sure the database is open.  If it is not, then open it.  If
00509 ** the database fails to open, print an error message and exit.
00510 */
00511 static void open_db(struct callback_data *p){
00512   if( p->db==0 ){
00513     char *zErrMsg = 0;
00514 #ifdef SQLITE_HAS_CODEC
00515     int n = p->zKey ? strlen(p->zKey) : 0;
00516     db = p->db = sqlite_open_encrypted(p->zDbFilename, p->zKey, n, 0, &zErrMsg);
00517 #else
00518     db = p->db = sqlite_open(p->zDbFilename, 0, &zErrMsg);
00519 #endif
00520     if( p->db==0 ){
00521       if( zErrMsg ){
00522         fprintf(stderr,"Unable to open database \"%s\": %s\n", 
00523            p->zDbFilename, zErrMsg);
00524       }else{
00525         fprintf(stderr,"Unable to open database %s\n", p->zDbFilename);
00526       }
00527       exit(1);
00528     }
00529   }
00530 }
00531 
00532 /*
00533 ** If an input line begins with "." then invoke this routine to
00534 ** process that line.
00535 **
00536 ** Return 1 to exit and 0 to continue.
00537 */
00538 static int do_meta_command(char *zLine, struct callback_data *p){
00539   int i = 1;
00540   int nArg = 0;
00541   int n, c;
00542   int rc = 0;
00543   char *azArg[50];
00544 
00545   /* Parse the input line into tokens.
00546   */
00547   while( zLine[i] && nArg<ArraySize(azArg) ){
00548     while( isspace(zLine[i]) ){ i++; }
00549     if( zLine[i]==0 ) break;
00550     if( zLine[i]=='\'' || zLine[i]=='"' ){
00551       int delim = zLine[i++];
00552       azArg[nArg++] = &zLine[i];
00553       while( zLine[i] && zLine[i]!=delim ){ i++; }
00554       if( zLine[i]==delim ){
00555         zLine[i++] = 0;
00556       }
00557     }else{
00558       azArg[nArg++] = &zLine[i];
00559       while( zLine[i] && !isspace(zLine[i]) ){ i++; }
00560       if( zLine[i] ) zLine[i++] = 0;
00561     }
00562   }
00563 
00564   /* Process the input line.
00565   */
00566   if( nArg==0 ) return rc;
00567   n = strlen(azArg[0]);
00568   c = azArg[0][0];
00569   if( c=='d' && n>1 && strncmp(azArg[0], "databases", n)==0 ){
00570     struct callback_data data;
00571     char *zErrMsg = 0;
00572     open_db(p);
00573     memcpy(&data, p, sizeof(data));
00574     data.showHeader = 1;
00575     data.mode = MODE_Column;
00576     data.colWidth[0] = 3;
00577     data.colWidth[1] = 15;
00578     data.colWidth[2] = 58;
00579     sqlite_exec(p->db, "PRAGMA database_list; ", callback, &data, &zErrMsg);
00580     if( zErrMsg ){
00581       fprintf(stderr,"Error: %s\n", zErrMsg);
00582       sqlite_freemem(zErrMsg);
00583     }
00584   }else
00585 
00586   if( c=='d' && strncmp(azArg[0], "dump", n)==0 ){
00587     char *zErrMsg = 0;
00588     open_db(p);
00589     fprintf(p->out, "BEGIN TRANSACTION;\n");
00590     if( nArg==1 ){
00591       sqlite_exec(p->db,
00592         "SELECT name, type, sql FROM sqlite_master "
00593         "WHERE type!='meta' AND sql NOT NULL "
00594         "ORDER BY substr(type,2,1), rowid",
00595         dump_callback, p, &zErrMsg
00596       );
00597     }else{
00598       int i;
00599       for(i=1; i<nArg && zErrMsg==0; i++){
00600         sqlite_exec_printf(p->db,
00601           "SELECT name, type, sql FROM sqlite_master "
00602           "WHERE tbl_name LIKE '%q' AND type!='meta' AND sql NOT NULL "
00603           "ORDER BY substr(type,2,1), rowid",
00604           dump_callback, p, &zErrMsg, azArg[i]
00605         );
00606       }
00607     }
00608     if( zErrMsg ){
00609       fprintf(stderr,"Error: %s\n", zErrMsg);
00610       sqlite_freemem(zErrMsg);
00611     }else{
00612       fprintf(p->out, "COMMIT;\n");
00613     }
00614   }else
00615 
00616   if( c=='e' && strncmp(azArg[0], "echo", n)==0 && nArg>1 ){
00617     int j;
00618     char *z = azArg[1];
00619     int val = atoi(azArg[1]);
00620     for(j=0; z[j]; j++){
00621       if( isupper(z[j]) ) z[j] = tolower(z[j]);
00622     }
00623     if( strcmp(z,"on")==0 ){
00624       val = 1;
00625     }else if( strcmp(z,"yes")==0 ){
00626       val = 1;
00627     }
00628     p->echoOn = val;
00629   }else
00630 
00631   if( c=='e' && strncmp(azArg[0], "exit", n)==0 ){
00632     rc = 1;
00633   }else
00634 
00635   if( c=='e' && strncmp(azArg[0], "explain", n)==0 ){
00636     int j;
00637     char *z = nArg>=2 ? azArg[1] : "1";
00638     int val = atoi(z);
00639     for(j=0; z[j]; j++){
00640       if( isupper(z[j]) ) z[j] = tolower(z[j]);
00641     }
00642     if( strcmp(z,"on")==0 ){
00643       val = 1;
00644     }else if( strcmp(z,"yes")==0 ){
00645       val = 1;
00646     }
00647     if(val == 1) {
00648       if(!p->explainPrev.valid) {
00649         p->explainPrev.valid = 1;
00650         p->explainPrev.mode = p->mode;
00651         p->explainPrev.showHeader = p->showHeader;
00652         memcpy(p->explainPrev.colWidth,p->colWidth,sizeof(p->colWidth));
00653       }
00654       /* We could put this code under the !p->explainValid
00655       ** condition so that it does not execute if we are already in
00656       ** explain mode. However, always executing it allows us an easy
00657       ** was to reset to explain mode in case the user previously
00658       ** did an .explain followed by a .width, .mode or .header
00659       ** command.
00660       */
00661       p->mode = MODE_Column;
00662       p->showHeader = 1;
00663       memset(p->colWidth,0,ArraySize(p->colWidth));
00664       p->colWidth[0] = 4;
00665       p->colWidth[1] = 12;
00666       p->colWidth[2] = 10;
00667       p->colWidth[3] = 10;
00668       p->colWidth[4] = 35;
00669     }else if (p->explainPrev.valid) {
00670       p->explainPrev.valid = 0;
00671       p->mode = p->explainPrev.mode;
00672       p->showHeader = p->explainPrev.showHeader;
00673       memcpy(p->colWidth,p->explainPrev.colWidth,sizeof(p->colWidth));
00674     }
00675   }else
00676 
00677   if( c=='h' && (strncmp(azArg[0], "header", n)==0
00678                  ||
00679                  strncmp(azArg[0], "headers", n)==0 )&& nArg>1 ){
00680     int j;
00681     char *z = azArg[1];
00682     int val = atoi(azArg[1]);
00683     for(j=0; z[j]; j++){
00684       if( isupper(z[j]) ) z[j] = tolower(z[j]);
00685     }
00686     if( strcmp(z,"on")==0 ){
00687       val = 1;
00688     }else if( strcmp(z,"yes")==0 ){
00689       val = 1;
00690     }
00691     p->showHeader = val;
00692   }else
00693 
00694   if( c=='h' && strncmp(azArg[0], "help", n)==0 ){
00695     fprintf(stderr,zHelp);
00696   }else
00697 
00698   if( c=='i' && strncmp(azArg[0], "indices", n)==0 && nArg>1 ){
00699     struct callback_data data;
00700     char *zErrMsg = 0;
00701     open_db(p);
00702     memcpy(&data, p, sizeof(data));
00703     data.showHeader = 0;
00704     data.mode = MODE_List;
00705     sqlite_exec_printf(p->db,
00706       "SELECT name FROM sqlite_master "
00707       "WHERE type='index' AND tbl_name LIKE '%q' "
00708       "UNION ALL "
00709       "SELECT name FROM sqlite_temp_master "
00710       "WHERE type='index' AND tbl_name LIKE '%q' "
00711       "ORDER BY 1",
00712       callback, &data, &zErrMsg, azArg[1], azArg[1]
00713     );
00714     if( zErrMsg ){
00715       fprintf(stderr,"Error: %s\n", zErrMsg);
00716       sqlite_freemem(zErrMsg);
00717     }
00718   }else
00719 
00720   if( c=='m' && strncmp(azArg[0], "mode", n)==0 && nArg>=2 ){
00721     int n2 = strlen(azArg[1]);
00722     if( strncmp(azArg[1],"line",n2)==0
00723         ||
00724         strncmp(azArg[1],"lines",n2)==0 ){
00725       p->mode = MODE_Line;
00726     }else if( strncmp(azArg[1],"column",n2)==0
00727               ||
00728               strncmp(azArg[1],"columns",n2)==0 ){
00729       p->mode = MODE_Column;
00730     }else if( strncmp(azArg[1],"list",n2)==0 ){
00731       p->mode = MODE_List;
00732     }else if( strncmp(azArg[1],"html",n2)==0 ){
00733       p->mode = MODE_Html;
00734     }else if( strncmp(azArg[1],"insert",n2)==0 ){
00735       p->mode = MODE_Insert;
00736       if( nArg>=3 ){
00737         set_table_name(p, azArg[2]);
00738       }else{
00739         set_table_name(p, "table");
00740       }
00741     }else {
00742       fprintf(stderr,"mode should be on of: column html insert line list\n");
00743     }
00744   }else
00745 
00746   if( c=='n' && strncmp(azArg[0], "nullvalue", n)==0 && nArg==2 ) {
00747     sprintf(p->nullvalue, "%.*s", (int)ArraySize(p->nullvalue)-1, azArg[1]);
00748   }else
00749 
00750   if( c=='o' && strncmp(azArg[0], "output", n)==0 && nArg==2 ){
00751     if( p->out!=stdout ){
00752       fclose(p->out);
00753     }
00754     if( strcmp(azArg[1],"stdout")==0 ){
00755       p->out = stdout;
00756       strcpy(p->outfile,"stdout");
00757     }else{
00758       p->out = fopen(azArg[1], "wb");
00759       if( p->out==0 ){
00760         fprintf(stderr,"can't write to \"%s\"\n", azArg[1]);
00761         p->out = stdout;
00762       } else {
00763          strcpy(p->outfile,azArg[1]);
00764       }
00765     }
00766   }else
00767 
00768   if( c=='p' && strncmp(azArg[0], "prompt", n)==0 && (nArg==2 || nArg==3)){
00769     if( nArg >= 2) {
00770       strncpy(mainPrompt,azArg[1],(int)ArraySize(mainPrompt)-1);
00771     }
00772     if( nArg >= 3) {
00773       strncpy(continuePrompt,azArg[2],(int)ArraySize(continuePrompt)-1);
00774     }
00775   }else
00776 
00777   if( c=='q' && strncmp(azArg[0], "quit", n)==0 ){
00778     rc = 1;
00779   }else
00780 
00781   if( c=='r' && strncmp(azArg[0], "read", n)==0 && nArg==2 ){
00782     FILE *alt = fopen(azArg[1], "rb");
00783     if( alt==0 ){
00784       fprintf(stderr,"can't open \"%s\"\n", azArg[1]);
00785     }else{
00786       process_input(p, alt);
00787       fclose(alt);
00788     }
00789   }else
00790 
00791 #ifdef SQLITE_HAS_CODEC
00792   if( c=='r' && strncmp(azArg[0],"rekey", n)==0 && nArg==4 ){
00793     char *zOld = p->zKey;
00794     if( zOld==0 ) zOld = "";
00795     if( strcmp(azArg[1],zOld) ){
00796       fprintf(stderr,"old key is incorrect\n");
00797     }else if( strcmp(azArg[2], azArg[3]) ){
00798       fprintf(stderr,"2nd copy of new key does not match the 1st\n");
00799     }else{
00800       sqlite_freemem(p->zKey);
00801       p->zKey = sqlite_mprintf("%s", azArg[2]);
00802       sqlite_rekey(p->db, p->zKey, strlen(p->zKey));
00803     }
00804   }else
00805 #endif
00806 
00807   if( c=='s' && strncmp(azArg[0], "schema", n)==0 ){
00808     struct callback_data data;
00809     char *zErrMsg = 0;
00810     open_db(p);
00811     memcpy(&data, p, sizeof(data));
00812     data.showHeader = 0;
00813     data.mode = MODE_Semi;
00814     if( nArg>1 ){
00815       extern int sqliteStrICmp(const char*,const char*);
00816       if( sqliteStrICmp(azArg[1],"sqlite_master")==0 ){
00817         char *new_argv[2], *new_colv[2];
00818         new_argv[0] = "CREATE TABLE sqlite_master (\n"
00819                       "  type text,\n"
00820                       "  name text,\n"
00821                       "  tbl_name text,\n"
00822                       "  rootpage integer,\n"
00823                       "  sql text\n"
00824                       ")";
00825         new_argv[1] = 0;
00826         new_colv[0] = "sql";
00827         new_colv[1] = 0;
00828         callback(&data, 1, new_argv, new_colv);
00829       }else if( sqliteStrICmp(azArg[1],"sqlite_temp_master")==0 ){
00830         char *new_argv[2], *new_colv[2];
00831         new_argv[0] = "CREATE TEMP TABLE sqlite_temp_master (\n"
00832                       "  type text,\n"
00833                       "  name text,\n"
00834                       "  tbl_name text,\n"
00835                       "  rootpage integer,\n"
00836                       "  sql text\n"
00837                       ")";
00838         new_argv[1] = 0;
00839         new_colv[0] = "sql";
00840         new_colv[1] = 0;
00841         callback(&data, 1, new_argv, new_colv);
00842       }else{
00843         sqlite_exec_printf(p->db,
00844           "SELECT sql FROM "
00845           "  (SELECT * FROM sqlite_master UNION ALL"
00846           "   SELECT * FROM sqlite_temp_master) "
00847           "WHERE tbl_name LIKE '%q' AND type!='meta' AND sql NOTNULL "
00848           "ORDER BY substr(type,2,1), name",
00849           callback, &data, &zErrMsg, azArg[1]);
00850       }
00851     }else{
00852       sqlite_exec(p->db,
00853          "SELECT sql FROM "
00854          "  (SELECT * FROM sqlite_master UNION ALL"
00855          "   SELECT * FROM sqlite_temp_master) "
00856          "WHERE type!='meta' AND sql NOTNULL "
00857          "ORDER BY substr(type,2,1), name",
00858          callback, &data, &zErrMsg
00859       );
00860     }
00861     if( zErrMsg ){
00862       fprintf(stderr,"Error: %s\n", zErrMsg);
00863       sqlite_freemem(zErrMsg);
00864     }
00865   }else
00866 
00867   if( c=='s' && strncmp(azArg[0], "separator", n)==0 && nArg==2 ){
00868     sprintf(p->separator, "%.*s", (int)ArraySize(p->separator)-1, azArg[1]);
00869   }else
00870 
00871   if( c=='s' && strncmp(azArg[0], "show", n)==0){
00872     int i;
00873     fprintf(p->out,"%9.9s: %s\n","echo", p->echoOn ? "on" : "off");
00874     fprintf(p->out,"%9.9s: %s\n","explain", p->explainPrev.valid ? "on" :"off");
00875     fprintf(p->out,"%9.9s: %s\n","headers", p->showHeader ? "on" : "off");
00876     fprintf(p->out,"%9.9s: %s\n","mode", modeDescr[p->mode]);
00877     fprintf(p->out,"%9.9s: %s\n","nullvalue", p->nullvalue);
00878     fprintf(p->out,"%9.9s: %s\n","output",
00879                                  strlen(p->outfile) ? p->outfile : "stdout");
00880     fprintf(p->out,"%9.9s: %s\n","separator", p->separator);
00881     fprintf(p->out,"%9.9s: ","width");
00882     for (i=0;i<(int)ArraySize(p->colWidth) && p->colWidth[i] != 0;i++) {
00883         fprintf(p->out,"%d ",p->colWidth[i]);
00884     }
00885     fprintf(p->out,"\n\n");
00886   }else
00887 
00888   if( c=='t' && n>1 && strncmp(azArg[0], "tables", n)==0 ){
00889     char **azResult;
00890     int nRow, rc;
00891     char *zErrMsg;
00892     open_db(p);
00893     if( nArg==1 ){
00894       rc = sqlite_get_table(p->db,
00895         "SELECT name FROM sqlite_master "
00896         "WHERE type IN ('table','view') "
00897         "UNION ALL "
00898         "SELECT name FROM sqlite_temp_master "
00899         "WHERE type IN ('table','view') "
00900         "ORDER BY 1",
00901         &azResult, &nRow, 0, &zErrMsg
00902       );
00903     }else{
00904       rc = sqlite_get_table_printf(p->db,
00905         "SELECT name FROM sqlite_master "
00906         "WHERE type IN ('table','view') AND name LIKE '%%%q%%' "
00907         "UNION ALL "
00908         "SELECT name FROM sqlite_temp_master "
00909         "WHERE type IN ('table','view') AND name LIKE '%%%q%%' "
00910         "ORDER BY 1",
00911         &azResult, &nRow, 0, &zErrMsg, azArg[1], azArg[1]
00912       );
00913     }
00914     if( zErrMsg ){
00915       fprintf(stderr,"Error: %s\n", zErrMsg);
00916       sqlite_freemem(zErrMsg);
00917     }
00918     if( rc==SQLITE_OK ){
00919       int len, maxlen = 0;
00920       int i, j;
00921       int nPrintCol, nPrintRow;
00922       for(i=1; i<=nRow; i++){
00923         if( azResult[i]==0 ) continue;
00924         len = strlen(azResult[i]);
00925         if( len>maxlen ) maxlen = len;
00926       }
00927       nPrintCol = 80/(maxlen+2);
00928       if( nPrintCol<1 ) nPrintCol = 1;
00929       nPrintRow = (nRow + nPrintCol - 1)/nPrintCol;
00930       for(i=0; i<nPrintRow; i++){
00931         for(j=i+1; j<=nRow; j+=nPrintRow){
00932           char *zSp = j<=nPrintRow ? "" : "  ";
00933           printf("%s%-*s", zSp, maxlen, azResult[j] ? azResult[j] : "");
00934         }
00935         printf("\n");
00936       }
00937     }
00938     sqlite_free_table(azResult);
00939   }else
00940 
00941   if( c=='t' && n>1 && strncmp(azArg[0], "timeout", n)==0 && nArg>=2 ){
00942     open_db(p);
00943     sqlite_busy_timeout(p->db, atoi(azArg[1]));
00944   }else
00945 
00946   if( c=='w' && strncmp(azArg[0], "width", n)==0 ){
00947     int j;
00948     for(j=1; j<nArg && j<ArraySize(p->colWidth); j++){
00949       p->colWidth[j-1] = atoi(azArg[j]);
00950     }
00951   }else
00952 
00953   {
00954     fprintf(stderr, "unknown command or invalid arguments: "
00955       " \"%s\". Enter \".help\" for help\n", azArg[0]);
00956   }
00957 
00958   return rc;
00959 }
00960 
00961 /*
00962 ** Return TRUE if the last non-whitespace character in z[] is a semicolon.
00963 ** z[] is N characters long.
00964 */
00965 static int _ends_with_semicolon(const char *z, int N){
00966   while( N>0 && isspace(z[N-1]) ){ N--; }
00967   return N>0 && z[N-1]==';';
00968 }
00969 
00970 /*
00971 ** Test to see if a line consists entirely of whitespace.
00972 */
00973 static int _all_whitespace(const char *z){
00974   for(; *z; z++){
00975     if( isspace(*z) ) continue;
00976     if( *z=='/' && z[1]=='*' ){
00977       z += 2;
00978       while( *z && (*z!='*' || z[1]!='/') ){ z++; }
00979       if( *z==0 ) return 0;
00980       z++;
00981       continue;
00982     }
00983     if( *z=='-' && z[1]=='-' ){
00984       z += 2;
00985       while( *z && *z!='\n' ){ z++; }
00986       if( *z==0 ) return 1;
00987       continue;
00988     }
00989     return 0;
00990   }
00991   return 1;
00992 }
00993 
00994 /*
00995 ** Return TRUE if the line typed in is an SQL command terminator other
00996 ** than a semi-colon.  The SQL Server style "go" command is understood
00997 ** as is the Oracle "/".
00998 */
00999 static int _is_command_terminator(const char *zLine){
01000   extern int sqliteStrNICmp(const char*,const char*,int);
01001   while( isspace(*zLine) ){ zLine++; };
01002   if( zLine[0]=='/' && _all_whitespace(&zLine[1]) ) return 1;  /* Oracle */
01003   if( sqliteStrNICmp(zLine,"go",2)==0 && _all_whitespace(&zLine[2]) ){
01004     return 1;  /* SQL Server */
01005   }
01006   return 0;
01007 }
01008 
01009 /*
01010 ** Read input from *in and process it.  If *in==0 then input
01011 ** is interactive - the user is typing it it.  Otherwise, input
01012 ** is coming from a file or device.  A prompt is issued and history
01013 ** is saved only if input is interactive.  An interrupt signal will
01014 ** cause this routine to exit immediately, unless input is interactive.
01015 */
01016 static void process_input(struct callback_data *p, FILE *in){
01017   char *zLine;
01018   char *zSql = 0;
01019   int nSql = 0;
01020   char *zErrMsg;
01021   int rc;
01022   while( fflush(p->out), (zLine = one_input_line(zSql, in))!=0 ){
01023     if( seenInterrupt ){
01024       if( in!=0 ) break;
01025       seenInterrupt = 0;
01026     }
01027     if( p->echoOn ) printf("%s\n", zLine);
01028     if( (zSql==0 || zSql[0]==0) && _all_whitespace(zLine) ) continue;
01029     if( zLine && zLine[0]=='.' && nSql==0 ){
01030       int rc = do_meta_command(zLine, p);
01031       free(zLine);
01032       if( rc ) break;
01033       continue;
01034     }
01035     if( _is_command_terminator(zLine) ){
01036       strcpy(zLine,";");
01037     }
01038     if( zSql==0 ){
01039       int i;
01040       for(i=0; zLine[i] && isspace(zLine[i]); i++){}
01041       if( zLine[i]!=0 ){
01042         nSql = strlen(zLine);
01043         zSql = malloc( nSql+1 );
01044         strcpy(zSql, zLine);
01045       }
01046     }else{
01047       int len = strlen(zLine);
01048       zSql = realloc( zSql, nSql + len + 2 );
01049       if( zSql==0 ){
01050         fprintf(stderr,"%s: out of memory!\n", Argv0);
01051         exit(1);
01052       }
01053       strcpy(&zSql[nSql++], "\n");
01054       strcpy(&zSql[nSql], zLine);
01055       nSql += len;
01056     }
01057     free(zLine);
01058     if( zSql && _ends_with_semicolon(zSql, nSql) && sqlite_complete(zSql) ){
01059       p->cnt = 0;
01060       open_db(p);
01061       rc = sqlite_exec(p->db, zSql, callback, p, &zErrMsg);
01062       if( rc || zErrMsg ){
01063         if( in!=0 && !p->echoOn ) printf("%s\n",zSql);
01064         if( zErrMsg!=0 ){
01065           printf("SQL error: %s\n", zErrMsg);
01066           sqlite_freemem(zErrMsg);
01067           zErrMsg = 0;
01068         }else{
01069           printf("SQL error: %s\n", sqlite_error_string(rc));
01070         }
01071       }
01072       free(zSql);
01073       zSql = 0;
01074       nSql = 0;
01075     }
01076   }
01077   if( zSql ){
01078     if( !_all_whitespace(zSql) ) printf("Incomplete SQL: %s\n", zSql);
01079     free(zSql);
01080   }
01081 }
01082 
01083 /*
01084 ** Return a pathname which is the user's home directory.  A
01085 ** 0 return indicates an error of some kind.  Space to hold the
01086 ** resulting string is obtained from malloc().  The calling
01087 ** function should free the result.
01088 */
01089 static char *find_home_dir(void){
01090   char *home_dir = NULL;
01091 
01092 #if !defined(_WIN32) && !defined(WIN32) && !defined(__MACOS__)
01093   struct passwd *pwent;
01094   uid_t uid = getuid();
01095   if( (pwent=getpwuid(uid)) != NULL) {
01096     home_dir = pwent->pw_dir;
01097   }
01098 #endif
01099 
01100 #ifdef __MACOS__
01101   char home_path[_MAX_PATH+1];
01102   home_dir = getcwd(home_path, _MAX_PATH);
01103 #endif
01104 
01105   if (!home_dir) {
01106     home_dir = getenv("HOME");
01107     if (!home_dir) {
01108       home_dir = getenv("HOMEPATH"); /* Windows? */
01109     }
01110   }
01111 
01112 #if defined(_WIN32) || defined(WIN32)
01113   if (!home_dir) {
01114     home_dir = "c:";
01115   }
01116 #endif
01117 
01118   if( home_dir ){
01119     char *z = malloc( strlen(home_dir)+1 );
01120     if( z ) strcpy(z, home_dir);
01121     home_dir = z;
01122   }
01123 
01124   return home_dir;
01125 }
01126 
01127 /*
01128 ** Read input from the file given by sqliterc_override.  Or if that
01129 ** parameter is NULL, take input from ~/.sqliterc
01130 */
01131 static void process_sqliterc(
01132   struct callback_data *p,        /* Configuration data */
01133   const char *sqliterc_override   /* Name of config file. NULL to use default */
01134 ){
01135   char *home_dir = NULL;
01136   const char *sqliterc = sqliterc_override;
01137   char *zBuf;
01138   FILE *in = NULL;
01139 
01140   if (sqliterc == NULL) {
01141     home_dir = find_home_dir();
01142     if( home_dir==0 ){
01143       fprintf(stderr,"%s: cannot locate your home directory!\n", Argv0);
01144       return;
01145     }
01146     zBuf = malloc(strlen(home_dir) + 15);
01147     if( zBuf==0 ){
01148       fprintf(stderr,"%s: out of memory!\n", Argv0);
01149       exit(1);
01150     }
01151     sprintf(zBuf,"%s/.sqliterc",home_dir);
01152     free(home_dir);
01153     sqliterc = (const char*)zBuf;
01154   }
01155   in = fopen(sqliterc,"rb");
01156   if( in ){
01157     if( isatty(fileno(stdout)) ){
01158       printf("Loading resources from %s\n",sqliterc);
01159     }
01160     process_input(p,in);
01161     fclose(in);
01162   }
01163   return;
01164 }
01165 
01166 /*
01167 ** Show available command line options
01168 */
01169 static const char zOptions[] = 
01170   "   -init filename       read/process named file\n"
01171   "   -echo                print commands before execution\n"
01172   "   -[no]header          turn headers on or off\n"
01173   "   -column              set output mode to 'column'\n"
01174   "   -html                set output mode to HTML\n"
01175 #ifdef SQLITE_HAS_CODEC
01176   "   -key KEY             encryption key\n"
01177 #endif                 
01178   "   -line                set output mode to 'line'\n"
01179   "   -list                set output mode to 'list'\n"
01180   "   -separator 'x'       set output field separator (|)\n"
01181   "   -nullvalue 'text'    set text string for NULL values\n"
01182   "   -version             show SQLite version\n"
01183   "   -help                show this text, also show dot-commands\n"
01184 ;
01185 static void usage(int showDetail){
01186   fprintf(stderr, "Usage: %s [OPTIONS] FILENAME [SQL]\n", Argv0);
01187   if( showDetail ){
01188     fprintf(stderr, "Options are:\n%s", zOptions);
01189   }else{
01190     fprintf(stderr, "Use the -help option for additional information\n");
01191   }
01192   exit(1);
01193 }
01194 
01195 /*
01196 ** Initialize the state information in data
01197 */
01198 void main_init(struct callback_data *data) {
01199   memset(data, 0, sizeof(*data));
01200   data->mode = MODE_List;
01201   strcpy(data->separator,"|");
01202   data->showHeader = 0;
01203   strcpy(mainPrompt,"sqlite> ");
01204   strcpy(continuePrompt,"   ...> ");
01205 }
01206 
01207 int main(int argc, char **argv){
01208   char *zErrMsg = 0;
01209   struct callback_data data;
01210   const char *zInitFile = 0;
01211   char *zFirstCmd = 0;
01212   int i;
01213   extern int sqliteOsFileExists(const char*);
01214 
01215 #ifdef __MACOS__
01216   argc = ccommand(&argv);
01217 #endif
01218 
01219   Argv0 = argv[0];
01220   main_init(&data);
01221 
01222   /* Make sure we have a valid signal handler early, before anything
01223   ** else is done.
01224   */
01225 #ifdef SIGINT
01226   signal(SIGINT, interrupt_handler);
01227 #endif
01228 
01229   /* Do an initial pass through the command-line argument to locate
01230   ** the name of the database file, the name of the initialization file,
01231   ** and the first command to execute.
01232   */
01233   for(i=1; i<argc-1; i++){
01234     if( argv[i][0]!='-' ) break;
01235     if( strcmp(argv[i],"-separator")==0 || strcmp(argv[i],"-nullvalue")==0 ){
01236       i++;
01237     }else if( strcmp(argv[i],"-init")==0 ){
01238       i++;
01239       zInitFile = argv[i];
01240     }else if( strcmp(argv[i],"-key")==0 ){
01241       i++;
01242       data.zKey = sqlite_mprintf("%s",argv[i]);
01243     }
01244   }
01245   if( i<argc ){
01246     data.zDbFilename = argv[i++];
01247   }else{
01248     data.zDbFilename = ":memory:";
01249   }
01250   if( i<argc ){
01251     zFirstCmd = argv[i++];
01252   }
01253   data.out = stdout;
01254 
01255   /* Go ahead and open the database file if it already exists.  If the
01256   ** file does not exist, delay opening it.  This prevents empty database
01257   ** files from being created if a user mistypes the database name argument
01258   ** to the sqlite command-line tool.
01259   */
01260   if( sqliteOsFileExists(data.zDbFilename) ){
01261     open_db(&data);
01262   }
01263 
01264   /* Process the initialization file if there is one.  If no -init option
01265   ** is given on the command line, look for a file named ~/.sqliterc and
01266   ** try to process it.
01267   */
01268   process_sqliterc(&data,zInitFile);
01269 
01270   /* Make a second pass through the command-line argument and set
01271   ** options.  This second pass is delayed until after the initialization
01272   ** file is processed so that the command-line arguments will override
01273   ** settings in the initialization file.
01274   */
01275   for(i=1; i<argc && argv[i][0]=='-'; i++){
01276     char *z = argv[i];
01277     if( strcmp(z,"-init")==0 || strcmp(z,"-key")==0 ){
01278       i++;
01279     }else if( strcmp(z,"-html")==0 ){
01280       data.mode = MODE_Html;
01281     }else if( strcmp(z,"-list")==0 ){
01282       data.mode = MODE_List;
01283     }else if( strcmp(z,"-line")==0 ){
01284       data.mode = MODE_Line;
01285     }else if( strcmp(z,"-column")==0 ){
01286       data.mode = MODE_Column;
01287     }else if( strcmp(z,"-separator")==0 ){
01288       i++;
01289       sprintf(data.separator,"%.*s",(int)sizeof(data.separator)-1,argv[i]);
01290     }else if( strcmp(z,"-nullvalue")==0 ){
01291       i++;
01292       sprintf(data.nullvalue,"%.*s",(int)sizeof(data.nullvalue)-1,argv[i]);
01293     }else if( strcmp(z,"-header")==0 ){
01294       data.showHeader = 1;
01295     }else if( strcmp(z,"-noheader")==0 ){
01296       data.showHeader = 0;
01297     }else if( strcmp(z,"-echo")==0 ){
01298       data.echoOn = 1;
01299     }else if( strcmp(z,"-version")==0 ){
01300       printf("%s\n", sqlite_version);
01301       return 1;
01302     }else if( strcmp(z,"-help")==0 ){
01303       usage(1);
01304     }else{
01305       fprintf(stderr,"%s: unknown option: %s\n", Argv0, z);
01306       fprintf(stderr,"Use -help for a list of options.\n");
01307       return 1;
01308     }
01309   }
01310 
01311   if( zFirstCmd ){
01312     /* Run just the command that follows the database name
01313     */
01314     if( zFirstCmd[0]=='.' ){
01315       do_meta_command(zFirstCmd, &data);
01316       exit(0);
01317     }else{
01318       int rc;
01319       open_db(&data);
01320       rc = sqlite_exec(data.db, zFirstCmd, callback, &data, &zErrMsg);
01321       if( rc!=0 && zErrMsg!=0 ){
01322         fprintf(stderr,"SQL error: %s\n", zErrMsg);
01323         exit(1);
01324       }
01325     }
01326   }else{
01327     /* Run commands received from standard input
01328     */
01329     if( isatty(fileno(stdout)) && isatty(fileno(stdin)) ){
01330       char *zHome;
01331       char *zHistory = 0;
01332       printf(
01333         "SQLite version %s\n"
01334         "Enter \".help\" for instructions\n",
01335         sqlite_version
01336       );
01337       zHome = find_home_dir();
01338       if( zHome && (zHistory = malloc(strlen(zHome)+20))!=0 ){
01339         sprintf(zHistory,"%s/.sqlite_history", zHome);
01340       }
01341       if( zHistory ) read_history(zHistory);
01342       process_input(&data, 0);
01343       if( zHistory ){
01344         stifle_history(100);
01345         write_history(zHistory);
01346       }
01347     }else{
01348       process_input(&data, stdin);
01349     }
01350   }
01351   set_table_name(&data, 0);
01352   if( db ) sqlite_close(db);
01353   return 0;
01354 }

Generated on Sun Dec 25 12:29:52 2005 for sqlite 2.8.17 by  doxygen 1.4.2