-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
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
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
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
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 */
" -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"
#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){
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:
{ "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);
"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];
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{
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,
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"
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 );
}
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);
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);
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:
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;
}