Work on the ".archive" command.
(1) Add the --dryrun option. (2) Do not require --file when open on a ZIP archive. (3) Miscellaneous code simplifications. This is an incremental check-in of work in progress. FossilOrigin-Name: a2baada429e84dc4b7243173a056e3c8bc042682f7efb01fdf8d2cc452c97e04
This commit is contained in:
parent
5af0698356
commit
b376b3d6aa
15
manifest
15
manifest
@ -1,5 +1,5 @@
|
|||||||
C Rearrange\ssome\sroutines\sin\sshell.c\sto\savoid\sthe\sneed\sto\sforward\sreference\sa\nstatic\sfunction.
|
C Work\son\sthe\s".archive"\scommand.\n(1)\sAdd\sthe\s--dryrun\soption.\n(2)\sDo\snot\srequire\s--file\swhen\sopen\son\sa\sZIP\sarchive.\n(3)\sMiscellaneous\scode\ssimplifications.\nThis\sis\san\sincremental\scheck-in\sof\swork\sin\sprogress.
|
||||||
D 2018-01-10T00:53:55.338
|
D 2018-01-10T13:11:51.661
|
||||||
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
||||||
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
||||||
F Makefile.in 12b6daa4bdb03fa87da27cbc205ff88ace645475b5be79414a3038b68ade14cb
|
F Makefile.in 12b6daa4bdb03fa87da27cbc205ff88ace645475b5be79414a3038b68ade14cb
|
||||||
@ -484,7 +484,7 @@ F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384
|
|||||||
F src/resolve.c bbee7e31d369a18a2f4836644769882e9c5d40ef4a3af911db06410b65cb3730
|
F src/resolve.c bbee7e31d369a18a2f4836644769882e9c5d40ef4a3af911db06410b65cb3730
|
||||||
F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac
|
F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac
|
||||||
F src/select.c 8b22abe193e4d8243befa2038e4ae2405802fed1c446e5e502d11f652e09ba74
|
F src/select.c 8b22abe193e4d8243befa2038e4ae2405802fed1c446e5e502d11f652e09ba74
|
||||||
F src/shell.c.in 1e50d66dc88bcc61d6300a5b8fb71d2d3821ec2d1418aee69337e391061514dd
|
F src/shell.c.in f86200b08a8201fab1c775edbff4a81cb7b07e5926b1ed1ad7c043453fdfa7b3
|
||||||
F src/sqlite.h.in 1f1a2da222ec57465794e8984d77f32d0bd0da80cdc136beadda461a0be9d80c
|
F src/sqlite.h.in 1f1a2da222ec57465794e8984d77f32d0bd0da80cdc136beadda461a0be9d80c
|
||||||
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
|
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
|
||||||
F src/sqlite3ext.h c02d628cca67f3889c689d82d25c3eb45e2c155db08e4c6089b5840d64687d34
|
F src/sqlite3ext.h c02d628cca67f3889c689d82d25c3eb45e2c155db08e4c6089b5840d64687d34
|
||||||
@ -1697,7 +1697,10 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
|
|||||||
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
||||||
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
||||||
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
||||||
P 36b89d728ff13d395fe0e1db8e7c01263f73dccb278b3ece27f6ef78e909b492
|
P fd7f51a107806666d5c3a3a7a62528ec3e1fb71c4256f49d57b4dcdac4bf8680
|
||||||
R c0e5b3be89f9671131b70568ccd2de3b
|
R da66d185dcc66f20b0c30262a6b67fe7
|
||||||
|
T *branch * archive-improvements
|
||||||
|
T *sym-archive-improvements *
|
||||||
|
T -sym-trunk *
|
||||||
U drh
|
U drh
|
||||||
Z 058862bc11ed7b27f8f707a776eec676
|
Z 75859d5801ea825c715cde8533b487b8
|
||||||
|
@ -1 +1 @@
|
|||||||
fd7f51a107806666d5c3a3a7a62528ec3e1fb71c4256f49d57b4dcdac4bf8680
|
a2baada429e84dc4b7243173a056e3c8bc042682f7efb01fdf8d2cc452c97e04
|
233
src/shell.c.in
233
src/shell.c.in
@ -4503,13 +4503,17 @@ static void shellReset(
|
|||||||
*/
|
*/
|
||||||
typedef struct ArCommand ArCommand;
|
typedef struct ArCommand ArCommand;
|
||||||
struct ArCommand {
|
struct ArCommand {
|
||||||
int eCmd; /* An AR_CMD_* value */
|
u8 eCmd; /* An AR_CMD_* value */
|
||||||
|
u8 bVerbose; /* True if --verbose */
|
||||||
|
u8 bZip; /* True if --zip */
|
||||||
|
u8 bDryRun; /* True if --dry-run */
|
||||||
|
int nArg; /* Number of command arguments */
|
||||||
|
const char *zSrcTable; /* "sqlar", "zipfile($file)" or "zip" */
|
||||||
const char *zFile; /* --file argument, or NULL */
|
const char *zFile; /* --file argument, or NULL */
|
||||||
const char *zDir; /* --directory argument, or NULL */
|
const char *zDir; /* --directory argument, or NULL */
|
||||||
int bVerbose; /* True if --verbose */
|
|
||||||
int bZip; /* True if --zip */
|
|
||||||
int nArg; /* Number of command arguments */
|
|
||||||
char **azArg; /* Array of command arguments */
|
char **azArg; /* Array of command arguments */
|
||||||
|
ShellState *p; /* Shell state */
|
||||||
|
sqlite3 *db; /* Database containing the archive */
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -4536,6 +4540,8 @@ static int arUsage(FILE *f){
|
|||||||
" -v, --verbose Print each filename as it is processed\n"
|
" -v, --verbose Print each filename as it is processed\n"
|
||||||
" -f FILE, --file FILE Operate on archive FILE (default is current db)\n"
|
" -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"
|
" -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"
|
||||||
"\n"
|
"\n"
|
||||||
"See also: http://sqlite.org/cli.html#sqlar_archive_support\n"
|
"See also: http://sqlite.org/cli.html#sqlar_archive_support\n"
|
||||||
"\n"
|
"\n"
|
||||||
@ -4574,6 +4580,7 @@ static int arErrorMsg(const char *zFmt, ...){
|
|||||||
#define AR_SWITCH_FILE 7
|
#define AR_SWITCH_FILE 7
|
||||||
#define AR_SWITCH_DIRECTORY 8
|
#define AR_SWITCH_DIRECTORY 8
|
||||||
#define AR_SWITCH_ZIP 9
|
#define AR_SWITCH_ZIP 9
|
||||||
|
#define AR_SWITCH_DRYRUN 10
|
||||||
|
|
||||||
static int arProcessSwitch(ArCommand *pAr, int eSwitch, const char *zArg){
|
static int arProcessSwitch(ArCommand *pAr, int eSwitch, const char *zArg){
|
||||||
switch( eSwitch ){
|
switch( eSwitch ){
|
||||||
@ -4588,6 +4595,9 @@ static int arProcessSwitch(ArCommand *pAr, int eSwitch, const char *zArg){
|
|||||||
pAr->eCmd = eSwitch;
|
pAr->eCmd = eSwitch;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case AR_SWITCH_DRYRUN:
|
||||||
|
pAr->bDryRun = 1;
|
||||||
|
break;
|
||||||
case AR_SWITCH_VERBOSE:
|
case AR_SWITCH_VERBOSE:
|
||||||
pAr->bVerbose = 1;
|
pAr->bVerbose = 1;
|
||||||
break;
|
break;
|
||||||
@ -4618,20 +4628,21 @@ static int arParseCommand(
|
|||||||
ArCommand *pAr /* Populate this object */
|
ArCommand *pAr /* Populate this object */
|
||||||
){
|
){
|
||||||
struct ArSwitch {
|
struct ArSwitch {
|
||||||
char cShort;
|
|
||||||
const char *zLong;
|
const char *zLong;
|
||||||
int eSwitch;
|
char cShort;
|
||||||
int bArg;
|
u8 eSwitch;
|
||||||
|
u8 bArg;
|
||||||
} aSwitch[] = {
|
} aSwitch[] = {
|
||||||
{ 'c', "create", AR_CMD_CREATE, 0 },
|
{ "create", 'c', AR_CMD_CREATE, 0 },
|
||||||
{ 'x', "extract", AR_CMD_EXTRACT, 0 },
|
{ "extract", 'x', AR_CMD_EXTRACT, 0 },
|
||||||
{ 't', "list", AR_CMD_LIST, 0 },
|
{ "list", 't', AR_CMD_LIST, 0 },
|
||||||
{ 'u', "update", AR_CMD_UPDATE, 0 },
|
{ "update", 'u', AR_CMD_UPDATE, 0 },
|
||||||
{ 'h', "help", AR_CMD_HELP, 0 },
|
{ "help", 'h', AR_CMD_HELP, 0 },
|
||||||
{ 'v', "verbose", AR_SWITCH_VERBOSE, 0 },
|
{ "verbose", 'v', AR_SWITCH_VERBOSE, 0 },
|
||||||
{ 'f', "file", AR_SWITCH_FILE, 1 },
|
{ "file", 'f', AR_SWITCH_FILE, 1 },
|
||||||
{ 'C', "directory", AR_SWITCH_DIRECTORY, 1 },
|
{ "directory", 'C', AR_SWITCH_DIRECTORY, 1 },
|
||||||
{ 'z', "zip", AR_SWITCH_ZIP, 0 }
|
{ "zip", 'z', AR_SWITCH_ZIP, 0 },
|
||||||
|
{ "dryrun", 'n', AR_SWITCH_DRYRUN, 0 },
|
||||||
};
|
};
|
||||||
int nSwitch = sizeof(aSwitch) / sizeof(struct ArSwitch);
|
int nSwitch = sizeof(aSwitch) / sizeof(struct ArSwitch);
|
||||||
struct ArSwitch *pEnd = &aSwitch[nSwitch];
|
struct ArSwitch *pEnd = &aSwitch[nSwitch];
|
||||||
@ -4758,37 +4769,40 @@ static int arParseCommand(
|
|||||||
** This is consistent with the way the [tar] command seems to work on
|
** This is consistent with the way the [tar] command seems to work on
|
||||||
** Linux.
|
** Linux.
|
||||||
*/
|
*/
|
||||||
static int arCheckEntries(sqlite3 *db, ArCommand *pAr){
|
static int arCheckEntries(ArCommand *pAr){
|
||||||
int rc = SQLITE_OK;
|
int rc = SQLITE_OK;
|
||||||
if( pAr->nArg ){
|
if( pAr->nArg ){
|
||||||
int i;
|
int i, j;
|
||||||
sqlite3_stmt *pTest = 0;
|
sqlite3_stmt *pTest = 0;
|
||||||
|
|
||||||
shellPreparePrintf(db, &rc, &pTest, "SELECT name FROM %s WHERE name=?1",
|
shellPreparePrintf(pAr->db, &rc, &pTest,
|
||||||
pAr->bZip ? "zipfile(?2)" : "sqlar"
|
"SELECT name FROM %s WHERE name=$name",
|
||||||
|
pAr->zSrcTable
|
||||||
);
|
);
|
||||||
if( rc==SQLITE_OK && pAr->bZip ){
|
if( rc==SQLITE_OK
|
||||||
sqlite3_bind_text(pTest, 2, pAr->zFile, -1, SQLITE_TRANSIENT);
|
&& (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++){
|
for(i=0; i<pAr->nArg && rc==SQLITE_OK; i++){
|
||||||
char *z = pAr->azArg[i];
|
char *z = pAr->azArg[i];
|
||||||
int n = strlen30(z);
|
int n = strlen30(z);
|
||||||
int bOk = 0;
|
int bOk = 0;
|
||||||
while( n>0 && z[n-1]=='/' ) n--;
|
while( n>0 && z[n-1]=='/' ) n--;
|
||||||
z[n] = '\0';
|
z[n] = '\0';
|
||||||
sqlite3_bind_text(pTest, 1, z, -1, SQLITE_STATIC);
|
sqlite3_bind_text(pTest, j, z, -1, SQLITE_STATIC);
|
||||||
if( SQLITE_ROW==sqlite3_step(pTest) ){
|
if( SQLITE_ROW==sqlite3_step(pTest) ){
|
||||||
bOk = 1;
|
bOk = 1;
|
||||||
}
|
}
|
||||||
shellReset(&rc, pTest);
|
shellReset(&rc, pTest);
|
||||||
if( rc==SQLITE_OK && bOk==0 ){
|
if( rc==SQLITE_OK && bOk==0 ){
|
||||||
raw_printf(stderr, "not found in archive: %s\n", z);
|
utf8_printf(stderr, "not found in archive: %s\n", z);
|
||||||
rc = SQLITE_ERROR;
|
rc = SQLITE_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
shellFinalize(&rc, pTest);
|
shellFinalize(&rc, pTest);
|
||||||
}
|
}
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4814,8 +4828,8 @@ static void arWhereClause(
|
|||||||
for(i=0; i<pAr->nArg; i++){
|
for(i=0; i<pAr->nArg; i++){
|
||||||
const char *z = pAr->azArg[i];
|
const char *z = pAr->azArg[i];
|
||||||
zWhere = sqlite3_mprintf(
|
zWhere = sqlite3_mprintf(
|
||||||
"%z%s name = '%q' OR name BETWEEN '%q/' AND '%q0'",
|
"%z%s name = '%q' OR substr(name,1,%d) = '%q/'",
|
||||||
zWhere, zSep, z, z, z
|
zWhere, zSep, z, strlen30(z)+1, z
|
||||||
);
|
);
|
||||||
if( zWhere==0 ){
|
if( zWhere==0 ){
|
||||||
*pRc = SQLITE_NOMEM;
|
*pRc = SQLITE_NOMEM;
|
||||||
@ -4858,9 +4872,8 @@ static void shellModeToString(char *zMode, int mode){
|
|||||||
/*
|
/*
|
||||||
** Implementation of .ar "lisT" command.
|
** Implementation of .ar "lisT" command.
|
||||||
*/
|
*/
|
||||||
static int arListCommand(ShellState *p, sqlite3 *db, ArCommand *pAr){
|
static int arListCommand(ArCommand *pAr){
|
||||||
const char *zSql = "SELECT %s FROM %s WHERE %s";
|
const char *zSql = "SELECT %s FROM %s WHERE %s";
|
||||||
const char *zTbl = (pAr->bZip ? "zipfile(?)" : "sqlar");
|
|
||||||
const char *azCols[] = {
|
const char *azCols[] = {
|
||||||
"name",
|
"name",
|
||||||
"mode, sz, datetime(mtime, 'unixepoch'), name"
|
"mode, sz, datetime(mtime, 'unixepoch'), name"
|
||||||
@ -4869,29 +4882,36 @@ static int arListCommand(ShellState *p, sqlite3 *db, ArCommand *pAr){
|
|||||||
char *zWhere = 0;
|
char *zWhere = 0;
|
||||||
sqlite3_stmt *pSql = 0;
|
sqlite3_stmt *pSql = 0;
|
||||||
int rc;
|
int rc;
|
||||||
|
int j;
|
||||||
|
|
||||||
rc = arCheckEntries(db, pAr);
|
rc = arCheckEntries(pAr);
|
||||||
arWhereClause(&rc, pAr, &zWhere);
|
arWhereClause(&rc, pAr, &zWhere);
|
||||||
|
|
||||||
shellPreparePrintf(db, &rc, &pSql, zSql, azCols[pAr->bVerbose], zTbl, zWhere);
|
shellPreparePrintf(pAr->db, &rc, &pSql, zSql, azCols[pAr->bVerbose],
|
||||||
if( rc==SQLITE_OK && pAr->bZip ){
|
pAr->zSrcTable, zWhere);
|
||||||
sqlite3_bind_text(pSql, 1, pAr->zFile, -1, SQLITE_TRANSIENT);
|
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{
|
||||||
while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){
|
while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){
|
||||||
if( pAr->bVerbose ){
|
if( pAr->bVerbose ){
|
||||||
char zMode[11];
|
char zMode[11];
|
||||||
shellModeToString(zMode, sqlite3_column_int(pSql, 0));
|
shellModeToString(zMode, sqlite3_column_int(pSql, 0));
|
||||||
|
|
||||||
raw_printf(p->out, "%s % 10d %s %s\n", zMode,
|
utf8_printf(pAr->p->out, "%s % 10d %s %s\n", zMode,
|
||||||
sqlite3_column_int(pSql, 1),
|
sqlite3_column_int(pSql, 1),
|
||||||
sqlite3_column_text(pSql, 2),
|
sqlite3_column_text(pSql, 2),
|
||||||
sqlite3_column_text(pSql, 3)
|
sqlite3_column_text(pSql, 3)
|
||||||
);
|
);
|
||||||
}else{
|
}else{
|
||||||
raw_printf(p->out, "%s\n", sqlite3_column_text(pSql, 0));
|
utf8_printf(pAr->p->out, "%s\n", sqlite3_column_text(pSql, 0));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
shellFinalize(&rc, pSql);
|
shellFinalize(&rc, pSql);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
@ -4900,31 +4920,28 @@ static int arListCommand(ShellState *p, sqlite3 *db, ArCommand *pAr){
|
|||||||
/*
|
/*
|
||||||
** Implementation of .ar "eXtract" command.
|
** Implementation of .ar "eXtract" command.
|
||||||
*/
|
*/
|
||||||
static int arExtractCommand(ShellState *p, sqlite3 *db, ArCommand *pAr){
|
static int arExtractCommand(ArCommand *pAr){
|
||||||
const char *zSql1 =
|
const char *zSql1 =
|
||||||
"SELECT "
|
"SELECT "
|
||||||
" :1 || name, "
|
" ($dir || name),"
|
||||||
" writefile(?1 || name, %s, mode, mtime) "
|
" writefile(($dir || name), %s, mode, mtime) "
|
||||||
"FROM %s WHERE (%s) AND (data IS NULL OR ?2 = 0)";
|
"FROM %s WHERE (%s) AND (data IS NULL OR $dirOnly = 0)";
|
||||||
|
|
||||||
const char *azExtraArg[] = {
|
const char *azExtraArg[] = {
|
||||||
"sqlar_uncompress(data, sz)",
|
"sqlar_uncompress(data, sz)",
|
||||||
"data"
|
"data"
|
||||||
};
|
};
|
||||||
const char *azSource[] = {
|
|
||||||
"sqlar", "zipfile(?3)"
|
|
||||||
};
|
|
||||||
|
|
||||||
sqlite3_stmt *pSql = 0;
|
sqlite3_stmt *pSql = 0;
|
||||||
int rc = SQLITE_OK;
|
int rc = SQLITE_OK;
|
||||||
char *zDir = 0;
|
char *zDir = 0;
|
||||||
char *zWhere = 0;
|
char *zWhere = 0;
|
||||||
int i;
|
int i, j;
|
||||||
|
|
||||||
/* If arguments are specified, check that they actually exist within
|
/* If arguments are specified, check that they actually exist within
|
||||||
** the archive before proceeding. And formulate a WHERE clause to
|
** the archive before proceeding. And formulate a WHERE clause to
|
||||||
** match them. */
|
** match them. */
|
||||||
rc = arCheckEntries(db, pAr);
|
rc = arCheckEntries(pAr);
|
||||||
arWhereClause(&rc, pAr, &zWhere);
|
arWhereClause(&rc, pAr, &zWhere);
|
||||||
|
|
||||||
if( rc==SQLITE_OK ){
|
if( rc==SQLITE_OK ){
|
||||||
@ -4936,14 +4953,16 @@ static int arExtractCommand(ShellState *p, sqlite3 *db, ArCommand *pAr){
|
|||||||
if( zDir==0 ) rc = SQLITE_NOMEM;
|
if( zDir==0 ) rc = SQLITE_NOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
shellPreparePrintf(db, &rc, &pSql, zSql1,
|
shellPreparePrintf(pAr->db, &rc, &pSql, zSql1,
|
||||||
azExtraArg[pAr->bZip], azSource[pAr->bZip], zWhere
|
azExtraArg[pAr->bZip], pAr->zSrcTable, zWhere
|
||||||
);
|
);
|
||||||
|
|
||||||
if( rc==SQLITE_OK ){
|
if( rc==SQLITE_OK ){
|
||||||
sqlite3_bind_text(pSql, 1, zDir, -1, SQLITE_STATIC);
|
j = sqlite3_bind_parameter_index(pSql, "$dir");
|
||||||
if( pAr->bZip ){
|
sqlite3_bind_text(pSql, j, zDir, -1, SQLITE_STATIC);
|
||||||
sqlite3_bind_text(pSql, 3, pAr->zFile, -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
|
/* Run the SELECT statement twice. The first time, writefile() is called
|
||||||
@ -4952,10 +4971,15 @@ static int arExtractCommand(ShellState *p, sqlite3 *db, ArCommand *pAr){
|
|||||||
** extracted directories must be reset after they are populated (as
|
** extracted directories must be reset after they are populated (as
|
||||||
** populating them changes the timestamp). */
|
** populating them changes the timestamp). */
|
||||||
for(i=0; i<2; i++){
|
for(i=0; i<2; i++){
|
||||||
sqlite3_bind_int(pSql, 2, i);
|
j = sqlite3_bind_parameter_index(pSql, "$dirOnly");
|
||||||
|
sqlite3_bind_int(pSql, j, i);
|
||||||
|
if( pAr->bDryRun ){
|
||||||
|
utf8_printf(pAr->p->out, "%s\n", sqlite3_sql(pSql));
|
||||||
|
}else{
|
||||||
while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){
|
while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){
|
||||||
if( i==0 && pAr->bVerbose ){
|
if( i==0 && pAr->bVerbose ){
|
||||||
raw_printf(p->out, "%s\n", sqlite3_column_text(pSql, 0));
|
utf8_printf(pAr->p->out, "%s\n", sqlite3_column_text(pSql, 0));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
shellReset(&rc, pSql);
|
shellReset(&rc, pSql);
|
||||||
@ -4968,6 +4992,20 @@ static int arExtractCommand(ShellState *p, sqlite3 *db, ArCommand *pAr){
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Run the SQL statement in zSql. Or if doing a --dryrun, merely print it out.
|
||||||
|
*/
|
||||||
|
static int arExecSql(ArCommand *pAr, const char *zSql){
|
||||||
|
int rc;
|
||||||
|
if( pAr->bDryRun ){
|
||||||
|
utf8_printf(pAr->p->out, "%s\n", zSql);
|
||||||
|
rc = SQLITE_OK;
|
||||||
|
}else{
|
||||||
|
rc = sqlite3_exec(pAr->db, zSql, 0, 0, 0);
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Implementation of .ar "create" and "update" commands.
|
** Implementation of .ar "create" and "update" commands.
|
||||||
@ -4980,11 +5018,9 @@ static int arExtractCommand(ShellState *p, sqlite3 *db, ArCommand *pAr){
|
|||||||
** The create command is the same as update, except that it drops
|
** The create command is the same as update, except that it drops
|
||||||
** any existing "sqlar" table before beginning.
|
** any existing "sqlar" table before beginning.
|
||||||
*/
|
*/
|
||||||
static int arCreateUpdate(
|
static int arCreateOrUpdateCommand(
|
||||||
ShellState *p, /* Shell state pointer */
|
|
||||||
sqlite3 *db,
|
|
||||||
ArCommand *pAr, /* Command arguments and options */
|
ArCommand *pAr, /* Command arguments and options */
|
||||||
int bUpdate
|
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(?, ?)";
|
||||||
const char *zCreate =
|
const char *zCreate =
|
||||||
@ -5005,17 +5041,17 @@ static int arCreateUpdate(
|
|||||||
|
|
||||||
assert( pAr->bZip==0 );
|
assert( pAr->bZip==0 );
|
||||||
|
|
||||||
rc = sqlite3_exec(db, "SAVEPOINT ar;", 0, 0, 0);
|
rc = arExecSql(pAr, "SAVEPOINT ar;");
|
||||||
if( rc!=SQLITE_OK ) return rc;
|
if( rc!=SQLITE_OK ) return rc;
|
||||||
|
|
||||||
if( bUpdate==0 ){
|
if( bUpdate==0 ){
|
||||||
rc = sqlite3_exec(db, zDrop, 0, 0, 0);
|
rc = arExecSql(pAr, zDrop);
|
||||||
if( rc!=SQLITE_OK ) return rc;
|
if( rc!=SQLITE_OK ) return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = sqlite3_exec(db, zCreate, 0, 0, 0);
|
rc = arExecSql(pAr, zCreate);
|
||||||
shellPrepare(db, &rc, zInsert, &pInsert);
|
shellPrepare(pAr->db, &rc, zInsert, &pInsert);
|
||||||
shellPrepare(db, &rc, zSql, &pStmt);
|
shellPrepare(pAr->db, &rc, zSql, &pStmt);
|
||||||
sqlite3_bind_text(pStmt, 2, pAr->zDir, -1, SQLITE_STATIC);
|
sqlite3_bind_text(pStmt, 2, pAr->zDir, -1, SQLITE_STATIC);
|
||||||
|
|
||||||
for(i=0; i<pAr->nArg && rc==SQLITE_OK; i++){
|
for(i=0; i<pAr->nArg && rc==SQLITE_OK; i++){
|
||||||
@ -5027,7 +5063,7 @@ static int arCreateUpdate(
|
|||||||
unsigned int mtime = sqlite3_column_int(pStmt, 2);
|
unsigned int mtime = sqlite3_column_int(pStmt, 2);
|
||||||
|
|
||||||
if( pAr->bVerbose ){
|
if( pAr->bVerbose ){
|
||||||
raw_printf(p->out, "%s\n", zName);
|
utf8_printf(pAr->p->out, "%s\n", zName);
|
||||||
}
|
}
|
||||||
|
|
||||||
sqlite3_bind_text(pInsert, 1, zName, -1, SQLITE_STATIC);
|
sqlite3_bind_text(pInsert, 1, zName, -1, SQLITE_STATIC);
|
||||||
@ -5047,46 +5083,26 @@ static int arCreateUpdate(
|
|||||||
}
|
}
|
||||||
|
|
||||||
sqlite3_bind_int(pInsert, 4, sz);
|
sqlite3_bind_int(pInsert, 4, sz);
|
||||||
|
if( pAr->bDryRun ){
|
||||||
|
utf8_printf(pAr->p->out, "%s\n", sqlite3_sql(pInsert));
|
||||||
|
}else{
|
||||||
sqlite3_step(pInsert);
|
sqlite3_step(pInsert);
|
||||||
|
}
|
||||||
rc = sqlite3_reset(pInsert);
|
rc = sqlite3_reset(pInsert);
|
||||||
}
|
}
|
||||||
shellReset(&rc, pStmt);
|
shellReset(&rc, pStmt);
|
||||||
}
|
}
|
||||||
|
|
||||||
if( rc!=SQLITE_OK ){
|
if( rc!=SQLITE_OK ){
|
||||||
sqlite3_exec(db, "ROLLBACK TO ar; RELEASE ar;", 0, 0, 0);
|
arExecSql(pAr, "ROLLBACK TO ar; RELEASE ar;");
|
||||||
}else{
|
}else{
|
||||||
rc = sqlite3_exec(db, "RELEASE ar;", 0, 0, 0);
|
rc = arExecSql(pAr, "RELEASE ar;");
|
||||||
}
|
}
|
||||||
shellFinalize(&rc, pStmt);
|
shellFinalize(&rc, pStmt);
|
||||||
shellFinalize(&rc, pInsert);
|
shellFinalize(&rc, pInsert);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
** Implementation of .ar "Create" command.
|
|
||||||
**
|
|
||||||
** Create the "sqlar" table in the database if it does not already exist.
|
|
||||||
** Then add each file in the azFile[] array to the archive. Directories
|
|
||||||
** are added recursively. If argument bVerbose is non-zero, a message is
|
|
||||||
** printed on stdout for each file archived.
|
|
||||||
*/
|
|
||||||
static int arCreateCommand(
|
|
||||||
ShellState *p, /* Shell state pointer */
|
|
||||||
sqlite3 *db,
|
|
||||||
ArCommand *pAr /* Command arguments and options */
|
|
||||||
){
|
|
||||||
return arCreateUpdate(p, db, pAr, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Implementation of .ar "Update" command.
|
|
||||||
*/
|
|
||||||
static int arUpdateCmd(ShellState *p, sqlite3 *db, ArCommand *pAr){
|
|
||||||
return arCreateUpdate(p, db, pAr, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Implementation of ".ar" dot command.
|
** Implementation of ".ar" dot command.
|
||||||
*/
|
*/
|
||||||
@ -5099,18 +5115,19 @@ static int arDotCommand(
|
|||||||
int rc;
|
int rc;
|
||||||
rc = arParseCommand(azArg, nArg, &cmd);
|
rc = arParseCommand(azArg, nArg, &cmd);
|
||||||
if( rc==SQLITE_OK ){
|
if( rc==SQLITE_OK ){
|
||||||
sqlite3 *db = 0; /* Database handle to use as archive */
|
cmd.p = pState;
|
||||||
|
cmd.db = pState->db;
|
||||||
|
cmd.zSrcTable = "sqlar";
|
||||||
if( cmd.bZip ){
|
if( cmd.bZip ){
|
||||||
if( cmd.zFile==0 ){
|
if( pState->openMode==SHELL_OPEN_ZIPFILE ){
|
||||||
raw_printf(stderr, "zip format requires a --file switch\n");
|
cmd.zSrcTable = "zip";
|
||||||
return SQLITE_ERROR;
|
}else{
|
||||||
}else
|
cmd.zSrcTable = "zipfile($archiveFile)";
|
||||||
|
}
|
||||||
if( cmd.eCmd==AR_CMD_CREATE || cmd.eCmd==AR_CMD_UPDATE ){
|
if( cmd.eCmd==AR_CMD_CREATE || cmd.eCmd==AR_CMD_UPDATE ){
|
||||||
raw_printf(stderr, "zip archives are read-only\n");
|
utf8_printf(stderr, "zip archives are read-only\n");
|
||||||
return SQLITE_ERROR;
|
return SQLITE_ERROR;
|
||||||
}
|
}
|
||||||
db = pState->db;
|
|
||||||
}else if( cmd.zFile ){
|
}else if( cmd.zFile ){
|
||||||
int flags;
|
int flags;
|
||||||
if( cmd.eCmd==AR_CMD_CREATE || cmd.eCmd==AR_CMD_UPDATE ){
|
if( cmd.eCmd==AR_CMD_CREATE || cmd.eCmd==AR_CMD_UPDATE ){
|
||||||
@ -5118,33 +5135,31 @@ static int arDotCommand(
|
|||||||
}else{
|
}else{
|
||||||
flags = SQLITE_OPEN_READONLY;
|
flags = SQLITE_OPEN_READONLY;
|
||||||
}
|
}
|
||||||
rc = sqlite3_open_v2(cmd.zFile, &db, flags, 0);
|
rc = sqlite3_open_v2(cmd.zFile, &cmd.db, flags, 0);
|
||||||
if( rc!=SQLITE_OK ){
|
if( rc!=SQLITE_OK ){
|
||||||
raw_printf(stderr, "cannot open file: %s (%s)\n",
|
utf8_printf(stderr, "cannot open file: %s (%s)\n",
|
||||||
cmd.zFile, sqlite3_errmsg(db)
|
cmd.zFile, sqlite3_errmsg(cmd.db)
|
||||||
);
|
);
|
||||||
sqlite3_close(db);
|
sqlite3_close(cmd.db);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
sqlite3_fileio_init(db, 0, 0);
|
sqlite3_fileio_init(cmd.db, 0, 0);
|
||||||
#ifdef SQLITE_HAVE_ZLIB
|
#ifdef SQLITE_HAVE_ZLIB
|
||||||
sqlite3_sqlar_init(db, 0, 0);
|
sqlite3_sqlar_init(cmd.db, 0, 0);
|
||||||
#endif
|
#endif
|
||||||
}else{
|
|
||||||
db = pState->db;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
switch( cmd.eCmd ){
|
switch( cmd.eCmd ){
|
||||||
case AR_CMD_CREATE:
|
case AR_CMD_CREATE:
|
||||||
rc = arCreateCommand(pState, db, &cmd);
|
rc = arCreateOrUpdateCommand(&cmd, 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AR_CMD_EXTRACT:
|
case AR_CMD_EXTRACT:
|
||||||
rc = arExtractCommand(pState, db, &cmd);
|
rc = arExtractCommand(&cmd);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AR_CMD_LIST:
|
case AR_CMD_LIST:
|
||||||
rc = arListCommand(pState, db, &cmd);
|
rc = arListCommand(&cmd);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AR_CMD_HELP:
|
case AR_CMD_HELP:
|
||||||
@ -5153,12 +5168,12 @@ static int arDotCommand(
|
|||||||
|
|
||||||
default:
|
default:
|
||||||
assert( cmd.eCmd==AR_CMD_UPDATE );
|
assert( cmd.eCmd==AR_CMD_UPDATE );
|
||||||
rc = arUpdateCmd(pState, db, &cmd);
|
rc = arCreateOrUpdateCommand(&cmd, 1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( cmd.zFile ){
|
if( cmd.zFile ){
|
||||||
sqlite3_close(db);
|
sqlite3_close(cmd.db);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user