/ Check-in [05c99eb8]
Login

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

Overview
Comment:The shell detects and opens ZIP archives using the zipfile extension.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 05c99eb8cefbb3366b6d4ae91e10aa0c82bdf5ea361f4b3375413783af9167ac
User & Date: drh 2018-01-06 21:46:01
Context
2018-01-07
19:52
Improved comments on the sqlar.c and compress.c extensions that describe the differences between the "zlib format" used by SQLAR, the raw deflate format used by ZIP, and the custom format used by compress.c. No changes to code. check-in: c13415c5 user: drh tags: trunk
2018-01-06
21:46
The shell detects and opens ZIP archives using the zipfile extension. check-in: 05c99eb8 user: drh tags: trunk
19:19
In the shell, include the ".archive" command only if compiling with SQLITE_HAVE_ZLIB. Add ".archive" to the ".help" output. check-in: 366469f5 user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/shell.c.in.

    59     59   #include <stdlib.h>
    60     60   #include <string.h>
    61     61   #include <stdio.h>
    62     62   #include <assert.h>
    63     63   #include "sqlite3.h"
    64     64   typedef sqlite3_int64 i64;
    65     65   typedef sqlite3_uint64 u64;
           66  +typedef unsigned char u8;
    66     67   #if SQLITE_USER_AUTHENTICATION
    67     68   # include "sqlite3userauth.h"
    68     69   #endif
    69     70   #include <ctype.h>
    70     71   #include <stdarg.h>
    71     72   
    72     73   #if !defined(_WIN32) && !defined(WIN32)
................................................................................
   934    935   /*
   935    936   ** State information about the database connection is contained in an
   936    937   ** instance of the following structure.
   937    938   */
   938    939   typedef struct ShellState ShellState;
   939    940   struct ShellState {
   940    941     sqlite3 *db;           /* The database */
   941         -  int autoExplain;       /* Automatically turn on .explain mode */
   942         -  int autoEQP;           /* Run EXPLAIN QUERY PLAN prior to seach SQL stmt */
   943         -  int statsOn;           /* True to display memory stats before each finalize */
   944         -  int scanstatsOn;       /* True to display scan stats before each finalize */
          942  +  u8 autoExplain;        /* Automatically turn on .explain mode */
          943  +  u8 autoEQP;            /* Run EXPLAIN QUERY PLAN prior to seach SQL stmt */
          944  +  u8 statsOn;            /* True to display memory stats before each finalize */
          945  +  u8 scanstatsOn;        /* True to display scan stats before each finalize */
          946  +  u8 openMode;           /* SHELL_OPEN_NORMAL, _APPENDVFS, or _ZIPFILE */
   945    947     int outCount;          /* Revert to stdout when reaching zero */
   946    948     int cnt;               /* Number of records displayed so far */
   947    949     FILE *out;             /* Write results here */
   948    950     FILE *traceOut;        /* Output for sqlite3_trace() */
   949    951     int nErr;              /* Number of errors seen */
   950    952     int mode;              /* An output mode setting */
   951    953     int cMode;             /* temporary output mode for the current query */
................................................................................
   973    975     int iIndent;           /* Index of current op in aiIndent[] */
   974    976   #if defined(SQLITE_ENABLE_SESSION)
   975    977     int nSession;             /* Number of active sessions */
   976    978     OpenSession aSession[4];  /* Array of sessions.  [0] is in focus. */
   977    979   #endif
   978    980     ExpertInfo expert;        /* Valid if previous command was ".expert OPT..." */
   979    981   };
          982  +
   980    983   
   981    984   /* Allowed values for ShellState.autoEQP
   982    985   */
   983    986   #define AUTOEQP_off      0
   984    987   #define AUTOEQP_on       1
   985    988   #define AUTOEQP_trigger  2
   986    989   #define AUTOEQP_full     3
   987    990   
          991  +/* Allowed values for ShellState.openMode
          992  +*/
          993  +#define SHELL_OPEN_UNSPEC     0      /* No open-mode specified */
          994  +#define SHELL_OPEN_NORMAL     1      /* Normal database file */
          995  +#define SHELL_OPEN_APPENDVFS  2      /* Use appendvfs */
          996  +#define SHELL_OPEN_ZIPFILE    3      /* Use the zipfile virtual table */
          997  +
   988    998   /*
   989    999   ** These are the allowed shellFlgs values
   990   1000   */
   991   1001   #define SHFLG_Pagecache      0x00000001 /* The --pagecache option is used */
   992   1002   #define SHFLG_Lookaside      0x00000002 /* Lookaside memory is used */
   993   1003   #define SHFLG_Backslash      0x00000004 /* The --backslash option is used */
   994   1004   #define SHFLG_PreserveRowid  0x00000008 /* .dump preserves rowid values */
