-C Setting\s".stats\s2"\sin\sthe\sCLI\scauses\scolumn\smetadata\sfor\seach\nprepared\sstatement\sto\sbe\sdisplayed.
-D 2018-03-09T16:37:05.324
+C Enhance\sthe\s".ar"\scommand\sin\sthe\sCLI\sso\sthat\sit\sis\sable\sto\supdate\sand\ncreate\sZIP\sArchives.
+D 2018-03-09T21:54:01.608
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F Makefile.in 7016fc56c6b9bfe5daac4f34be8be38d8c0b5fab79ccbfb764d3b23bf1c6fff3
F src/resolve.c 66c73fcb7719b8ff0e841b58338f13604ff3e2b50a723f9b8f383595735262f6
F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac
F src/select.c f02352ac5cbb6fad3804add825743b924cfb6c742ba2e8666d726828a9985d73
-F src/shell.c.in 754905107134107564345d43e74921f3a3b3f964827b2e2d5bc437ebba843eaf
+F src/shell.c.in b499275d69fffce0012681ddf0c00a2856b65af0028a7e5b9aee3886180e91e9
F src/sqlite.h.in 49d776d536076894e38de837a6c999e5150949baf008aa02d91fea70471eae78
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h 83a3c4ce93d650bedfd1aa558cb85a516bd6d094445ee989740827d0d944368d
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P 72e8f529ac8a268611f16456b13d55cc6c62df7f1a0aaa78a169338a0d95b960
-R e31c00c5775bc8c440f35c0a79819b6a
+P 7fea00fd96a8ab7e65734540edb907b6224659ae95d7e0504755f2610c545587
+R 85f130d4e717fcf952736cd9ba56b3e7
U drh
-Z c4b88c9fba10493862085e7979f0eebb
+Z 22e107de180218309232866a05b8494f
/*
** Try to deduce the type of file for zName based on its content. Return
** one of the SHELL_OPEN_* constants.
+**
+** If the file does not exist or is empty but its name looks like a ZIP
+** archive and the dfltZip flag is true, then assume it is a ZIP archive.
+** Otherwise, assume an ordinary database regardless of the filename if
+** the type cannot be determined from content.
*/
-static int deduceDatabaseType(const char *zName){
+static int deduceDatabaseType(const char *zName, int dfltZip){
FILE *f = fopen(zName, "rb");
size_t n;
int rc = SHELL_OPEN_UNSPEC;
char zBuf[100];
- if( f==0 ) return SHELL_OPEN_NORMAL;
+ if( f==0 ){
+ if( dfltZip && sqlite3_strlike("%.zip",zName,0)==0 ) return SHELL_OPEN_ZIPFILE;
+ return SHELL_OPEN_NORMAL;
+ }
fseek(f, -25, SEEK_END);
n = fread(zBuf, 25, 1, f);
if( n==1 && memcmp(zBuf, "Start-Of-SQLite3-", 17)==0 ){
if( n==1 && zBuf[0]==0x50 && zBuf[1]==0x4b && zBuf[2]==0x05
&& zBuf[3]==0x06 ){
rc = SHELL_OPEN_ZIPFILE;
+ }else if( n==0 && dfltZip && sqlite3_strlike("%.zip",zName,0)==0 ){
+ return SHELL_OPEN_ZIPFILE;
}
}
fclose(f);
if( p->db==0 ){
sqlite3_initialize();
if( p->openMode==SHELL_OPEN_UNSPEC && access(p->zDbFilename,0)==0 ){
- p->openMode = (u8)deduceDatabaseType(p->zDbFilename);
+ p->openMode = (u8)deduceDatabaseType(p->zDbFilename, 0);
}
switch( p->openMode ){
case SHELL_OPEN_APPENDVFS: {
" data BLOB -- compressed content\n"
")";
const char *zDrop = "DROP TABLE IF EXISTS sqlar";
- const char *zInsertFmt =
- "REPLACE INTO sqlar(name,mode,mtime,sz,data)\n"
+ const char *zInsertFmt[2] = {
+ "REPLACE INTO %s(name,mode,mtime,sz,data)\n"
" SELECT\n"
" %s,\n"
" mode,\n"
" WHEN '-' THEN length(data)\n"
" WHEN 'd' THEN 0\n"
" ELSE -1 END,\n"
- " CASE WHEN lsmode(mode) LIKE 'd%%' THEN NULL else data END\n"
+ " data\n"
" FROM fsdir(%Q,%Q)\n"
- " WHERE lsmode(mode) NOT LIKE '?%%';";
+ " WHERE lsmode(mode) NOT LIKE '?%%';",
+ "REPLACE INTO %s(name,mode,mtime,data)\n"
+ " SELECT\n"
+ " %s,\n"
+ " mode,\n"
+ " mtime,\n"
+ " data\n"
+ " FROM fsdir(%Q,%Q)\n"
+ " WHERE lsmode(mode) NOT LIKE '?%%';"
+ };
int i; /* For iterating through azFile[] */
int rc; /* Return code */
+ const char *zTab = 0; /* SQL table into which to insert */
+ char *zSql;
+ char zTemp[50];
+ arExecSql(pAr, "PRAGMA page_size=512");
rc = arExecSql(pAr, "SAVEPOINT ar;");
if( rc!=SQLITE_OK ) return rc;
- if( bUpdate==0 ){
- rc = arExecSql(pAr, zDrop);
- if( rc!=SQLITE_OK ) return rc;
+ zTemp[0] = 0;
+ if( pAr->bZip ){
+ /* Initialize the zipfile virtual table, if necessary */
+ if( pAr->zFile ){
+ sqlite3_uint64 r;
+ sqlite3_randomness(sizeof(r),&r);
+ sqlite3_snprintf(sizeof(zTemp),zTemp,"zip%016llx",r);
+ zTab = zTemp;
+ zSql = sqlite3_mprintf(
+ "CREATE VIRTUAL TABLE temp.%s USING zipfile(%Q)",
+ zTab, pAr->zFile
+ );
+ rc = arExecSql(pAr, zSql);
+ sqlite3_free(zSql);
+ }else{
+ zTab = "zip";
+ }
+ }else{
+ /* Initialize the table for an SQLAR */
+ zTab = "sqlar";
+ if( bUpdate==0 ){
+ rc = arExecSql(pAr, zDrop);
+ if( rc!=SQLITE_OK ) goto end_ar_transaction;
+ }
+ rc = arExecSql(pAr, zCreate);
}
- rc = arExecSql(pAr, zCreate);
for(i=0; i<pAr->nArg && rc==SQLITE_OK; i++){
- char *zSql = sqlite3_mprintf(zInsertFmt,
+ char *zSql = sqlite3_mprintf(zInsertFmt[pAr->bZip], zTab,
pAr->bVerbose ? "shell_putsnl(name)" : "name",
pAr->azArg[i], pAr->zDir);
rc = arExecSql(pAr, zSql);
sqlite3_free(zSql);
}
+end_ar_transaction:
if( rc!=SQLITE_OK ){
arExecSql(pAr, "ROLLBACK TO ar; RELEASE ar;");
}else{
rc = arExecSql(pAr, "RELEASE ar;");
+ if( pAr->bZip && pAr->zFile ){
+ zSql = sqlite3_mprintf("DROP TABLE %s", zTemp);
+ arExecSql(pAr, zSql);
+ sqlite3_free(zSql);
+ }
}
return rc;
}
cmd.p = pState;
cmd.db = pState->db;
if( cmd.zFile ){
- eDbType = deduceDatabaseType(cmd.zFile);
+ eDbType = deduceDatabaseType(cmd.zFile, 1);
}else{
eDbType = pState->openMode;
}
if( eDbType==SHELL_OPEN_ZIPFILE ){
- if( cmd.zFile==0 ){
- cmd.zSrcTable = sqlite3_mprintf("zip");
- }else{
- 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");
- rc = SQLITE_ERROR;
- goto end_ar_command;
+ if( cmd.eCmd==AR_CMD_EXTRACT || cmd.eCmd==AR_CMD_LIST ){
+ if( cmd.zFile==0 ){
+ cmd.zSrcTable = sqlite3_mprintf("zip");
+ }else{
+ cmd.zSrcTable = sqlite3_mprintf("zipfile(%Q)", cmd.zFile);
+ }
}
cmd.bZip = 1;
}else if( cmd.zFile ){
shellPutsFunc, 0, 0);
}
- if( cmd.zSrcTable==0 ){
+ if( cmd.zSrcTable==0 && cmd.bZip==0 ){
if( cmd.eCmd!=AR_CMD_CREATE
&& sqlite3_table_column_metadata(cmd.db,0,"sqlar","name",0,0,0,0,0)
){