]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
The ".ar" command deduces whether or not the target file is
authordrh <drh@noemail.net>
Wed, 10 Jan 2018 15:17:34 +0000 (15:17 +0000)
committerdrh <drh@noemail.net>
Wed, 10 Jan 2018 15:17:34 +0000 (15:17 +0000)
a ZIP or SQLAR and does the appropropriate thing.  The "-z" option is omitted.
The "--append" option is added to open auxiliary databases using apndvfs.

FossilOrigin-Name: 430d1a7daa823ae53606b7a158af4e7c16f62ff9b072b90606524e7c3f6131df

manifest
manifest.uuid
src/shell.c.in
test/shell8.test

index 96ab066f1b09eb7c530cbd35400383ad3cc016ba..da3f0596642c824d119d30b7f66964f30c6faed7 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Allow\sthe\suse\sof\s".ar\s-t"\swithout\sspecifying\san\sarchive\sfile\sor\sthe\s"-z"\noption\swhen\sthe\scommand-line\sshell\sis\sopened\son\sa\sZIP\sarchive.
-D 2018-01-10T14:00:00.949
+C The\s".ar"\scommand\sdeduces\swhether\sor\snot\sthe\starget\sfile\sis\na\sZIP\sor\sSQLAR\sand\sdoes\sthe\sappropropriate\sthing.\s\sThe\s"-z"\soption\sis\somitted.\nThe\s"--append"\soption\sis\sadded\sto\sopen\sauxiliary\sdatabases\susing\sapndvfs.
+D 2018-01-10T15:17:34.832
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F Makefile.in 12b6daa4bdb03fa87da27cbc205ff88ace645475b5be79414a3038b68ade14cb
@@ -484,7 +484,7 @@ F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384
 F src/resolve.c bbee7e31d369a18a2f4836644769882e9c5d40ef4a3af911db06410b65cb3730
 F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac
 F src/select.c 8b22abe193e4d8243befa2038e4ae2405802fed1c446e5e502d11f652e09ba74
-F src/shell.c.in aae06c143e7c70cfe616a96af8b5656f3891916beee172c7a40b084dab221b79
+F src/shell.c.in 7d49ed78c6d8298d38d4733c3cc24f3a4230cd2f151564b7c11ab2e280007f9c
 F src/sqlite.h.in 1f1a2da222ec57465794e8984d77f32d0bd0da80cdc136beadda461a0be9d80c
 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
 F src/sqlite3ext.h c02d628cca67f3889c689d82d25c3eb45e2c155db08e4c6089b5840d64687d34
@@ -1225,7 +1225,7 @@ F test/shell4.test 89ad573879a745974ff2df20ff97c5d6ffffbd5d
 F test/shell5.test 23939a4c51f0421330ea61dbd3c74f9c215f5f8d3d1a94846da6ffc777a35458
 F test/shell6.test 1ceb51b2678c472ba6cf1e5da96679ce8347889fe2c3bf93a0e0fa73f00b00d3
 F test/shell7.test 115132f66d0463417f408562cc2cf534f6bbc6d83a6d50f0072a9eb171bae97f
-F test/shell8.test 5a1f2c6d5cc11e7c7d69e960972f447a9b01e80c419ff9ebaf059f94fe5b3ab9
+F test/shell8.test c836470ccde867e1f438a7acad7560805cc04f9dbab84cb55d92925942b76247
 F test/shortread1.test bb591ef20f0fd9ed26d0d12e80eee6d7ac8897a3
 F test/show_speedtest1_rtree.tcl 32e6c5f073d7426148a6936a0408f4b5b169aba5
 F test/shrink.test 1b4330b1fd9e818c04726d45cb28db73087535ce
@@ -1697,7 +1697,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
 F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P a2baada429e84dc4b7243173a056e3c8bc042682f7efb01fdf8d2cc452c97e04
-R 870698cbfc790bad8e7df783afd6e385
+P 9340a2c145bcb4b38d19276a16264a37341c617f0554d66e1da653f1d9f85163
+R 9764fa4832552c458077bab9b9143a51
 U drh