................................................................................
  3096   3106     int i;
  3097   3107     for(i=0; i<pSession->nFilter; i++){
  3098   3108       if( sqlite3_strglob(pSession->azFilter[i], zTab)==0 ) return 0;
  3099   3109     }
  3100   3110     return 1;
  3101   3111   }
  3102   3112   #endif
         3113  +
         3114  +/*
         3115  +** Try to deduce the type of file for zName based on its content.  Return
         3116  +** one of the SHELL_OPEN_* constants.
         3117  +*/
         3118  +static int deduceDatabaseType(const char *zName){
         3119  +  FILE *f = fopen(zName, "rb");
         3120  +  size_t n;
         3121  +  int rc = SHELL_OPEN_UNSPEC;
         3122  +  char zBuf[100];
         3123  +  if( f==0 ) return SHELL_OPEN_NORMAL;
         3124  +  fseek(f, -25, SEEK_END);
         3125  +  n = fread(zBuf, 25, 1, f);
         3126  +  if( n==1 && memcmp(zBuf, "Start-Of-SQLite3-", 17)==0 ){
         3127  +    rc = SHELL_OPEN_APPENDVFS;
         3128  +  }else{
         3129  +    fseek(f, -22, SEEK_END);
         3130  +    n = fread(zBuf, 22, 1, f);
         3131  +    if( n==1 && zBuf[0]==0x50 && zBuf[1]==0x4b && zBuf[2]==0x05
         3132  +       && zBuf[3]==0x06 ){
         3133  +      rc = SHELL_OPEN_ZIPFILE;
         3134  +    }
         3135  +  }
         3136  +  fclose(f);
         3137  +  return rc;  
         3138  +}
  3103   3139   
  3104   3140   /*
  3105   3141   ** Make sure the database is open.  If it is not, then open it.  If
  3106   3142   ** the database fails to open, print an error message and exit.
  3107   3143   */
  3108   3144   static void open_db(ShellState *p, int keepAlive){
  3109   3145     if( p->db==0 ){
  3110   3146       sqlite3_initialize();
  3111         -    sqlite3_open(p->zDbFilename, &p->db);
         3147  +    if( p->openMode==SHELL_OPEN_UNSPEC && access(p->zDbFilename,0)==0 ){
         3148  +      p->openMode = deduceDatabaseType(p->zDbFilename);
         3149  +    }
         3150  +    switch( p->openMode ){
         3151  +      case SHELL_OPEN_APPENDVFS: {
         3152  +        sqlite3_open_v2(p->zDbFilename, &p->db, 
         3153  +           SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE, "apndvfs");
         3154  +        break;
         3155  +      }
         3156  +      case SHELL_OPEN_ZIPFILE: {
         3157  +        sqlite3_open(":memory:", &p->db);
         3158  +        break;
         3159  +      }
         3160  +      case SHELL_OPEN_UNSPEC:
         3161  +      case SHELL_OPEN_NORMAL: {
         3162  +        sqlite3_open(p->zDbFilename, &p->db);
         3163  +        break;
         3164  +      }
         3165  +    }
  3112   3166       globalDb = p->db;
  3113   3167       if( p->db==0 || SQLITE_OK!=sqlite3_errcode(p->db) ){
  3114   3168         utf8_printf(stderr,"Error: unable to open database \"%s\": %s\n",
  3115   3169             p->zDbFilename, sqlite3_errmsg(p->db));
  3116   3170         if( keepAlive ) return;
  3117   3171         exit(1);
  3118   3172       }
................................................................................
  3126   3180       sqlite3_zipfile_init(p->db, 0, 0);
  3127   3181       sqlite3_sqlar_init(p->db, 0, 0);
  3128   3182   #endif
  3129   3183       sqlite3_create_function(p->db, "shell_add_schema", 3, SQLITE_UTF8, 0,
  3130   3184                               shellAddSchemaName, 0, 0);
  3131   3185       sqlite3_create_function(p->db, "shell_module_schema", 1, SQLITE_UTF8, 0,
  3132   3186                               shellModuleSchema, 0, 0);
         3187  +    if( p->openMode==SHELL_OPEN_ZIPFILE ){
         3188  +      char *zSql = sqlite3_mprintf(
         3189  +         "CREATE VIRTUAL TABLE zip USING zipfile(%Q);", p->zDbFilename);
         3190  +      sqlite3_exec(p->db, zSql, 0, 0, 0);
         3191  +      sqlite3_free(zSql);
         3192  +    }
  3133   3193     }
  3134   3194   }
  3135   3195   
  3136   3196   #if HAVE_READLINE || HAVE_EDITLINE
  3137   3197   /*
  3138   3198   ** Readline completion callbacks
  3139   3199   */
