/ Check-in [419d286a]
Login
SQLite training in Houston TX on 2019-11-05 (details)
Part of the 2019 Tcl Conference

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

Overview
Comment:Merge the latest trunk changes, and in particular the refactoring of the object names in the command-line shell.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | sessions
Files: files | file ages | folders
SHA1: 419d286a2fc465f6e0f9662909d0cc52a18eefa4
User & Date: drh 2014-08-18 13:48:41
Context
2014-08-18
16:03
Add miscellaneous test cases to improve coverage of sessions module. check-in: 0fac6cff user: dan tags: sessions
15:08
Begin adding commands to the command-line interface for interacting with the sessions extension. This is the first check-in of a work-in-progress. check-in: c2fcf0b9 user: drh tags: sessions_from_cli
13:48
Merge the latest trunk changes, and in particular the refactoring of the object names in the command-line shell. check-in: 419d286a user: drh tags: sessions
13:45
Refactor the names of state objects in the command-line shell implementation.. check-in: 11a70e1a user: drh tags: trunk
08:42
Add tests for sessions module. check-in: 82fdb197 user: dan tags: sessions
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/mutex_w32.c.

    95     95   static int winMutex_isInit = 0;
    96     96   static int winMutex_isNt = -1; /* <0 means "need to query" */
    97     97   
    98     98   /* As the winMutexInit() and winMutexEnd() functions are called as part
    99     99   ** of the sqlite3_initialize() and sqlite3_shutdown() processing, the
   100    100   ** "interlocked" magic used here is probably not strictly necessary.
   101    101   */
   102         -static LONG volatile winMutex_lock = 0;
          102  +static LONG SQLITE_WIN32_VOLATILE winMutex_lock = 0;
   103    103   
   104    104   int sqlite3_win32_is_nt(void); /* os_win.c */
   105    105   void sqlite3_win32_sleep(DWORD milliseconds); /* os_win.c */
   106    106   
   107    107   static int winMutexInit(void){
   108    108     /* The first to increment to 1 does actual initialization */
   109    109     if( InterlockedCompareExchange(&winMutex_lock, 1, 0)==0 ){

Changes to src/os_win.c.

   406    406   ** 1:   Operating system is Win9x.
   407    407   ** 2:   Operating system is WinNT.
   408    408   **
   409    409   ** In order to facilitate testing on a WinNT system, the test fixture
   410    410   ** can manually set this value to 1 to emulate Win98 behavior.
   411    411   */
   412    412   #ifdef SQLITE_TEST
   413         -LONG volatile sqlite3_os_type = 0;
          413  +LONG SQLITE_WIN32_VOLATILE sqlite3_os_type = 0;
   414    414   #else
   415         -static LONG volatile sqlite3_os_type = 0;
          415  +static LONG SQLITE_WIN32_VOLATILE sqlite3_os_type = 0;
   416    416   #endif
   417    417   
   418    418   #ifndef SYSCALL
   419    419   #  define SYSCALL sqlite3_syscall_ptr
   420    420   #endif
   421    421   
   422    422   /*
................................................................................
  1051   1051   #if defined(InterlockedCompareExchange)
  1052   1052     { "InterlockedCompareExchange", (SYSCALL)0,                    0 },
  1053   1053   
  1054   1054   #define osInterlockedCompareExchange InterlockedCompareExchange
  1055   1055   #else
  1056   1056     { "InterlockedCompareExchange", (SYSCALL)InterlockedCompareExchange, 0 },
  1057   1057   
  1058         -#define osInterlockedCompareExchange ((LONG(WINAPI*)(LONG volatile*, \
  1059         -        LONG,LONG))aSyscall[76].pCurrent)
         1058  +#define osInterlockedCompareExchange ((LONG(WINAPI*)(LONG \
         1059  +        SQLITE_WIN32_VOLATILE*, LONG,LONG))aSyscall[76].pCurrent)
  1060   1060   #endif /* defined(InterlockedCompareExchange) */
  1061   1061   
  1062   1062   }; /* End of the overrideable system calls */
  1063   1063   
  1064   1064   /*
  1065   1065   ** This is the xSetSystemCall() method of sqlite3_vfs for all of the
  1066   1066   ** "win32" VFSes.  Return SQLITE_OK opon successfully updating the

Changes to src/os_win.h.

    60     60   ** Determine if we are dealing with WinRT, which provides only a subset of
    61     61   ** the full Win32 API.
    62     62   */
    63     63   #if !defined(SQLITE_OS_WINRT)
    64     64   # define SQLITE_OS_WINRT 0
    65     65   #endif
    66     66   
           67  +/*
           68  +** For WinCE, some API function parameters do not appear to be declared as
           69  +** volatile.
           70  +*/
           71  +#if SQLITE_OS_WINCE
           72  +# define SQLITE_WIN32_VOLATILE
           73  +#else
           74  +# define SQLITE_WIN32_VOLATILE volatile
           75  +#endif
           76  +
    67     77   #endif /* _OS_WIN_H_ */

Changes to src/shell.c.

   428    428       fflush(stdout);
   429    429       zResult = local_getline(zPrior, stdin);
   430    430   #endif
   431    431     }
   432    432     return zResult;
   433    433   }
   434    434   
   435         -struct previous_mode_data {
   436         -  int valid;        /* Is there legit data in here? */
   437         -  int mode;
   438         -  int showHeader;
   439         -  int colWidth[100];
          435  +/*
          436  +** Shell output mode information from before ".explain on", 
          437  +** saved so that it can be restored by ".explain off"
          438  +*/
          439  +typedef struct SavedModeInfo SavedModeInfo;
          440  +struct SavedModeInfo {
          441  +  int valid;          /* Is there legit data in here? */
          442  +  int mode;           /* Mode prior to ".explain on" */
          443  +  int showHeader;     /* The ".header" setting prior to ".explain on" */
          444  +  int colWidth[100];  /* Column widths prior to ".explain on" */
   440    445   };
   441    446   
   442    447   /*
   443         -** An pointer to an instance of this structure is passed from
   444         -** the main program to the callback.  This is used to communicate
   445         -** state and mode information.
          448  +** State information about the database connection is contained in an
          449  +** instance of the following structure.
   446    450   */
   447         -struct callback_data {
          451  +typedef struct ShellState ShellState;
          452  +struct ShellState {
   448    453     sqlite3 *db;           /* The database */
   449    454     int echoOn;            /* True to echo input commands */
   450    455     int autoEQP;           /* Run EXPLAIN QUERY PLAN prior to seach SQL stmt */
   451    456     int statsOn;           /* True to display memory stats before each finalize */
   452    457     int outCount;          /* Revert to stdout when reaching zero */
   453    458     int cnt;               /* Number of records displayed so far */
   454    459     FILE *out;             /* Write results here */
................................................................................
   460    465     char *zDestTable;      /* Name of destination table when MODE_Insert */
   461    466     char separator[20];    /* Separator character for MODE_List */
   462    467     char newline[20];      /* Record separator in MODE_Csv */
   463    468     int colWidth[100];     /* Requested width of each column when in column mode*/
   464    469     int actualWidth[100];  /* Actual width of each column */
   465    470     char nullvalue[20];    /* The text to print when a NULL comes back from
   466    471                            ** the database */
   467         -  struct previous_mode_data explainPrev;
   468         -                         /* Holds the mode information just before
   469         -                         ** .explain ON */
          472  +  SavedModeInfo normalMode;/* Holds the mode just before .explain ON */
   470    473     char outfile[FILENAME_MAX]; /* Filename for *out */
   471    474     const char *zDbFilename;    /* name of the database file */
   472    475     char *zFreeOnClose;         /* Filename to free when closing */
   473    476     const char *zVfs;           /* Name of VFS to use */
   474    477     sqlite3_stmt *pStmt;   /* Current statement if any. */
   475    478     FILE *pLog;            /* Write log output here */
   476    479     int *aiIndent;         /* Array of indents used in MODE_Explain */
................................................................................
   518    521     return 0x3fffffff & (int)(z2 - z);
   519    522   }
   520    523   
   521    524   /*
   522    525   ** A callback for the sqlite3_log() interface.
   523    526   */
   524    527   static void shellLog(void *pArg, int iErrCode, const char *zMsg){
   525         -  struct callback_data *p = (struct callback_data*)pArg;
          528  +  ShellState *p = (ShellState*)pArg;
   526    529     if( p->pLog==0 ) return;
   527    530     fprintf(p->pLog, "(%d) %s\n", iErrCode, zMsg);
   528    531     fflush(p->pLog);
   529    532   }
   530    533   
   531    534   /*
   532    535   ** Output the given string as a hex-encoded blob (eg. X'1234' )
................................................................................
   660    663   
   661    664   /*
   662    665   ** Output a single term of CSV.  Actually, p->separator is used for
   663    666   ** the separator, which may or may not be a comma.  p->nullvalue is
   664    667   ** the null value.  Strings are quoted if necessary.  The separator
   665    668   ** is only issued if bSep is true.
   666    669   */
   667         -static void output_csv(struct callback_data *p, const char *z, int bSep){
          670  +static void output_csv(ShellState *p, const char *z, int bSep){
   668    671     FILE *out = p->out;
   669    672     if( z==0 ){
   670    673       fprintf(out,"%s",p->nullvalue);
   671    674     }else{
   672    675       int i;
   673    676       int nSep = strlen30(p->separator);
   674    677       for(i=0; z[i]; i++){
................................................................................
   709    712   
   710    713   /*
   711    714   ** This is the callback routine that the shell
   712    715   ** invokes for each row of a query result.
   713    716   */
   714    717   static int shell_callback(void *pArg, int nArg, char **azArg, char **azCol, int *aiType){
   715    718     int i;
   716         -  struct callback_data *p = (struct callback_data*)pArg;
          719  +  ShellState *p = (ShellState*)pArg;
   717    720   
   718    721     switch( p->mode ){
   719    722       case MODE_Line: {
   720    723         int w = 5;
   721    724         if( azArg==0 ) break;
   722    725         for(i=0; i<nArg; i++){
   723    726           int len = strlen30(azCol[i] ? azCol[i] : "");
................................................................................
   919    922   */
   920    923   static int callback(void *pArg, int nArg, char **azArg, char **azCol){
   921    924     /* since we don't have type info, call the shell_callback with a NULL value */
   922    925     return shell_callback(pArg, nArg, azArg, azCol, NULL);
   923    926   }
   924    927   
   925    928   /*
   926         -** Set the destination table field of the callback_data structure to
          929  +** Set the destination table field of the ShellState structure to
   927    930   ** the name of the table given.  Escape any quote characters in the
   928    931   ** table name.
   929    932   */
   930         -static void set_table_name(struct callback_data *p, const char *zName){
          933  +static void set_table_name(ShellState *p, const char *zName){
   931    934     int i, n;
   932    935     int needQuote;
   933    936     char *z;
   934    937   
   935    938     if( p->zDestTable ){
   936    939       free(p->zDestTable);
   937    940       p->zDestTable = 0;
................................................................................
  1013   1016   **
  1014   1017   ** If the number of columns is 1 and that column contains text "--"
  1015   1018   ** then write the semicolon on a separate line.  That way, if a 
  1016   1019   ** "--" comment occurs at the end of the statement, the comment
  1017   1020   ** won't consume the semicolon terminator.
  1018   1021   */
  1019   1022   static int run_table_dump_query(
  1020         -  struct callback_data *p, /* Query context */
         1023  +  ShellState *p,           /* Query context */
  1021   1024     const char *zSelect,     /* SELECT statement to extract content */
  1022   1025     const char *zFirstRow    /* Print before first row, if not NULL */
  1023   1026   ){
  1024   1027     sqlite3_stmt *pSelect;
  1025   1028     int rc;
  1026   1029     int nResult;
  1027   1030     int i;
................................................................................
  1076   1079   }
  1077   1080   
  1078   1081   /*
  1079   1082   ** Display memory stats.
  1080   1083   */
  1081   1084   static int display_stats(
  1082   1085     sqlite3 *db,                /* Database to query */
  1083         -  struct callback_data *pArg, /* Pointer to struct callback_data */
         1086  +  ShellState *pArg,           /* Pointer to ShellState */
  1084   1087     int bReset                  /* True to reset the stats */
  1085   1088   ){
  1086   1089     int iCur;
  1087   1090     int iHiwtr;
  1088   1091   
  1089   1092     if( pArg && pArg->out ){
  1090   1093       
................................................................................
  1183   1186       if( 0==strcmp(zStr, azArray[i]) ) return 1;
  1184   1187     }
  1185   1188     return 0;
  1186   1189   }
  1187   1190   
  1188   1191   /*
  1189   1192   ** If compiled statement pSql appears to be an EXPLAIN statement, allocate
  1190         -** and populate the callback_data.aiIndent[] array with the number of
         1193  +** and populate the ShellState.aiIndent[] array with the number of
  1191   1194   ** spaces each opcode should be indented before it is output. 
  1192   1195   **
  1193   1196   ** The indenting rules are:
  1194   1197   **
  1195   1198   **     * For each "Next", "Prev", "VNext" or "VPrev" instruction, indent
  1196   1199   **       all opcodes that occur between the p2 jump destination and the opcode
  1197   1200   **       itself by 2 spaces.
................................................................................
  1199   1202   **     * For each "Goto", if the jump destination is earlier in the program
  1200   1203   **       and ends on one of:
  1201   1204   **          Yield  SeekGt  SeekLt  RowSetRead  Rewind
  1202   1205   **       or if the P1 parameter is one instead of zero,
  1203   1206   **       then indent all opcodes between the earlier instruction
  1204   1207   **       and "Goto" by 2 spaces.
  1205   1208   */
  1206         -static void explain_data_prepare(struct callback_data *p, sqlite3_stmt *pSql){
         1209  +static void explain_data_prepare(ShellState *p, sqlite3_stmt *pSql){
  1207   1210     const char *zSql;               /* The text of the SQL statement */
  1208   1211     const char *z;                  /* Used to check if this is an EXPLAIN */
  1209   1212     int *abYield = 0;               /* True if op is an OP_Yield */
  1210   1213     int nAlloc = 0;                 /* Allocated size of p->aiIndent[], abYield */
  1211   1214     int iOp;                        /* Index of operation in p->aiIndent[] */
  1212   1215   
  1213   1216     const char *azNext[] = { "Next", "Prev", "VPrev", "VNext", "SorterNext",
................................................................................
  1259   1262     sqlite3_free(abYield);
  1260   1263     sqlite3_reset(pSql);
  1261   1264   }
  1262   1265   
  1263   1266   /*
  1264   1267   ** Free the array allocated by explain_data_prepare().
  1265   1268   */
  1266         -static void explain_data_delete(struct callback_data *p){
         1269  +static void explain_data_delete(ShellState *p){
  1267   1270     sqlite3_free(p->aiIndent);
  1268   1271     p->aiIndent = 0;
  1269   1272     p->nIndent = 0;
  1270   1273     p->iIndent = 0;
  1271   1274   }
  1272   1275   
  1273   1276   /*
................................................................................
  1276   1279   ** set via the supplied callback.
  1277   1280   **
  1278   1281   ** This is very similar to SQLite's built-in sqlite3_exec() 
  1279   1282   ** function except it takes a slightly different callback 
  1280   1283   ** and callback data argument.
  1281   1284   */
  1282   1285   static int shell_exec(
  1283         -  sqlite3 *db,                                /* An open database */
  1284         -  const char *zSql,                           /* SQL to be evaluated */
         1286  +  sqlite3 *db,                              /* An open database */
         1287  +  const char *zSql,                         /* SQL to be evaluated */
  1285   1288     int (*xCallback)(void*,int,char**,char**,int*),   /* Callback function */
  1286         -                                              /* (not the same as sqlite3_exec) */
  1287         -  struct callback_data *pArg,                 /* Pointer to struct callback_data */
  1288         -  char **pzErrMsg                             /* Error msg written here */
         1289  +                                            /* (not the same as sqlite3_exec) */
         1290  +  ShellState *pArg,                         /* Pointer to ShellState */
         1291  +  char **pzErrMsg                           /* Error msg written here */
  1289   1292   ){
  1290   1293     sqlite3_stmt *pStmt = NULL;     /* Statement to execute. */
  1291   1294     int rc = SQLITE_OK;             /* Return Code */
  1292   1295     int rc2;
  1293   1296     const char *zLeftover;          /* Tail of unprocessed SQL */
  1294   1297   
  1295   1298     if( pzErrMsg ){
................................................................................
  1449   1452   */
  1450   1453   static int dump_callback(void *pArg, int nArg, char **azArg, char **azCol){
  1451   1454     int rc;
  1452   1455     const char *zTable;
  1453   1456     const char *zType;
  1454   1457     const char *zSql;
  1455   1458     const char *zPrepStmt = 0;
  1456         -  struct callback_data *p = (struct callback_data *)pArg;
         1459  +  ShellState *p = (ShellState *)pArg;
  1457   1460   
  1458   1461     UNUSED_PARAMETER(azCol);
  1459   1462     if( nArg!=3 ) return 1;
  1460   1463     zTable = azArg[0];
  1461   1464     zType = azArg[1];
  1462   1465     zSql = azArg[2];
  1463   1466     
................................................................................
  1545   1548   ** Run zQuery.  Use dump_callback() as the callback routine so that
  1546   1549   ** the contents of the query are output as SQL statements.
  1547   1550   **
  1548   1551   ** If we get a SQLITE_CORRUPT error, rerun the query after appending
  1549   1552   ** "ORDER BY rowid DESC" to the end.
  1550   1553   */
  1551   1554   static int run_schema_dump_query(
  1552         -  struct callback_data *p, 
         1555  +  ShellState *p, 
  1553   1556     const char *zQuery
  1554   1557   ){
  1555   1558     int rc;
  1556   1559     char *zErr = 0;
  1557   1560     rc = sqlite3_exec(p->db, zQuery, dump_callback, p, &zErr);
  1558   1561     if( rc==SQLITE_CORRUPT ){
  1559   1562       char *zQ2;
................................................................................
  1645   1648     ".trace FILE|off        Output each SQL statement as it is run\n"
  1646   1649     ".vfsname ?AUX?         Print the name of the VFS stack\n"
  1647   1650     ".width NUM1 NUM2 ...   Set column widths for \"column\" mode\n"
  1648   1651     "                         Negative values right-justify\n"
  1649   1652   ;
  1650   1653   
  1651   1654   /* Forward reference */
  1652         -static int process_input(struct callback_data *p, FILE *in);
         1655  +static int process_input(ShellState *p, FILE *in);
  1653   1656   /*
  1654   1657   ** Implementation of the "readfile(X)" SQL function.  The entire content
  1655   1658   ** of the file named X is read and returned as a BLOB.  NULL is returned
  1656   1659   ** if the file does not exist or is unreadable.
  1657   1660   */
  1658   1661   static void readfileFunc(
  1659   1662     sqlite3_context *context,
................................................................................
  1711   1714     sqlite3_result_int64(context, rc);
  1712   1715   }
  1713   1716   
  1714   1717   /*
  1715   1718   ** Make sure the database is open.  If it is not, then open it.  If
  1716   1719   ** the database fails to open, print an error message and exit.
  1717   1720   */
  1718         -static void open_db(struct callback_data *p, int keepAlive){
         1721  +static void open_db(ShellState *p, int keepAlive){
  1719   1722     if( p->db==0 ){
  1720   1723       sqlite3_initialize();
  1721   1724       sqlite3_open(p->zDbFilename, &p->db);
  1722   1725       db = p->db;
  1723   1726       if( db && sqlite3_errcode(db)==SQLITE_OK ){
  1724   1727         sqlite3_create_function(db, "shellstatic", 0, SQLITE_UTF8, 0,
  1725   1728             shellstaticFunc, 0, 0);
................................................................................
  2010   2013   
  2011   2014   /*
  2012   2015   ** Try to transfer data for table zTable.  If an error is seen while
  2013   2016   ** moving forward, try to go backwards.  The backwards movement won't
  2014   2017   ** work for WITHOUT ROWID tables.
  2015   2018   */
  2016   2019   static void tryToCloneData(
  2017         -  struct callback_data *p,
         2020  +  ShellState *p,
  2018   2021     sqlite3 *newDb,
  2019   2022     const char *zTable
  2020   2023   ){
  2021   2024     sqlite3_stmt *pQuery = 0; 
  2022   2025     sqlite3_stmt *pInsert = 0;
  2023   2026     char *zQuery = 0;
  2024   2027     char *zInsert = 0;
................................................................................
  2123   2126   /*
  2124   2127   ** Try to transfer all rows of the schema that match zWhere.  For
  2125   2128   ** each row, invoke xForEach() on the object defined by that row.
  2126   2129   ** If an error is encountered while moving forward through the
  2127   2130   ** sqlite_master table, try again moving backwards.
  2128   2131   */
  2129   2132   static void tryToCloneSchema(
  2130         -  struct callback_data *p,
         2133  +  ShellState *p,
  2131   2134     sqlite3 *newDb,
  2132   2135     const char *zWhere,
  2133         -  void (*xForEach)(struct callback_data*,sqlite3*,const char*)
         2136  +  void (*xForEach)(ShellState*,sqlite3*,const char*)
  2134   2137   ){
  2135   2138     sqlite3_stmt *pQuery = 0;
  2136   2139     char *zQuery = 0;
  2137   2140     int rc;
  2138   2141     const unsigned char *zName;
  2139   2142     const unsigned char *zSql;
  2140   2143     char *zErrMsg = 0;
................................................................................
  2197   2200   }
  2198   2201   
  2199   2202   /*
  2200   2203   ** Open a new database file named "zNewDb".  Try to recover as much information
  2201   2204   ** as possible out of the main database (which might be corrupt) and write it
  2202   2205   ** into zNewDb.
  2203   2206   */
  2204         -static void tryToClone(struct callback_data *p, const char *zNewDb){
         2207  +static void tryToClone(ShellState *p, const char *zNewDb){
  2205   2208     int rc;
  2206   2209     sqlite3 *newDb = 0;
  2207   2210     if( access(zNewDb,0)==0 ){
  2208   2211       fprintf(stderr, "File \"%s\" already exists.\n", zNewDb);
  2209   2212       return;
  2210   2213     }
  2211   2214     rc = sqlite3_open(zNewDb, &newDb);
................................................................................
  2222   2225     }
  2223   2226     sqlite3_close(newDb);
  2224   2227   }
  2225   2228   
  2226   2229   /*
  2227   2230   ** Change the output file back to stdout
  2228   2231   */
  2229         -static void output_reset(struct callback_data *p){
         2232  +static void output_reset(ShellState *p){
  2230   2233     if( p->outfile[0]=='|' ){
  2231   2234       pclose(p->out);
  2232   2235     }else{
  2233   2236       output_file_close(p->out);
  2234   2237     }
  2235   2238     p->outfile[0] = 0;
  2236   2239     p->out = stdout;
................................................................................
  2238   2241   
  2239   2242   /*
  2240   2243   ** If an input line begins with "." then invoke this routine to
  2241   2244   ** process that line.
  2242   2245   **
  2243   2246   ** Return 1 on error, 2 to exit, and 0 otherwise.
  2244   2247   */
  2245         -static int do_meta_command(char *zLine, struct callback_data *p){
         2248  +static int do_meta_command(char *zLine, ShellState *p){
  2246   2249     int i = 1;
  2247   2250     int nArg = 0;
  2248   2251     int n, c;
  2249   2252     int rc = 0;
  2250   2253     char *azArg[50];
  2251   2254   
  2252   2255     /* Parse the input line into tokens.
................................................................................
  2356   2359       }else{
  2357   2360         fprintf(stderr, "Usage: .clone FILENAME\n");
  2358   2361         rc = 1;
  2359   2362       }
  2360   2363     }else
  2361   2364   
  2362   2365     if( c=='d' && n>1 && strncmp(azArg[0], "databases", n)==0 ){
  2363         -    struct callback_data data;
         2366  +    ShellState data;
  2364   2367       char *zErrMsg = 0;
  2365   2368       open_db(p, 0);
  2366   2369       memcpy(&data, p, sizeof(data));
  2367   2370       data.showHeader = 1;
  2368   2371       data.mode = MODE_Column;
  2369   2372       data.colWidth[0] = 3;
  2370   2373       data.colWidth[1] = 15;
................................................................................
  2454   2457       if( nArg>1 && (rc = (int)integerValue(azArg[1]))!=0 ) exit(rc);
  2455   2458       rc = 2;
  2456   2459     }else
  2457   2460   
  2458   2461     if( c=='e' && strncmp(azArg[0], "explain", n)==0 ){
  2459   2462       int val = nArg>=2 ? booleanValue(azArg[1]) : 1;
  2460   2463       if(val == 1) {
  2461         -      if(!p->explainPrev.valid) {
  2462         -        p->explainPrev.valid = 1;
  2463         -        p->explainPrev.mode = p->mode;
  2464         -        p->explainPrev.showHeader = p->showHeader;
  2465         -        memcpy(p->explainPrev.colWidth,p->colWidth,sizeof(p->colWidth));
         2464  +      if(!p->normalMode.valid) {
         2465  +        p->normalMode.valid = 1;
         2466  +        p->normalMode.mode = p->mode;
         2467  +        p->normalMode.showHeader = p->showHeader;
         2468  +        memcpy(p->normalMode.colWidth,p->colWidth,sizeof(p->colWidth));
  2466   2469         }
  2467   2470         /* We could put this code under the !p->explainValid
  2468   2471         ** condition so that it does not execute if we are already in
  2469   2472         ** explain mode. However, always executing it allows us an easy
  2470   2473         ** was to reset to explain mode in case the user previously
  2471   2474         ** did an .explain followed by a .width, .mode or .header
  2472   2475         ** command.
................................................................................
  2478   2481         p->colWidth[1] = 13;                 /* opcode */
  2479   2482         p->colWidth[2] = 4;                  /* P1 */
  2480   2483         p->colWidth[3] = 4;                  /* P2 */
  2481   2484         p->colWidth[4] = 4;                  /* P3 */
  2482   2485         p->colWidth[5] = 13;                 /* P4 */
  2483   2486         p->colWidth[6] = 2;                  /* P5 */
  2484   2487         p->colWidth[7] = 13;                  /* Comment */
  2485         -    }else if (p->explainPrev.valid) {
  2486         -      p->explainPrev.valid = 0;
  2487         -      p->mode = p->explainPrev.mode;
  2488         -      p->showHeader = p->explainPrev.showHeader;
  2489         -      memcpy(p->colWidth,p->explainPrev.colWidth,sizeof(p->colWidth));
         2488  +    }else if (p->normalMode.valid) {
         2489  +      p->normalMode.valid = 0;
         2490  +      p->mode = p->normalMode.mode;
         2491  +      p->showHeader = p->normalMode.showHeader;
         2492  +      memcpy(p->colWidth,p->normalMode.colWidth,sizeof(p->colWidth));
  2490   2493       }
  2491   2494     }else
  2492   2495   
  2493   2496     if( c=='f' && strncmp(azArg[0], "fullschema", n)==0 ){
  2494         -    struct callback_data data;
         2497  +    ShellState data;
  2495   2498       char *zErrMsg = 0;
  2496   2499       int doStats = 0;
  2497   2500       if( nArg!=1 ){
  2498   2501         fprintf(stderr, "Usage: .fullschema\n");
  2499   2502         rc = 1;
  2500   2503         goto meta_command_exit;
  2501   2504       }
................................................................................
  2708   2711       xCloser(sCsv.in);
  2709   2712       sqlite3_free(sCsv.z);
  2710   2713       sqlite3_finalize(pStmt);
  2711   2714       if( needCommit ) sqlite3_exec(db, "COMMIT", 0, 0, 0);
  2712   2715     }else
  2713   2716   
  2714   2717     if( c=='i' && strncmp(azArg[0], "indices", n)==0 ){
  2715         -    struct callback_data data;
         2718  +    ShellState data;
  2716   2719       char *zErrMsg = 0;
  2717   2720       open_db(p, 0);
  2718   2721       memcpy(&data, p, sizeof(data));
  2719   2722       data.showHeader = 0;
  2720   2723       data.mode = MODE_List;
  2721   2724       if( nArg==1 ){
  2722   2725         rc = sqlite3_exec(p->db,
................................................................................
  3002   3005         fprintf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
  3003   3006         rc = 1;
  3004   3007       }
  3005   3008       sqlite3_close(pSrc);
  3006   3009     }else
  3007   3010   
  3008   3011     if( c=='s' && strncmp(azArg[0], "schema", n)==0 ){
  3009         -    struct callback_data data;
         3012  +    ShellState data;
  3010   3013       char *zErrMsg = 0;
  3011   3014       open_db(p, 0);
  3012   3015       memcpy(&data, p, sizeof(data));
  3013   3016       data.showHeader = 0;
  3014   3017       data.mode = MODE_Semi;
  3015   3018       if( nArg==2 ){
  3016   3019         int i;
................................................................................
  3144   3147       if( nArg!=1 ){
  3145   3148         fprintf(stderr, "Usage: .show\n");
  3146   3149         rc = 1;
  3147   3150         goto meta_command_exit;
  3148   3151       }
  3149   3152       fprintf(p->out,"%9.9s: %s\n","echo", p->echoOn ? "on" : "off");
  3150   3153       fprintf(p->out,"%9.9s: %s\n","eqp", p->autoEQP ? "on" : "off");
  3151         -    fprintf(p->out,"%9.9s: %s\n","explain", p->explainPrev.valid ? "on" :"off");
         3154  +    fprintf(p->out,"%9.9s: %s\n","explain", p->normalMode.valid ? "on" :"off");
  3152   3155       fprintf(p->out,"%9.9s: %s\n","headers", p->showHeader ? "on" : "off");
  3153   3156       fprintf(p->out,"%9.9s: %s\n","mode", modeDescr[p->mode]);
  3154   3157       fprintf(p->out,"%9.9s: ", "nullvalue");
  3155   3158         output_c_string(p->out, p->nullvalue);
  3156   3159         fprintf(p->out, "\n");
  3157   3160       fprintf(p->out,"%9.9s: %s\n","output",
  3158   3161               strlen30(p->outfile) ? p->outfile : "stdout");
................................................................................
  3536   3539   ** is interactive - the user is typing it it.  Otherwise, input
  3537   3540   ** is coming from a file or device.  A prompt is issued and history
  3538   3541   ** is saved only if input is interactive.  An interrupt signal will
  3539   3542   ** cause this routine to exit immediately, unless input is interactive.
  3540   3543   **
  3541   3544   ** Return the number of errors.
  3542   3545   */
  3543         -static int process_input(struct callback_data *p, FILE *in){
         3546  +static int process_input(ShellState *p, FILE *in){
  3544   3547     char *zLine = 0;          /* A single input line */
  3545   3548     char *zSql = 0;           /* Accumulated SQL text */
  3546   3549     int nLine;                /* Length of current line */
  3547   3550     int nSql = 0;             /* Bytes of zSql[] used */
  3548   3551     int nAlloc = 0;           /* Allocated zSql[] space */
  3549   3552     int nSqlPrior = 0;        /* Bytes of zSql[] used by prior line */
  3550   3553     char *zErrMsg;            /* Error message returned */
................................................................................
  3715   3718   /*
  3716   3719   ** Read input from the file given by sqliterc_override.  Or if that
  3717   3720   ** parameter is NULL, take input from ~/.sqliterc
  3718   3721   **
  3719   3722   ** Returns the number of errors.
  3720   3723   */
  3721   3724   static int process_sqliterc(
  3722         -  struct callback_data *p,        /* Configuration data */
         3725  +  ShellState *p,                  /* Configuration data */
  3723   3726     const char *sqliterc_override   /* Name of config file. NULL to use default */
  3724   3727   ){
  3725   3728     char *home_dir = NULL;
  3726   3729     const char *sqliterc = sqliterc_override;
  3727   3730     char *zBuf = 0;
  3728   3731     FILE *in = NULL;
  3729   3732     int rc = 0;
................................................................................
  3798   3801     }
  3799   3802     exit(1);
  3800   3803   }
  3801   3804   
  3802   3805   /*
  3803   3806   ** Initialize the state information in data
  3804   3807   */
  3805         -static void main_init(struct callback_data *data) {
         3808  +static void main_init(ShellState *data) {
  3806   3809     memset(data, 0, sizeof(*data));
  3807   3810     data->mode = MODE_List;
  3808   3811     memcpy(data->separator,"|", 2);
  3809   3812     memcpy(data->newline,"\r\n", 3);
  3810   3813     data->showHeader = 0;
  3811   3814     sqlite3_config(SQLITE_CONFIG_URI, 1);
  3812   3815     sqlite3_config(SQLITE_CONFIG_LOG, shellLog, data);
................................................................................
  3846   3849       exit(1);
  3847   3850     }
  3848   3851     return argv[i];
  3849   3852   }
  3850   3853   
  3851   3854   int main(int argc, char **argv){
  3852   3855     char *zErrMsg = 0;
  3853         -  struct callback_data data;
         3856  +  ShellState data;
  3854   3857     const char *zInitFile = 0;
  3855   3858     char *zFirstCmd = 0;
  3856   3859     int i;
  3857   3860     int rc = 0;
  3858   3861     int warnInmemoryDb = 0;
  3859   3862   
  3860   3863   #if USE_SYSTEM_SQLITE+0!=1