-Z 6cb4ecc388fb1e11ac7a5d118227df45
+Z fa68d24d45da969d4d63bf64e8c4f030
index 94454fbf0db213fb5fa85ab811168351323b02e8..8a5e2767d261acabfe18e4c00222e1befb9008f9 100644 (file)
@@ -1 +1 @@
-9340a2c145bcb4b38d19276a16264a37341c617f0554d66e1da653f1d9f85163
\ No newline at end of file
+430d1a7daa823ae53606b7a158af4e7c16f62ff9b072b90606524e7c3f6131df
\ No newline at end of file
index ad5300336e3fa8a4ac0d64c1f91072d5b7504e7e..83b21b1663cb8c9da5000ea2d56409e9055f137d 100644 (file)
@@ -4505,10 +4505,11 @@ typedef struct ArCommand ArCommand;
 struct ArCommand {
   u8 eCmd;                        /* An AR_CMD_* value */
   u8 bVerbose;                    /* True if --verbose */
-  u8 bZip;                        /* True if --zip */
+  u8 bZip;                        /* True if the archive is a ZIP */
   u8 bDryRun;                     /* True if --dry-run */
+  u8 bAppend;                     /* True if --append */
   int nArg;                       /* Number of command arguments */
-  const char *zSrcTable;          /* "sqlar", "zipfile($file)" or "zip" */
+  char *zSrcTable;                /* "sqlar", "zipfile($file)" or "zip" */
   const char *zFile;              /* --file argument, or NULL */
   const char *zDir;               /* --directory argument, or NULL */
   char **azArg;                   /* Array of command arguments */
@@ -4541,7 +4542,7 @@ static int arUsage(FILE *f){
 "  -f FILE, --file FILE       Operate on archive FILE (default is current db)\n"
 "  -C DIR, --directory DIR    Change to directory DIR to read/extract files\n"
 "  -n, --dryrun               Show the SQL that would have occurred\n"
-"  -z, --zip                  Operate on a ZIP archive instead of an SQLAR\n"
+"  -a, --append               Append the SQLAR to an existing file\n"
 "\n"
 "See also: http://sqlite.org/cli.html#sqlar_archive_support\n"
 "\n"
@@ -4579,7 +4580,7 @@ static int arErrorMsg(const char *zFmt, ...){
 #define AR_SWITCH_VERBOSE     6
 #define AR_SWITCH_FILE        7
 #define AR_SWITCH_DIRECTORY   8
-#define AR_SWITCH_ZIP         9
+#define AR_SWITCH_APPEND      9
 #define AR_SWITCH_DRYRUN     10
 
 static int arProcessSwitch(ArCommand *pAr, int eSwitch, const char *zArg){
@@ -4601,8 +4602,8 @@ static int arProcessSwitch(ArCommand *pAr, int eSwitch, const char *zArg){
     case AR_SWITCH_VERBOSE:
       pAr->bVerbose = 1;
       break;
-    case AR_SWITCH_ZIP:
-      pAr->bZip = 1;
+    case AR_SWITCH_APPEND:
+      pAr->bAppend = 1;
       break;
 
     case AR_SWITCH_FILE:
@@ -4641,7 +4642,7 @@ static int arParseCommand(
     { "verbose",   'v', AR_SWITCH_VERBOSE,   0 },
     { "file",      'f', AR_SWITCH_FILE,      1 },
     { "directory", 'C', AR_SWITCH_DIRECTORY, 1 },
-    { "zip",       'z', AR_SWITCH_ZIP,       0 },
+    { "append",    'a', AR_SWITCH_APPEND,    0 },
     { "dryrun",    'n', AR_SWITCH_DRYRUN,    0 },
   };
   int nSwitch = sizeof(aSwitch) / sizeof(struct ArSwitch);
@@ -4779,11 +4780,6 @@ static int arCheckEntries(ArCommand *pAr){
         "SELECT name FROM %s WHERE name=$name", 
         pAr->zSrcTable
     );
-    if( rc==SQLITE_OK
-     && (j = sqlite3_bind_parameter_index(pTest, "$archiveFile"))>0
-    ){
-      sqlite3_bind_text(pTest, j, pAr->zFile, -1, SQLITE_TRANSIENT);
-    }
     j = sqlite3_bind_parameter_index(pTest, "$name");
     for(i=0; i<pAr->nArg && rc==SQLITE_OK; i++){
       char *z = pAr->azArg[i];
@@ -4882,18 +4878,12 @@ static int arListCommand(ArCommand *pAr){
   char *zWhere = 0;
   sqlite3_stmt *pSql = 0;
   int rc;
-  int j;
 
   rc = arCheckEntries(pAr);
   arWhereClause(&rc, pAr, &zWhere);
 
   shellPreparePrintf(pAr->db, &rc, &pSql, zSql, azCols[pAr->bVerbose],
                      pAr->zSrcTable, zWhere);
-  if( rc==SQLITE_OK 
-   && (j = sqlite3_bind_parameter_index(pSql, "$archiveFile"))>0
-  ){
-    sqlite3_bind_text(pSql, j, pAr->zFile, -1, SQLITE_TRANSIENT);
-  }
   if( pAr->bDryRun ){
     utf8_printf(pAr->p->out, "%s\n", sqlite3_sql(pSql));
   }else{
@@ -4960,10 +4950,6 @@ static int arExtractCommand(ArCommand *pAr){
   if( rc==SQLITE_OK ){
     j = sqlite3_bind_parameter_index(pSql, "$dir");
     sqlite3_bind_text(pSql, j, zDir, -1, SQLITE_STATIC);
-    j = sqlite3_bind_parameter_index(pSql, "$archiveFile");
-    if( j ){
-      sqlite3_bind_text(pSql, j, pAr->zFile, -1, SQLITE_STATIC);
-    }
 
     /* Run the SELECT statement twice. The first time, writefile() is called
     ** for all archive members that should be extracted. The second time,
@@ -5022,7 +5008,7 @@ static int arCreateOrUpdateCommand(
   ArCommand *pAr,                 /* Command arguments and options */
   int bUpdate                     /* true for a --create.  false for --update */
 ){
-  const char *zSql = "SELECT name, mode, mtime, data FROM fsdir(?, ?)";
+  const char *zSql = "SELECT name, mode, mtime, data FROM fsdir($name, $dir)";
   const char *zCreate = 
       "CREATE TABLE IF NOT EXISTS sqlar(\n"
       "  name TEXT PRIMARY KEY,  -- name of the file\n"
@@ -5037,6 +5023,7 @@ static int arCreateOrUpdateCommand(
   sqlite3_stmt *pStmt = 0;        /* Directory traverser */
   sqlite3_stmt *pInsert = 0;      /* Compilation of zInsert */
   int i;                          /* For iterating through azFile[] */
+  int j;                          /* Parameter index */
   int rc;                         /* Return code */
 
   assert( pAr->bZip==0 );
@@ -5050,12 +5037,19 @@ static int arCreateOrUpdateCommand(
   }
 
   rc = arExecSql(pAr, zCreate);
-  shellPrepare(pAr->db, &rc, zInsert, &pInsert);
+  if( !pAr->bDryRun ){
+    shellPrepare(pAr->db, &rc, zInsert, &pInsert);
+  }
   shellPrepare(pAr->db, &rc, zSql, &pStmt);
-  sqlite3_bind_text(pStmt, 2, pAr->zDir, -1, SQLITE_STATIC);
+  j = sqlite3_bind_parameter_index(pStmt, "$dir");
+  sqlite3_bind_text(pStmt, j, pAr->zDir, -1, SQLITE_STATIC);
+  if( pAr->bDryRun ){
+    utf8_printf(pAr->p->out, "%s;\n", sqlite3_sql(pStmt));
+  }
 
   for(i=0; i<pAr->nArg && rc==SQLITE_OK; i++){
-    sqlite3_bind_text(pStmt, 1, pAr->azArg[i], -1, SQLITE_STATIC);
+    j = sqlite3_bind_parameter_index(pStmt, "$name");
+    sqlite3_bind_text(pStmt, j, pAr->azArg[i], -1, SQLITE_STATIC);
     while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
       int sz;
       const char *zName = (const char*)sqlite3_column_text(pStmt, 0);
@@ -5065,6 +5059,10 @@ static int arCreateOrUpdateCommand(
       if( pAr->bVerbose ){
         utf8_printf(pAr->p->out, "%s\n", zName);
       }
+      if( pAr->bDryRun ){
+        utf8_printf(pAr->p->out, "%s;\n", zInsert);
+        continue;
+      }
 
       sqlite3_bind_text(pInsert, 1, zName, -1, SQLITE_STATIC);
       sqlite3_bind_int(pInsert, 2, mode);
@@ -5115,45 +5113,61 @@ static int arDotCommand(
   int rc;
   rc = arParseCommand(azArg, nArg, &cmd);
   if( rc==SQLITE_OK ){
+    int eDbType = SHELL_OPEN_UNSPEC;
     cmd.p = pState;
     cmd.db = pState->db;
-    cmd.zSrcTable = "sqlar";
-    if( cmd.bZip || pState->openMode==SHELL_OPEN_ZIPFILE ){
-      if( cmd.zFile==0
-       && sqlite3_table_column_metadata(cmd.db,0,"zip","name",0,0,0,0,0)==SQLITE_OK
-      ){
-        cmd.zSrcTable = "zip";
-      }else if( cmd.zFile!=0 ){
-        cmd.zSrcTable = "zipfile($archiveFile)";
+    cmd.zSrcTable = 0;
+    if( cmd.zFile ){
+      eDbType = deduceDatabaseType(cmd.zFile);
+    }else{
+      eDbType = pState->openMode;
+    }
+    if( eDbType==SHELL_OPEN_ZIPFILE ){
+      if( cmd.zFile==0 ){
+        cmd.zSrcTable = sqlite3_mprintf("zip");
       }else{
-        utf8_printf(stderr, "no zip archive file specified\n");
-        return SQLITE_ERROR;
+        cmd.zSrcTable = sqlite3_mprintf("zipfile(%Q)", cmd.zFile);
       }
       if( cmd.eCmd==AR_CMD_CREATE || cmd.eCmd==AR_CMD_UPDATE ){
         utf8_printf(stderr, "zip archives are read-only\n");
-        return SQLITE_ERROR;
+        rc = SQLITE_ERROR;
+        goto end_ar_command;
       }
+      cmd.bZip = 1;
     }else if( cmd.zFile ){
       int flags;
+      if( cmd.bAppend ) eDbType = SHELL_OPEN_APPENDVFS;
       if( cmd.eCmd==AR_CMD_CREATE || cmd.eCmd==AR_CMD_UPDATE ){
         flags = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE;
       }else{
         flags = SQLITE_OPEN_READONLY;
       }
       cmd.db = 0;
-      rc = sqlite3_open_v2(cmd.zFile, &cmd.db, flags, 0);
+      if( cmd.bDryRun ){
+        utf8_printf(pState->out, "-- open database '%s'%s\n", cmd.zFile,
+             eDbType==SHELL_OPEN_APPENDVFS ? " using 'apndvfs'" : "");
+      }
+      rc = sqlite3_open_v2(cmd.zFile, &cmd.db, flags, 
+             eDbType==SHELL_OPEN_APPENDVFS ? "apndvfs" : 0);
       if( rc!=SQLITE_OK ){
         utf8_printf(stderr, "cannot open file: %s (%s)\n", 
             cmd.zFile, sqlite3_errmsg(cmd.db)
         );
-        sqlite3_close(cmd.db);
-        return rc;
+        goto end_ar_command;
       }
       sqlite3_fileio_init(cmd.db, 0, 0);
 #ifdef SQLITE_HAVE_ZLIB
       sqlite3_sqlar_init(cmd.db, 0, 0);
 #endif
     }
+    if( cmd.zSrcTable==0 ){
+      if( sqlite3_table_column_metadata(cmd.db,0,"sqlar","name",0,0,0,0,0) ){
+        utf8_printf(stderr, "database does not contain an 'sqlar' table\n");
+        rc = SQLITE_ERROR;
+        goto end_ar_command;
+      }
+      cmd.zSrcTable = sqlite3_mprintf("sqlar");
+    }
 
     switch( cmd.eCmd ){
       case AR_CMD_CREATE:
@@ -5177,11 +5191,12 @@ static int arDotCommand(
         rc = arCreateOrUpdateCommand(&cmd, 1);
         break;
     }
-
-    if( cmd.db!=pState->db ){
-      sqlite3_close(cmd.db);
-    }
   }
+end_ar_command:
+  if( cmd.db!=pState->db ){
+    sqlite3_close(cmd.db);
+  }
+  sqlite3_free(cmd.zSrcTable);
 
   return rc;
 }
index 0dcb10d67bf0d2828b692eac33524e535587c959..de0f237f727c5bd8d18baf78898037cc3b0274f9 100644 (file)
@@ -101,7 +101,7 @@ foreach {tn tcl} {
     set x2 ".ar --extract --dir ar3"
 
     set c3 ".ar --creat --dir ar1 --file test_xyz.db ."
-    set x3 ".ar --e  --d ar3 --f test_xyz.db"
+    set x3 ".ar --e  --dir ar3 --f test_xyz.db"
   }
 
   4 {
@@ -169,4 +169,3 @@ finish_test
 
 
 finish_test
-