................................................................................
  6008   6068       /* Close the existing database */
  6009   6069       session_close_all(p);
  6010   6070       sqlite3_close(p->db);
  6011   6071       p->db = 0;
  6012   6072       p->zDbFilename = 0;
  6013   6073       sqlite3_free(p->zFreeOnClose);
  6014   6074       p->zFreeOnClose = 0;
         6075  +    p->openMode = SHELL_OPEN_UNSPEC;
  6015   6076       /* Check for command-line arguments */
  6016   6077       for(iName=1; iName<nArg && azArg[iName][0]=='-'; iName++){
  6017   6078         const char *z = azArg[iName];
  6018   6079         if( optionMatch(z,"new") ){
  6019   6080           newFlag = 1;
         6081  +#ifdef SQLITE_HAVE_ZIP
         6082  +      }else if( optionMatch(z, "zip") ){
         6083  +        p->openMode = SHELL_OPEN_ZIPFILE;
         6084  +#endif
         6085  +      }else if( optionMatch(z, "append") ){
         6086  +        p->openMode = SHELL_OPEN_APPENDVFS;
  6020   6087         }else if( z[0]=='-' ){
  6021   6088           utf8_printf(stderr, "unknown option: %s\n", z);
  6022   6089           rc = 1;
  6023   6090           goto meta_command_exit;
  6024   6091         }
  6025   6092       }
  6026   6093       /* If a filename is specified, try to open it first */
................................................................................
  7933   8000       }else if( strcmp(z,"-line")==0 ){
  7934   8001         data.mode = MODE_Line;
  7935   8002       }else if( strcmp(z,"-column")==0 ){
  7936   8003         data.mode = MODE_Column;
  7937   8004       }else if( strcmp(z,"-csv")==0 ){
  7938   8005         data.mode = MODE_Csv;
  7939   8006         memcpy(data.colSeparator,",",2);
         8007  +#ifdef SQLITE_HAVE_ZIP
         8008  +    }else if( strcmp(z,"-zip")==0 ){
         8009  +      data.openMode = SHELL_OPEN_ZIPFILE;
         8010  +#endif
         8011  +    }else if( strcmp(z,"-append")==0 ){
         8012  +      data.openMode = SHELL_OPEN_APPENDVFS;
  7940   8013       }else if( strcmp(z,"-ascii")==0 ){
  7941   8014         data.mode = MODE_Ascii;
  7942   8015         sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator,
  7943   8016                          SEP_Unit);
  7944   8017         sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator,
  7945   8018                          SEP_Record);
  7946   8019       }else if( strcmp(z,"-separator")==0 ){