/ Check-in [3baa04cf]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Command-line shell enhancements. Bail out when errors are seen in non-interactive mode. Override isatty() using -interactive or -batch command-line options. Report line number in error messages. Tickets #2009, #2045. (CVS 3490)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 3baa04cfb91039e27f642f6f78ef761b5770cb08
User & Date: drh 2006-10-26 14:25:58
Context
2006-10-26
18:15
Bring CVS output into more commonly accepted practice. Tickets #2030, #1573. Add command-line options -bail and ".bail" commands. Default behavior is to continue after encountering an error. Ticket #2045. (CVS 3491) check-in: 517712d6 user: drh tags: trunk
14:25
Command-line shell enhancements. Bail out when errors are seen in non-interactive mode. Override isatty() using -interactive or -batch command-line options. Report line number in error messages. Tickets #2009, #2045. (CVS 3490) check-in: 3baa04cf user: drh tags: trunk
00:41
Empty queries should get no results. My recent change ( http://www.sqlite.org/cvstrac/chngview?cn=3486 ) broke test fts2a-5.3. This change should make the expected result more obvious. (CVS 3489) check-in: cde383eb user: shess tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/shell.c.

     8      8   **    May you find forgiveness for yourself and forgive others.
     9      9   **    May you share freely, never taking more than you give.
    10     10   **
    11     11   *************************************************************************
    12     12   ** This file contains code to implement the "sqlite" command line
    13     13   ** utility for accessing SQLite databases.
    14     14   **
    15         -** $Id: shell.c,v 1.150 2006/09/25 13:09:23 drh Exp $
           15  +** $Id: shell.c,v 1.151 2006/10/26 14:25:58 drh Exp $
    16     16   */
    17     17   #include <stdlib.h>
    18     18   #include <string.h>
    19     19   #include <stdio.h>
    20     20   #include <assert.h>
    21     21   #include "sqlite3.h"
    22     22   #include <ctype.h>
................................................................................
    56     56   # include <io.h>
    57     57   #else
    58     58   /* Make sure isatty() has a prototype.
    59     59   */
    60     60   extern int isatty();
    61     61   #endif
    62     62   
           63  +/*
           64  +** Threat stdin as an interactive input if the following variable
           65  +** is true.  Otherwise, assume stdin is connected to a file or pipe.
           66  +*/
           67  +static int stdin_is_interactive = 1;
           68  +
    63     69   /*
    64     70   ** The following is the open SQLite database.  We make a pointer
    65     71   ** to this database a static variable so that it can be accessed
    66     72   ** by the SIGINT handler to interrupt database processing.
    67     73   */
    68     74   static sqlite3 *db = 0;
    69     75   
................................................................................
   180    186       }
   181    187     }
   182    188     zLine = realloc( zLine, n+1 );
   183    189     return zLine;
   184    190   }
   185    191   
   186    192   /*
   187         -** Retrieve a single line of input text.  "isatty" is true if text
   188         -** is coming from a terminal.  In that case, we issue a prompt and
   189         -** attempt to use "readline" for command-line editing.  If "isatty"
   190         -** is false, use "local_getline" instead of "readline" and issue no prompt.
          193  +** Retrieve a single line of input text.
   191    194   **
   192    195   ** zPrior is a string of prior text retrieved.  If not the empty
   193    196   ** string, then issue a continuation prompt.
   194    197   */
   195    198   static char *one_input_line(const char *zPrior, FILE *in){
   196    199     char *zPrompt;
   197    200     char *zResult;
................................................................................
   583    586   ** from malloc(), or a NULL pointer. The string pointed to by zAppend is
   584    587   ** added to zIn, and the result returned in memory obtained from malloc().
   585    588   ** zIn, if it was not NULL, is freed.
   586    589   **
   587    590   ** If the third argument, quote, is not '\0', then it is used as a 
   588    591   ** quote character for zAppend.
   589    592   */
   590         -static char * appendText(char *zIn, char const *zAppend, char quote){
          593  +static char *appendText(char *zIn, char const *zAppend, char quote){
   591    594     int len;
   592    595     int i;
   593    596     int nAppend = strlen(zAppend);
   594    597     int nIn = (zIn?strlen(zIn):0);
   595    598   
   596    599     len = nAppend+nIn+1;
   597    600     if( quote ){
................................................................................
   789    792     ".show                  Show the current values for various settings\n"
   790    793     ".tables ?PATTERN?      List names of tables matching a LIKE pattern\n"
   791    794     ".timeout MS            Try opening locked tables for MS milliseconds\n"
   792    795     ".width NUM NUM ...     Set column widths for \"column\" mode\n"
   793    796   ;
   794    797   
   795    798   /* Forward reference */
   796         -static void process_input(struct callback_data *p, FILE *in);
          799  +static int process_input(struct callback_data *p, FILE *in);
   797    800   
   798    801   /*
   799    802   ** Make sure the database is open.  If it is not, then open it.  If
   800    803   ** the database fails to open, print an error message and exit.
   801    804   */
   802    805   static void open_db(struct callback_data *p){
   803    806     if( p->db==0 ){
................................................................................
   848    851           }
   849    852         }
   850    853       }
   851    854       z[j] = c;
   852    855     }
   853    856     z[j] = 0;
   854    857   }
          858  +
          859  +/*
          860  +** Interpret zArg as a boolean value.  Return either 0 or 1.
          861  +*/
          862  +static int booleanValue(char *zArg){
          863  +  int val = atoi(zArg);
          864  +  int j;
          865  +  for(j=0; zArg[j]; j++){
          866  +    zArg[j] = tolower(zArg[j]);
          867  +  }
          868  +  if( strcmp(zArg,"on")==0 ){
          869  +    val = 1;
          870  +  }else if( strcmp(zArg,"yes")==0 ){
          871  +    val = 1;
          872  +  }
          873  +  return val;
          874  +}
   855    875   
   856    876   /*
   857    877   ** If an input line begins with "." then invoke this routine to
   858    878   ** process that line.
   859    879   **
   860    880   ** Return 1 to exit and 0 to continue.
   861    881   */
................................................................................
   953    973         sqlite3_free(zErrMsg);
   954    974       }else{
   955    975         fprintf(p->out, "COMMIT;\n");
   956    976       }
   957    977     }else
   958    978   
   959    979     if( c=='e' && strncmp(azArg[0], "echo", n)==0 && nArg>1 ){
   960         -    int j;
   961         -    char *z = azArg[1];
   962         -    int val = atoi(azArg[1]);
   963         -    for(j=0; z[j]; j++){
   964         -      z[j] = tolower((unsigned char)z[j]);
   965         -    }
   966         -    if( strcmp(z,"on")==0 ){
   967         -      val = 1;
   968         -    }else if( strcmp(z,"yes")==0 ){
   969         -      val = 1;
   970         -    }
   971         -    p->echoOn = val;
          980  +    p->echoOn = booleanValue(azArg[1]);
   972    981     }else
   973    982   
   974    983     if( c=='e' && strncmp(azArg[0], "exit", n)==0 ){
   975    984       rc = 1;
   976    985     }else
   977    986   
   978    987     if( c=='e' && strncmp(azArg[0], "explain", n)==0 ){
   979         -    int j;
   980         -    static char zOne[] = "1";
   981         -    char *z = nArg>=2 ? azArg[1] : zOne;
   982         -    int val = atoi(z);
   983         -    for(j=0; z[j]; j++){
   984         -      z[j] = tolower((unsigned char)z[j]);
   985         -    }
   986         -    if( strcmp(z,"on")==0 ){
   987         -      val = 1;
   988         -    }else if( strcmp(z,"yes")==0 ){
   989         -      val = 1;
   990         -    }
          988  +    int val = nArg>=2 ? booleanValue(azArg[1]) : 1;
   991    989       if(val == 1) {
   992    990         if(!p->explainPrev.valid) {
   993    991           p->explainPrev.valid = 1;
   994    992           p->explainPrev.mode = p->mode;
   995    993           p->explainPrev.showHeader = p->showHeader;
   996    994           memcpy(p->explainPrev.colWidth,p->colWidth,sizeof(p->colWidth));
   997    995         }
................................................................................
  1014   1012         p->explainPrev.valid = 0;
  1015   1013         p->mode = p->explainPrev.mode;
  1016   1014         p->showHeader = p->explainPrev.showHeader;
  1017   1015         memcpy(p->colWidth,p->explainPrev.colWidth,sizeof(p->colWidth));
  1018   1016       }
  1019   1017     }else
  1020   1018   
  1021         -  if( c=='h' && (strncmp(azArg[0], "header", n)==0
  1022         -                 ||
         1019  +  if( c=='h' && (strncmp(azArg[0], "header", n)==0 ||
  1023   1020                    strncmp(azArg[0], "headers", n)==0 )&& nArg>1 ){
  1024         -    int j;
  1025         -    char *z = azArg[1];
  1026         -    int val = atoi(azArg[1]);
  1027         -    for(j=0; z[j]; j++){
  1028         -      z[j] = tolower((unsigned char)z[j]);
  1029         -    }
  1030         -    if( strcmp(z,"on")==0 ){
  1031         -      val = 1;
  1032         -    }else if( strcmp(z,"yes")==0 ){
  1033         -      val = 1;
  1034         -    }
  1035         -    p->showHeader = val;
         1021  +    p->showHeader = booleanValue(azArg[1]);
  1036   1022     }else
  1037   1023   
  1038   1024     if( c=='h' && strncmp(azArg[0], "help", n)==0 ){
  1039   1025       fprintf(stderr,zHelp);
  1040   1026     }else
  1041   1027   
  1042   1028     if( c=='i' && strncmp(azArg[0], "import", n)==0 && nArg>=3 ){
................................................................................
  1478   1464   
  1479   1465   /*
  1480   1466   ** Read input from *in and process it.  If *in==0 then input
  1481   1467   ** is interactive - the user is typing it it.  Otherwise, input
  1482   1468   ** is coming from a file or device.  A prompt is issued and history
  1483   1469   ** is saved only if input is interactive.  An interrupt signal will
  1484   1470   ** cause this routine to exit immediately, unless input is interactive.
         1471  +**
         1472  +** Return the number of errors.
  1485   1473   */
  1486         -static void process_input(struct callback_data *p, FILE *in){
         1474  +static int process_input(struct callback_data *p, FILE *in){
  1487   1475     char *zLine;
  1488   1476     char *zSql = 0;
  1489   1477     int nSql = 0;
  1490   1478     char *zErrMsg;
  1491         -  int rc;
         1479  +  int rc = 0;
         1480  +  int lineno = 0;
         1481  +  int startline = 0;
  1492   1482     while( fflush(p->out), (zLine = one_input_line(zSql, in))!=0 ){
  1493   1483       if( seenInterrupt ){
  1494   1484         if( in!=0 ) break;
  1495   1485         seenInterrupt = 0;
  1496   1486       }
         1487  +    if( rc && (in!=0 || !stdin_is_interactive) ){
         1488  +      break;
         1489  +    }
         1490  +    lineno++;
  1497   1491       if( p->echoOn ) printf("%s\n", zLine);
  1498   1492       if( (zSql==0 || zSql[0]==0) && _all_whitespace(zLine) ) continue;
  1499   1493       if( zLine && zLine[0]=='.' && nSql==0 ){
  1500   1494         int rc = do_meta_command(zLine, p);
  1501   1495         free(zLine);
  1502   1496         if( rc ) break;
  1503   1497         continue;
................................................................................
  1512   1506           nSql = strlen(zLine);
  1513   1507           zSql = malloc( nSql+1 );
  1514   1508           if( zSql==0 ){
  1515   1509             fprintf(stderr, "out of memory\n");
  1516   1510             exit(1);
  1517   1511           }
  1518   1512           strcpy(zSql, zLine);
         1513  +        startline = lineno;
  1519   1514         }
  1520   1515       }else{
  1521   1516         int len = strlen(zLine);
  1522   1517         zSql = realloc( zSql, nSql + len + 2 );
  1523   1518         if( zSql==0 ){
  1524   1519           fprintf(stderr,"%s: out of memory!\n", Argv0);
  1525   1520           exit(1);
................................................................................
  1530   1525       }
  1531   1526       free(zLine);
  1532   1527       if( zSql && _ends_with_semicolon(zSql, nSql) && sqlite3_complete(zSql) ){
  1533   1528         p->cnt = 0;
  1534   1529         open_db(p);
  1535   1530         rc = sqlite3_exec(p->db, zSql, callback, p, &zErrMsg);
  1536   1531         if( rc || zErrMsg ){
  1537         -        /* if( in!=0 && !p->echoOn ) printf("%s\n",zSql); */
         1532  +        char zPrefix[100];
         1533  +        if( in!=0 || !stdin_is_interactive ){
         1534  +          sprintf(zPrefix, "SQL error near line %d:", startline);
         1535  +        }else{
         1536  +          sprintf(zPrefix, "SQL error:");
         1537  +        }
  1538   1538           if( zErrMsg!=0 ){
  1539         -          printf("SQL error: %s\n", zErrMsg);
         1539  +          printf("%s %s\n", zPrefix, zErrMsg);
  1540   1540             sqlite3_free(zErrMsg);
  1541   1541             zErrMsg = 0;
  1542   1542           }else{
  1543         -          printf("SQL error: %s\n", sqlite3_errmsg(p->db));
         1543  +          printf("%s %s\n", zPrefix, sqlite3_errmsg(p->db));
  1544   1544           }
  1545   1545         }
  1546   1546         free(zSql);
  1547   1547         zSql = 0;
  1548   1548         nSql = 0;
  1549   1549       }
  1550   1550     }
  1551   1551     if( zSql ){
  1552   1552       if( !_all_whitespace(zSql) ) printf("Incomplete SQL: %s\n", zSql);
  1553   1553       free(zSql);
  1554   1554     }
         1555  +  return rc;
  1555   1556   }
  1556   1557   
  1557   1558   /*
  1558   1559   ** Return a pathname which is the user's home directory.  A
  1559   1560   ** 0 return indicates an error of some kind.  Space to hold the
  1560   1561   ** resulting string is obtained from malloc().  The calling
  1561   1562   ** function should free the result.
................................................................................
  1638   1639       }
  1639   1640       sprintf(zBuf,"%s/.sqliterc",home_dir);
  1640   1641       free(home_dir);
  1641   1642       sqliterc = (const char*)zBuf;
  1642   1643     }
  1643   1644     in = fopen(sqliterc,"rb");
  1644   1645     if( in ){
  1645         -    if( isatty(fileno(stdout)) ){
         1646  +    if( stdin_is_interactive ){
  1646   1647         printf("Loading resources from %s\n",sqliterc);
  1647   1648       }
  1648   1649       process_input(p,in);
  1649   1650       fclose(in);
  1650   1651     }
  1651   1652     free(zBuf);
  1652   1653     return;
................................................................................
  1694   1695   
  1695   1696   int main(int argc, char **argv){
  1696   1697     char *zErrMsg = 0;
  1697   1698     struct callback_data data;
  1698   1699     const char *zInitFile = 0;
  1699   1700     char *zFirstCmd = 0;
  1700   1701     int i;
         1702  +  int rc = 0;
  1701   1703   
  1702   1704   #ifdef __MACOS__
  1703   1705     argc = ccommand(&argv);
  1704   1706   #endif
  1705   1707   
  1706   1708     Argv0 = argv[0];
  1707   1709     main_init(&data);
         1710  +  stdin_is_interactive = isatty(0);
  1708   1711   
  1709   1712     /* Make sure we have a valid signal handler early, before anything
  1710   1713     ** else is done.
  1711   1714     */
  1712   1715   #ifdef SIGINT
  1713   1716     signal(SIGINT, interrupt_handler);
  1714   1717   #endif
  1715   1718   
  1716   1719     /* Do an initial pass through the command-line argument to locate
  1717   1720     ** the name of the database file, the name of the initialization file,
  1718   1721     ** and the first command to execute.
  1719   1722     */
  1720   1723     for(i=1; i<argc-1; i++){
         1724  +    char *z;
  1721   1725       if( argv[i][0]!='-' ) break;
         1726  +    z = argv[i];
         1727  +    if( z[0]=='-' && z[1]=='-' ) z++;
  1722   1728       if( strcmp(argv[i],"-separator")==0 || strcmp(argv[i],"-nullvalue")==0 ){
  1723   1729         i++;
  1724   1730       }else if( strcmp(argv[i],"-init")==0 ){
  1725   1731         i++;
  1726   1732         zInitFile = argv[i];
  1727   1733       }
  1728   1734     }
................................................................................
  1765   1771     /* Make a second pass through the command-line argument and set
  1766   1772     ** options.  This second pass is delayed until after the initialization
  1767   1773     ** file is processed so that the command-line arguments will override
  1768   1774     ** settings in the initialization file.
  1769   1775     */
  1770   1776     for(i=1; i<argc && argv[i][0]=='-'; i++){
  1771   1777       char *z = argv[i];
         1778  +    if( z[1]=='-' ){ z++; }
  1772   1779       if( strcmp(z,"-init")==0 ){
  1773   1780         i++;
  1774   1781       }else if( strcmp(z,"-html")==0 ){
  1775   1782         data.mode = MODE_Html;
  1776   1783       }else if( strcmp(z,"-list")==0 ){
  1777   1784         data.mode = MODE_List;
  1778   1785       }else if( strcmp(z,"-line")==0 ){
................................................................................
  1790   1797       }else if( strcmp(z,"-noheader")==0 ){
  1791   1798         data.showHeader = 0;
  1792   1799       }else if( strcmp(z,"-echo")==0 ){
  1793   1800         data.echoOn = 1;
  1794   1801       }else if( strcmp(z,"-version")==0 ){
  1795   1802         printf("%s\n", sqlite3_libversion());
  1796   1803         return 0;
         1804  +    }else if( strcmp(z,"-interactive")==0 ){
         1805  +      stdin_is_interactive = 1;
         1806  +    }else if( strcmp(z,"-batch")==0 ){
         1807  +      stdin_is_interactive = 0;
  1797   1808       }else if( strcmp(z,"-help")==0 || strcmp(z, "--help")==0 ){
  1798   1809         usage(1);
  1799   1810       }else{
  1800   1811         fprintf(stderr,"%s: unknown option: %s\n", Argv0, z);
  1801   1812         fprintf(stderr,"Use -help for a list of options.\n");
  1802   1813         return 1;
  1803   1814       }
................................................................................
  1817   1828           fprintf(stderr,"SQL error: %s\n", zErrMsg);
  1818   1829           exit(1);
  1819   1830         }
  1820   1831       }
  1821   1832     }else{
  1822   1833       /* Run commands received from standard input
  1823   1834       */
  1824         -    if( isatty(fileno(stdout)) && isatty(fileno(stdin)) ){
         1835  +    if( stdin_is_interactive ){
  1825   1836         char *zHome;
  1826   1837         char *zHistory = 0;
  1827   1838         printf(
  1828   1839           "SQLite version %s\n"
  1829   1840           "Enter \".help\" for instructions\n",
  1830   1841           sqlite3_libversion()
  1831   1842         );
................................................................................
  1832   1843         zHome = find_home_dir();
  1833   1844         if( zHome && (zHistory = malloc(strlen(zHome)+20))!=0 ){
  1834   1845           sprintf(zHistory,"%s/.sqlite_history", zHome);
  1835   1846         }
  1836   1847   #if defined(HAVE_READLINE) && HAVE_READLINE==1
  1837   1848         if( zHistory ) read_history(zHistory);
  1838   1849   #endif
  1839         -      process_input(&data, 0);
         1850  +      rc = process_input(&data, 0);
  1840   1851         if( zHistory ){
  1841   1852           stifle_history(100);
  1842   1853           write_history(zHistory);
  1843   1854           free(zHistory);
  1844   1855         }
  1845   1856         free(zHome);
  1846   1857       }else{
  1847         -      process_input(&data, stdin);
         1858  +      rc = process_input(&data, stdin);
  1848   1859       }
  1849   1860     }
  1850   1861     set_table_name(&data, 0);
  1851   1862     if( db ){
  1852   1863       if( sqlite3_close(db)!=SQLITE_OK ){
  1853   1864         fprintf(stderr,"error closing database: %s\n", sqlite3_errmsg(db));
  1854   1865       }
  1855   1866     }
  1856         -  return 0;
         1867  +  return rc;
  1857   1868   }