Merge enhancements from trunk, especially the CLI fixes.
FossilOrigin-Name: a350040a3bb962823f92908fb31cade52baf13eab90ef608ca3a8349e4c28c9d
diff --git a/manifest b/manifest
index bf8c287..707ba67 100644
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Avoid\sunnecessary\ssqlite3_finalize()\soperations.
-D 2018-05-18T16:53:07.242
+C Merge\senhancements\sfrom\strunk,\sespecially\sthe\sCLI\sfixes.
+D 2018-05-18T17:17:36.604
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F Makefile.in bfc40f350586923e0419d2ea4b559c37ec10ee4b6e210e08c14401f8e340f0da
@@ -495,7 +495,7 @@
F src/resolve.c 6415381a0e9d22c0e7cba33ca4a53f81474190862f5d4838190f5eb5b0b47bc9
F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac
F src/select.c a35d462ee7a3c0856ad7a9d9c8921fbf3d91d911a8f39ad9d61302eb43b24a71
-F src/shell.c.in 53affa90711f280342f7238f9c9aa9dcaed321ec6218a18043cf92154ef8a704
+F src/shell.c.in 51c100206f4b7f86cd9affd80b764825e0edc36ca0190c442e4ca7994611bfe2
F src/sqlite.h.in 34be2d0d18bf4726538793bdc9854cd87f689fda4b3789515134cdbd68188cf4
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h 9887b27e69c01e79c2cbe74ef73bf01af5b5703d6a7f0a4371e386d7249cb1c7
@@ -568,7 +568,7 @@
F src/vdbe.h d970d9738efdd09cb2df73e3a40856e7df13e88a3486789c49fcdd322c9eb8a2
F src/vdbeInt.h 95f7adfdc5c8f1353321f55a6c5ec00a90877e3b85af5159e393afb41ff54110
F src/vdbeapi.c 29d2baf9c1233131ec467d7bed1b7c8a03c27579048d768c4b04acf427838858
-F src/vdbeaux.c f1cb5ae6e42c54d4991e2951e5293c1e18bad6847056e9b17622fbf6b17964a9
+F src/vdbeaux.c 3b0650dbebebb196010d8af830551e61ea7dcc0e414a2b747f897305b0bd0b8f
F src/vdbeblob.c f5c70f973ea3a9e915d1693278a5f890dc78594300cf4d54e64f2b0917c94191
F src/vdbemem.c 0cbe9b9560e42b72983cf9e1bceba48f297e51142bfb6b57f3747cf60106b92d
F src/vdbesort.c 731a09e5cb9e96b70c394c1b7cf3860fbe84acca7682e178615eb941a3a0ef2f
@@ -1729,7 +1729,7 @@
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P 95fd296ffc8130526a1453cbdca6ce47f22fc5b5c474aa31d66b627d0c7393a1
-R 2d7f80f5a8cb7985e7256646130cf7be
+P 16f71032a3a2919cb226b25b5256a370adb5c55fa506d4774b7f83dc8868e793 e3b2e0a078b82ac6cd3c3312e8ac0983c1375e1052f1e324476d2f8d1b227c30
+R c67fcd3e8c429daa0c0bf5aeb356dbf0
U drh
-Z 143ebe5c5507b367bd6154b3294d97b7
+Z 66b7d64381807f753032bf250835a757
diff --git a/manifest.uuid b/manifest.uuid
index 643e5a1..ce4a1dd 100644
--- a/manifest.uuid
+++ b/manifest.uuid
@@ -1 +1 @@
-16f71032a3a2919cb226b25b5256a370adb5c55fa506d4774b7f83dc8868e793
\ No newline at end of file
+a350040a3bb962823f92908fb31cade52baf13eab90ef608ca3a8349e4c28c9d
\ No newline at end of file
diff --git a/src/shell.c.in b/src/shell.c.in
index c50c92e..e7cc36f 100644
--- a/src/shell.c.in
+++ b/src/shell.c.in
@@ -3547,8 +3547,11 @@
int rc = SHELL_OPEN_UNSPEC;
char zBuf[100];
if( f==0 ){
- if( dfltZip && sqlite3_strlike("%.zip",zName,0)==0 ) return SHELL_OPEN_ZIPFILE;
- return SHELL_OPEN_NORMAL;
+ if( dfltZip && sqlite3_strlike("%.zip",zName,0)==0 ){
+ return SHELL_OPEN_ZIPFILE;
+ }else{
+ return SHELL_OPEN_NORMAL;
+ }
}
fseek(f, -25, SEEK_END);
n = fread(zBuf, 25, 1, f);
@@ -3568,17 +3571,31 @@
return rc;
}
+/* Flags for open_db().
+**
+** The default behavior of open_db() is to exit(1) if the database fails to
+** open. The OPEN_DB_KEEPALIVE flag changes that so that it prints an error
+** but still returns without calling exit.
+**
+** The OPEN_DB_ZIPFILE flag causes open_db() to prefer to open files as a
+** ZIP archive if the file does not exist or is empty and its name matches
+** the *.zip pattern.
+*/
+#define OPEN_DB_KEEPALIVE 0x001 /* Return after error if true */
+#define OPEN_DB_ZIPFILE 0x002 /* Open as ZIP if name matches *.zip */
+
/*
** Make sure the database is open. If it is not, then open it. If
** the database fails to open, print an error message and exit.
*/
-static void open_db(ShellState *p, int keepAlive){
+static void open_db(ShellState *p, int openFlags){
if( p->db==0 ){
if( p->openMode==SHELL_OPEN_UNSPEC ){
if( p->zDbFilename==0 || p->zDbFilename[0]==0 ){
p->openMode = SHELL_OPEN_NORMAL;
- }else if( access(p->zDbFilename,0)==0 ){
- p->openMode = (u8)deduceDatabaseType(p->zDbFilename, 0);
+ }else{
+ p->openMode = (u8)deduceDatabaseType(p->zDbFilename,
+ (openFlags & OPEN_DB_ZIPFILE)!=0);
}
}
switch( p->openMode ){
@@ -3605,7 +3622,7 @@
if( p->db==0 || SQLITE_OK!=sqlite3_errcode(p->db) ){
utf8_printf(stderr,"Error: unable to open database \"%s\": %s\n",
p->zDbFilename, sqlite3_errmsg(p->db));
- if( keepAlive ) return;
+ if( openFlags & OPEN_DB_KEEPALIVE ) return;
exit(1);
}
#ifndef SQLITE_OMIT_LOAD_EXTENSION
@@ -3639,6 +3656,17 @@
}
}
+/*
+** Attempt to close the databaes connection. Report errors.
+*/
+void close_db(sqlite3 *db){
+ int rc = sqlite3_close(db);
+ if( rc ){
+ utf8_printf(stderr, "Error: sqlite3_close() returns %d: %s\n",
+ rc, sqlite3_errmsg(db));
+ }
+}
+
#if HAVE_READLINE || HAVE_EDITLINE
/*
** Readline completion callbacks
@@ -4219,7 +4247,7 @@
sqlite3_exec(newDb, "COMMIT;", 0, 0, 0);
sqlite3_exec(p->db, "PRAGMA writable_schema=OFF;", 0, 0, 0);
}
- sqlite3_close(newDb);
+ close_db(newDb);
}
/*
@@ -4874,6 +4902,7 @@
u8 bZip; /* True if the archive is a ZIP */
u8 bDryRun; /* True if --dry-run */
u8 bAppend; /* True if --append */
+ u8 fromCmdLine; /* Run from -A instead of .archive */
int nArg; /* Number of command arguments */
char *zSrcTable; /* "sqlar", "zipfile($file)" or "zip" */
const char *zFile; /* --file argument, or NULL */
@@ -4920,13 +4949,18 @@
** Print an error message for the .ar command to stderr and return
** SQLITE_ERROR.
*/
-static int arErrorMsg(const char *zFmt, ...){
+static int arErrorMsg(ArCommand *pAr, const char *zFmt, ...){
va_list ap;
char *z;
va_start(ap, zFmt);
z = sqlite3_vmprintf(zFmt, ap);
va_end(ap);
- raw_printf(stderr, "Error: %s (try \".ar --help\")\n", z);
+ utf8_printf(stderr, "Error: %s\n", z);
+ if( pAr->fromCmdLine ){
+ utf8_printf(stderr, "Use \"-A\" for more help\n");
+ }else{
+ utf8_printf(stderr, "Use \".archive --help\" for more help\n");
+ }
sqlite3_free(z);
return SQLITE_ERROR;
}
@@ -4957,7 +4991,7 @@
case AR_CMD_UPDATE:
case AR_CMD_HELP:
if( pAr->eCmd ){
- return arErrorMsg("multiple command options");
+ return arErrorMsg(pAr, "multiple command options");
}
pAr->eCmd = eSwitch;
break;
@@ -5017,8 +5051,6 @@
return arUsage(stderr);
}else{
char *z = azArg[1];
- memset(pAr, 0, sizeof(ArCommand));
-
if( z[0]!='-' ){
/* Traditional style [tar] invocation */
int i;
@@ -5030,11 +5062,11 @@
if( z[i]==pOpt->cShort ) break;
}
if( pOpt==pEnd ){
- return arErrorMsg("unrecognized option: %c", z[i]);
+ return arErrorMsg(pAr, "unrecognized option: %c", z[i]);
}
if( pOpt->bArg ){
if( iArg>=nArg ){
- return arErrorMsg("option requires an argument: %c",z[i]);
+ return arErrorMsg(pAr, "option requires an argument: %c",z[i]);
}
zArg = azArg[iArg++];
}
@@ -5068,7 +5100,7 @@
if( z[i]==pOpt->cShort ) break;
}
if( pOpt==pEnd ){
- return arErrorMsg("unrecognized option: %c\n", z[i]);
+ return arErrorMsg(pAr, "unrecognized option: %c", z[i]);
}
if( pOpt->bArg ){
if( i<(n-1) ){
@@ -5076,7 +5108,7 @@
i = n;
}else{
if( iArg>=(nArg-1) ){
- return arErrorMsg("option requires an argument: %c\n",z[i]);
+ return arErrorMsg(pAr, "option requires an argument: %c",z[i]);
}
zArg = azArg[++iArg];
}
@@ -5098,7 +5130,7 @@
const char *zLong = pOpt->zLong;
if( (n-2)<=strlen30(zLong) && 0==memcmp(&z[2], zLong, n-2) ){
if( pMatch ){
- return arErrorMsg("ambiguous option: %s",z);
+ return arErrorMsg(pAr, "ambiguous option: %s",z);
}else{
pMatch = pOpt;
}
@@ -5106,11 +5138,11 @@
}
if( pMatch==0 ){
- return arErrorMsg("unrecognized option: %s", z);
+ return arErrorMsg(pAr, "unrecognized option: %s", z);
}
if( pMatch->bArg ){
if( iArg>=(nArg-1) ){
- return arErrorMsg("option requires an argument: %s", z);
+ return arErrorMsg(pAr, "option requires an argument: %s", z);
}
zArg = azArg[++iArg];
}
@@ -5239,6 +5271,7 @@
}
}
shellFinalize(&rc, pSql);
+ sqlite3_free(zWhere);
return rc;
}
@@ -5441,12 +5474,14 @@
*/
static int arDotCommand(
ShellState *pState, /* Current shell tool state */
+ int fromCmdLine, /* True if -A command-line option, not .ar cmd */
char **azArg, /* Array of arguments passed to dot command */
int nArg /* Number of entries in azArg[] */
){
ArCommand cmd;
int rc;
memset(&cmd, 0, sizeof(cmd));
+ cmd.fromCmdLine = fromCmdLine;
rc = arParseCommand(azArg, nArg, &cmd);
if( rc==SQLITE_OK ){
int eDbType = SHELL_OPEN_UNSPEC;
@@ -5493,7 +5528,7 @@
shellPutsFunc, 0, 0);
}
- if( cmd.zSrcTable==0 && cmd.bZip==0 ){
+ if( cmd.zSrcTable==0 && cmd.bZip==0 && cmd.eCmd!=AR_CMD_HELP ){
if( cmd.eCmd!=AR_CMD_CREATE
&& sqlite3_table_column_metadata(cmd.db,0,"sqlar","name",0,0,0,0,0)
){
@@ -5529,7 +5564,7 @@
}
end_ar_command:
if( cmd.db!=pState->db ){
- sqlite3_close(cmd.db);
+ close_db(cmd.db);
}
sqlite3_free(cmd.zSrcTable);
@@ -5609,7 +5644,7 @@
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
if( c=='a' && strncmp(azArg[0], "archive", n)==0 ){
open_db(p, 0);
- rc = arDotCommand(p, azArg, nArg);
+ rc = arDotCommand(p, 0, azArg, nArg);
}else
#endif
@@ -5652,14 +5687,14 @@
SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE, zVfs);
if( rc!=SQLITE_OK ){
utf8_printf(stderr, "Error: cannot open \"%s\"\n", zDestFile);
- sqlite3_close(pDest);
+ close_db(pDest);
return 1;
}
open_db(p, 0);
pBackup = sqlite3_backup_init(pDest, "main", p->db, zDb);
if( pBackup==0 ){
utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(pDest));
- sqlite3_close(pDest);
+ close_db(pDest);
return 1;
}
while( (rc = sqlite3_backup_step(pBackup,100))==SQLITE_OK ){}
@@ -5670,7 +5705,7 @@
utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(pDest));
rc = 1;
}
- sqlite3_close(pDest);
+ close_db(pDest);
}else
if( c=='b' && n>=3 && strncmp(azArg[0], "bail", n)==0 ){
@@ -6486,7 +6521,7 @@
int newFlag = 0; /* True to delete file before opening */
/* Close the existing database */
session_close_all(p);
- sqlite3_close(p->db);
+ close_db(p->db);
p->db = 0;
p->zDbFilename = 0;
sqlite3_free(p->zFreeOnClose);
@@ -6516,7 +6551,7 @@
if( zNewFilename ){
if( newFlag ) shellDeleteFile(zNewFilename);
p->zDbFilename = zNewFilename;
- open_db(p, 1);
+ open_db(p, OPEN_DB_KEEPALIVE);
if( p->db==0 ){
utf8_printf(stderr, "Error: cannot open '%s'\n", zNewFilename);
sqlite3_free(zNewFilename);
@@ -6666,14 +6701,14 @@
rc = sqlite3_open(zSrcFile, &pSrc);
if( rc!=SQLITE_OK ){
utf8_printf(stderr, "Error: cannot open \"%s\"\n", zSrcFile);
- sqlite3_close(pSrc);
+ close_db(pSrc);
return 1;
}
open_db(p, 0);
pBackup = sqlite3_backup_init(p->db, zDb, pSrc, "main");
if( pBackup==0 ){
utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
- sqlite3_close(pSrc);
+ close_db(pSrc);
return 1;
}
while( (rc = sqlite3_backup_step(pBackup,100))==SQLITE_OK
@@ -6693,7 +6728,7 @@
utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
rc = 1;
}
- sqlite3_close(pSrc);
+ close_db(pSrc);
}else
if( c=='s' && strncmp(azArg[0], "scanstats", n)==0 ){
@@ -7377,7 +7412,10 @@
initText(&s);
open_db(p, 0);
rc = sqlite3_prepare_v2(p->db, "PRAGMA database_list", -1, &pStmt, 0);
- if( rc ) return shellDatabaseError(p->db);
+ if( rc ){
+ sqlite3_finalize(pStmt);
+ return shellDatabaseError(p->db);
+ }
if( nArg>2 && c=='i' ){
/* It is an historical accident that the .indexes command shows an error
@@ -7385,6 +7423,7 @@
** command does not. */
raw_printf(stderr, "Usage: .indexes ?LIKE-PATTERN?\n");
rc = 1;
+ sqlite3_finalize(pStmt);
goto meta_command_exit;
}
for(ii=0; sqlite3_step(pStmt)==SQLITE_ROW; ii++){
@@ -8285,6 +8324,10 @@
int nCmd = 0;
char **azCmd = 0;
const char *zVfs = 0; /* Value of -vfs command-line option */
+#if !SQLITE_SHELL_IS_UTF8
+ char **argvToFree = 0;
+ int argcToFree = 0;
+#endif
setBinaryMode(stdin, 0);
setvbuf(stderr, 0, _IONBF, 0); /* Make sure stderr is unbuffered */
@@ -8308,7 +8351,9 @@
*/
#if !SQLITE_SHELL_IS_UTF8
sqlite3_initialize();
- argv = malloc(sizeof(argv[0])*argc);
+ argvToFree = malloc(sizeof(argv[0])*argc*2);
+ argcToFree = argc;
+ argv = argvToFree + argc;
if( argv==0 ) shell_out_of_memory();
for(i=0; i<argc; i++){
char *z = sqlite3_win32_unicode_to_utf8(wargv[i]);
@@ -8318,6 +8363,7 @@
argv[i] = malloc( n+1 );
if( argv[i]==0 ) shell_out_of_memory();
memcpy(argv[i], z, n+1);
+ argvToFree[i] = argv[i];
sqlite3_free(z);
}
sqlite3_shutdown();
@@ -8639,12 +8685,12 @@
" with \"%s\"\n", z);
return 1;
}
- open_db(&data, 0);
+ open_db(&data, OPEN_DB_ZIPFILE);
if( z[2] ){
argv[i] = &z[2];
- arDotCommand(&data, argv+(i-1), argc-(i-1));
+ arDotCommand(&data, 1, argv+(i-1), argc-(i-1));
}else{
- arDotCommand(&data, argv+i, argc-i);
+ arDotCommand(&data, 1, argv+i, argc-i);
}
readStdin = 0;
break;
@@ -8723,7 +8769,7 @@
set_table_name(&data, 0);
if( data.db ){
session_close_all(&data);
- sqlite3_close(data.db);
+ close_db(data.db);
}
sqlite3_free(data.zFreeOnClose);
find_home_dir(1);
@@ -8731,8 +8777,11 @@
data.doXdgOpen = 0;
clearTempFile(&data);
#if !SQLITE_SHELL_IS_UTF8
- for(i=0; i<argc; i++) free(argv[i]);
- free(argv);
+ for(i=0; i<argcToFree; i++) free(argvToFree[i]);
+ free(argvToFree);
#endif
+ /* Clear the global data structure so that valgrind will detect memory
+ ** leaks */
+ memset(&data, 0, sizeof(data));
return rc;
}
diff --git a/src/vdbeaux.c b/src/vdbeaux.c
index 210712a..4b07647 100644
--- a/src/vdbeaux.c
+++ b/src/vdbeaux.c
@@ -3917,13 +3917,10 @@
i64 y;
double s;
if( r<-9223372036854775808.0 ) return +1;
- if( r>9223372036854775807.0 ) return -1;
+ if( r>=9223372036854775808.0 ) return -1;
y = (i64)r;
if( i<y ) return -1;
- if( i>y ){
- if( y==SMALLEST_INT64 && r>0.0 ) return -1;
- return +1;
- }
+ if( i>y ) return +1;
s = (double)i;
if( s<r ) return -1;
if( s>r ) return +1;