From 0578248b082d605a86ac67cc7abdbd7d260f0aab Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 24 Oct 2013 15:20:20 +0000 Subject: [PATCH] Add the ".open" command to the command-line shell. FossilOrigin-Name: 21eccb919441bd111ba414dde3f00862822e2c99 --- manifest | 14 ++++++------- manifest.uuid | 2 +- src/shell.c | 58 ++++++++++++++++++++++++++++++++++++--------------- 3 files changed, 49 insertions(+), 25 deletions(-) diff --git a/manifest b/manifest index 5450a8543e..7e56b8018a 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Improve\ssupport\sfor\sthe\sSQLITE_OMIT_FLAG_PRAGMAS\scompile-time\soption. -D 2013-10-21T23:17:23.344 +C Add\sthe\s".open"\scommand\sto\sthe\scommand-line\sshell. +D 2013-10-24T15:20:20.917 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 0522b53cdc1fcfc18f3a98e0246add129136c654 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -219,7 +219,7 @@ F src/random.c 0b2dbc37fdfbfa6bd455b091dfcef5bdb32dba68 F src/resolve.c 572585a96bf282bb9c3d9e08785ec3cae21dc488 F src/rowset.c 64655f1a627c9c212d9ab497899e7424a34222e0 F src/select.c 15127b54cc11defb2cddef6914e1f384501a61c4 -F src/shell.c 6f11f0e9ded63d48e306f2c6858c521e568a47bb +F src/shell.c d5eebdc6034014103de2b9d58e1d3f6f7de0fb50 F src/sqlite.h.in 547a44dd4ff4d975e92a645ea2d609e543a83d0f F src/sqlite3.rc 11094cc6a157a028b301a9f06b3d03089ea37c3e F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc @@ -1126,7 +1126,7 @@ F tool/vdbe-compress.tcl f12c884766bd14277f4fcedcae07078011717381 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P 4bd592c8f0e011e203443a6e88008a61d6926df5 -R 53b76eeb5375ab8ab4a6606d590d0d10 -U mistachkin -Z 54790c9a063cf1ed56ef1eaa1dcf530f +P f1d8c3b07e61c5a8b39675d0d62876ca15e207f3 +R 669ddc5b90d3123c7996e141023f003e +U drh +Z eb67a516397c437f69feed70887b8d2e diff --git a/manifest.uuid b/manifest.uuid index 43f51523c1..7867b45ac4 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -f1d8c3b07e61c5a8b39675d0d62876ca15e207f3 \ No newline at end of file +21eccb919441bd111ba414dde3f00862822e2c99 \ No newline at end of file diff --git a/src/shell.c b/src/shell.c index 41ea56492e..26c38c59ea 100644 --- a/src/shell.c +++ b/src/shell.c @@ -436,6 +436,7 @@ struct callback_data { ** .explain ON */ char outfile[FILENAME_MAX]; /* Filename for *out */ const char *zDbFilename; /* name of the database file */ + char *zFreeOnClose; /* Filename to free when closing */ const char *zVfs; /* Name of VFS to use */ sqlite3_stmt *pStmt; /* Current statement if any. */ FILE *pLog; /* Write log output here */ @@ -1437,6 +1438,7 @@ static char zHelp[] = " tabs Tab-separated values\n" " tcl TCL list elements\n" ".nullvalue STRING Use STRING in place of NULL values\n" + ".open ?FILENAME? Close existing database and reopen FILENAME\n" ".output FILENAME Send output to FILENAME\n" ".output stdout Send output to the screen\n" ".print STRING... Print literal STRING\n" @@ -1470,7 +1472,7 @@ static int process_input(struct callback_data *p, FILE *in); ** 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(struct callback_data *p){ +static void open_db(struct callback_data *p, int keepAlive){ if( p->db==0 ){ sqlite3_initialize(); sqlite3_open(p->zDbFilename, &p->db); @@ -1482,6 +1484,7 @@ static void open_db(struct callback_data *p){ if( db==0 || SQLITE_OK!=sqlite3_errcode(db) ){ fprintf(stderr,"Error: unable to open database \"%s\": %s\n", p->zDbFilename, sqlite3_errmsg(db)); + if( keepAlive ) return; exit(1); } #ifndef SQLITE_OMIT_LOAD_EXTENSION @@ -1834,7 +1837,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){ sqlite3_close(pDest); return 1; } - open_db(p); + open_db(p, 0); pBackup = sqlite3_backup_init(pDest, "main", p->db, zDb); if( pBackup==0 ){ fprintf(stderr, "Error: %s\n", sqlite3_errmsg(pDest)); @@ -1866,7 +1869,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){ if( c=='d' && n>1 && strncmp(azArg[0], "databases", n)==0 && nArg==1 ){ struct callback_data data; char *zErrMsg = 0; - open_db(p); + open_db(p, 0); memcpy(&data, p, sizeof(data)); data.showHeader = 1; data.mode = MODE_Column; @@ -1883,7 +1886,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){ }else if( c=='d' && strncmp(azArg[0], "dump", n)==0 && nArg<3 ){ - open_db(p); + open_db(p, 0); /* When playing back a "dump", the content might appear in an order ** which causes immediate foreign key constraints to be violated. ** So disable foreign-key constraint enforcement to prevent problems. */ @@ -2002,7 +2005,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){ seenInterrupt = 0; memset(&sCsv, 0, sizeof(sCsv)); - open_db(p); + open_db(p, 0); nSep = strlen30(p->separator); if( nSep==0 ){ fprintf(stderr, "Error: non-null separator required for import\n"); @@ -2140,7 +2143,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){ if( c=='i' && strncmp(azArg[0], "indices", n)==0 && nArg<3 ){ struct callback_data data; char *zErrMsg = 0; - open_db(p); + open_db(p, 0); memcpy(&data, p, sizeof(data)); data.showHeader = 0; data.mode = MODE_List; @@ -2206,7 +2209,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){ char *zErrMsg = 0; zFile = azArg[1]; zProc = nArg>=3 ? azArg[2] : 0; - open_db(p); + open_db(p, 0); rc = sqlite3_load_extension(p->db, zFile, zProc, &zErrMsg); if( rc!=SQLITE_OK ){ fprintf(stderr, "Error: %s\n", zErrMsg); @@ -2272,6 +2275,26 @@ static int do_meta_command(char *zLine, struct callback_data *p){ "%.*s", (int)ArraySize(p->nullvalue)-1, azArg[1]); }else + if( c=='o' && strncmp(azArg[0], "open", n)==0 && n>=2 ){ + sqlite3 *savedDb = p->db; + const char *zSavedFilename = p->zDbFilename; + char *zNewFilename = 0; + p->db = 0; + if( nArg>=2 ){ + p->zDbFilename = zNewFilename = sqlite3_mprintf("%s", azArg[1]); + } + open_db(p, 1); + if( p->db!=0 ){ + sqlite3_close(savedDb); + sqlite3_free(p->zFreeOnClose); + p->zFreeOnClose = zNewFilename; + }else{ + sqlite3_free(zNewFilename); + p->db = savedDb; + p->zDbFilename = zSavedFilename; + } + }else + if( c=='o' && strncmp(azArg[0], "output", n)==0 && nArg==2 ){ if( p->outfile[0]=='|' ){ pclose(p->out); @@ -2355,7 +2378,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){ sqlite3_close(pSrc); return 1; } - open_db(p); + open_db(p, 0); pBackup = sqlite3_backup_init(p->db, zDb, pSrc, "main"); if( pBackup==0 ){ fprintf(stderr, "Error: %s\n", sqlite3_errmsg(p->db)); @@ -2385,7 +2408,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){ if( c=='s' && strncmp(azArg[0], "schema", n)==0 && nArg<3 ){ struct callback_data data; char *zErrMsg = 0; - open_db(p); + open_db(p, 0); memcpy(&data, p, sizeof(data)); data.showHeader = 0; data.mode = MODE_Semi; @@ -2516,7 +2539,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){ int nRow, nAlloc; char *zSql = 0; int ii; - open_db(p); + open_db(p, 0); rc = sqlite3_prepare_v2(p->db, "PRAGMA database_list", -1, &pStmt, 0); if( rc ) return rc; zSql = sqlite3_mprintf( @@ -2616,7 +2639,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){ int testctrl = -1; int rc = 0; int i, n; - open_db(p); + open_db(p, 0); /* convert testctrl text option to value. allow any unique prefix ** of the option name, or a numerical value. */ @@ -2715,7 +2738,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){ }else if( c=='t' && n>4 && strncmp(azArg[0], "timeout", n)==0 && nArg==2 ){ - open_db(p); + open_db(p, 0); sqlite3_busy_timeout(p->db, (int)integerValue(azArg[1])); }else @@ -2726,7 +2749,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){ }else if( c=='t' && strncmp(azArg[0], "trace", n)==0 && nArg>1 ){ - open_db(p); + open_db(p, 0); output_file_close(p->traceOut); p->traceOut = output_file_open(azArg[1]); #if !defined(SQLITE_OMIT_TRACE) && !defined(SQLITE_OMIT_FLOATING_POINT) @@ -2918,7 +2941,7 @@ static int process_input(struct callback_data *p, FILE *in){ if( nSql && line_contains_semicolon(&zSql[nSqlPrior], nSql-nSqlPrior) && sqlite3_complete(zSql) ){ p->cnt = 0; - open_db(p); + open_db(p, 0); BEGIN_TIMER; rc = shell_exec(p->db, zSql, shell_callback, p, &zErrMsg); END_TIMER; @@ -3245,7 +3268,7 @@ int main(int argc, char **argv){ ** to the sqlite command-line tool. */ if( access(data.zDbFilename, 0)==0 ){ - open_db(&data); + open_db(&data, 0); } /* Process the initialization file if there is one. If no -init option @@ -3325,7 +3348,7 @@ int main(int argc, char **argv){ rc = do_meta_command(z, &data); if( rc && bail_on_error ) return rc==2 ? 0 : rc; }else{ - open_db(&data); + open_db(&data, 0); rc = shell_exec(data.db, z, shell_callback, &data, &zErrMsg); if( zErrMsg!=0 ){ fprintf(stderr,"Error: %s\n", zErrMsg); @@ -3349,7 +3372,7 @@ int main(int argc, char **argv){ rc = do_meta_command(zFirstCmd, &data); if( rc==2 ) rc = 0; }else{ - open_db(&data); + open_db(&data, 0); rc = shell_exec(data.db, zFirstCmd, shell_callback, &data, &zErrMsg); if( zErrMsg!=0 ){ fprintf(stderr,"Error: %s\n", zErrMsg); @@ -3396,5 +3419,6 @@ int main(int argc, char **argv){ if( data.db ){ sqlite3_close(data.db); } + sqlite3_free(data.zFreeOnClose); return rc; }