From: larrybr Date: Sun, 6 Feb 2022 14:30:16 +0000 (+0000) Subject: CLI extended parsing and .x features mostly tested X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=4af7ea5b4c362945f4135e2927b821fd94f4025a;p=thirdparty%2Fsqlite.git CLI extended parsing and .x features mostly tested FossilOrigin-Name: 9c664984fd61d5858b436952d876bf3560333ee0edd8e1956cfe74cf9649511d --- diff --git a/manifest b/manifest index e7cb304375..33ec5c364d 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Sync\swith\strunk.\sMore\sshell9.test\stests\sto\scome. -D 2022-02-06T00:07:18.666 +C CLI\sextended\sparsing\sand\s.x\sfeatures\smostly\stested +D 2022-02-06T14:30:16.552 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -553,7 +553,7 @@ F src/random.c 097dc8b31b8fba5a9aca1697aeb9fd82078ec91be734c16bffda620ced7ab83c F src/resolve.c 868a88d47b11f4f6b8b413db72c9290c211972ee91316c1ece318846600ff725 F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92 F src/select.c 3baa9dd8cf240654773c7974e2bcce398ac9dd24419c36684156963defe43b35 -F src/shell.c.in 537c1cfe3e7b90c94dbddf6226b951154cdb239f755a883008223296f5e07f28 x +F src/shell.c.in 683c927a205999a3a13b268762de0309427d2f474ac1bd44d97c22b8064b1128 x F src/sqlite.h.in 800d6509517d383d38188e71bb5f1802c7db097a1282af7bf5d6c9a6da5a15ed F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h a95cb9ed106e3d39e2118e4dcc15a14faec3fa50d0093425083d340d9dfd96e6 @@ -1395,7 +1395,7 @@ F test/shell5.test b85069bfcf3159b225228629ab2c3e69aa923d098fea8ea074b5dcd743522 F test/shell6.test 1ceb51b2678c472ba6cf1e5da96679ce8347889fe2c3bf93a0e0fa73f00b00d3 F test/shell7.test 115132f66d0463417f408562cc2cf534f6bbc6d83a6d50f0072a9eb171bae97f F test/shell8.test 388471d16e4de767333107e30653983f186232c0e863f4490bb230419e830aae -F test/shell9.test 05f656a4c61b6e17b36a8cf7a70edffa6a77348bf4d633fb5cefb86b0127ce6b +F test/shell9.test 7fbfb85a2a9c2ea29d96cfa9ae2a116ecba7b0261ee366ed0d650c4c9054ba5c F test/shmlock.test 3dbf017d34ab0c60abe6a44e447d3552154bd0c87b41eaf5ceacd408dd13fda5 F test/shortread1.test bb591ef20f0fd9ed26d0d12e80eee6d7ac8897a3 F test/show_speedtest1_rtree.tcl 32e6c5f073d7426148a6936a0408f4b5b169aba5 @@ -1944,8 +1944,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 53d4582a0e9dab594264a5125324e1fab476e5fd806ebc61bd5fc6ffff10e34b 5b8d2577907abda10de29884716bacc10bff0df1451228a0ac40342dbea6d589 -R 57d729c30b618aa6811994c900b4082b +P 2e72dc4621bcccd6ef4f01d059ff052bc39b8ea122b006d842be6102736460f4 +R 25fb77e100f746489d50fee668ec40ea U larrybr -Z 99e81bee1944eeeb26bfd2cd711be880 +Z 7b3a3cb6deab772402e5b78d5f0789c5 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index b5bbc9a1b4..80ab8ac2b8 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -2e72dc4621bcccd6ef4f01d059ff052bc39b8ea122b006d842be6102736460f4 \ No newline at end of file +9c664984fd61d5858b436952d876bf3560333ee0edd8e1956cfe74cf9649511d \ No newline at end of file diff --git a/src/shell.c.in b/src/shell.c.in index 7ddd2dc7ce..feee1211c6 100755 --- a/src/shell.c.in +++ b/src/shell.c.in @@ -3356,15 +3356,15 @@ static int param_table_exists( sqlite3 *db ){ ** tables. The table must be in the TEMP schema. Only rows with ** uses=PTU_Binding are eligible for parameter binding. */ -static void bind_prepared_stmt(ShellState *pArg, sqlite3_stmt *pStmt){ +static void bind_prepared_stmt(sqlite3 *db, sqlite3_stmt *pStmt){ int nVar; int i; int rc; sqlite3_stmt *pQ = 0; nVar = sqlite3_bind_parameter_count(pStmt); - if( nVar==0 || !param_table_exists(pArg->db) ) return; /* Nothing to do */ - rc = sqlite3_prepare_v2(pArg->db, + if( nVar==0 || !param_table_exists(db) ) return; /* Nothing to do */ + rc = sqlite3_prepare_v2(db, "SELECT value FROM "PARAM_TABLE_SNAME " WHERE key=?1 AND uses=0", -1, &pQ, 0); if( rc || pQ==0 ) return; @@ -4153,7 +4153,7 @@ static int shell_exec( } } - bind_prepared_stmt(pArg, pStmt); + bind_prepared_stmt(pArg->db, pStmt); exec_prepared_stmt(pArg, pStmt); explain_data_delete(pArg); eqp_render(pArg); @@ -4636,9 +4636,10 @@ static const char *(azHelp[]) = { " -e Send output to the system text editor", " -x Send output as CSV to a spreadsheet", ".parameter CMD ... Manage SQL parameter bindings and scripts table", - " clear ?NAMES? Erase some or all named parameters", + " clear ?NAMES? Erase all or only given named parameters", #ifndef SQLITE_NOHAVE_SYSTEM - " edit NAME Use edit() to create or alter parameter NAME", + " edit ?OPT? NAME ... Use edit() to create or alter parameter NAME", + " OPT may be -t or -e to use edited value as text or evaluate it first.", #endif " init Initialize TEMP table for bindings and scripts", " list List parameters table binding and script values", @@ -6085,11 +6086,12 @@ static void output_reset(ShellState *p){ /* ** Run an SQL command and return the single integer result. +** No parameter binding is done. */ -static int db_int(ShellState *p, const char *zSql){ +static int db_int(sqlite3 *db, const char *zSql){ sqlite3_stmt *pStmt; int res = 0; - sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); + sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0); if( pStmt && sqlite3_step(pStmt)==SQLITE_ROW ){ res = sqlite3_column_int(pStmt,0); } @@ -6097,6 +6099,26 @@ static int db_int(ShellState *p, const char *zSql){ return res; } +/* +** Run an SQL command and return the single text result, +** Parameter binding is done iff bBind is true. +** The return must be freed by caller. +*/ +static char *db_text(sqlite3 *db, const char *zSql, int bBind){ + sqlite3_stmt *pStmt; + char *zRes = 0; + sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0); + if( pStmt ){ + if( bBind ) bind_prepared_stmt(db, pStmt); + if( sqlite3_step(pStmt)==SQLITE_ROW ){ + zRes = sqlite3_mprintf("%s", sqlite3_column_text(pStmt,0)); + shell_check_oom(zRes); + } + } + sqlite3_finalize(pStmt); + return zRes; +} + /* ** Convert a 2-byte or 4-byte big-endian integer into a native integer */ @@ -6194,7 +6216,7 @@ static int shell_dbinfo_command(ShellState *p, int nArg, char **azArg){ } for(i=0; idb, zSql); sqlite3_free(zSql); utf8_printf(p->out, "%-20s %d\n", aQuery[i].zName, val); } @@ -8460,34 +8482,57 @@ static int parameters_save(sqlite3 *db, const char *azArg[], int nArg){ static int edit_one_param(sqlite3 *db, char *name, int eval, ParamTableUse uses, const char * zEditor){ struct param_row paramVU = {0,0,0}; + int rc; + char * zVal = 0; char * zSql = sqlite3_mprintf ("SELECT value, uses FROM " PARAM_TABLE_SNAME " WHERE key=%Q", name); shell_check_oom(zSql); sqlite3_exec(db, zSql, param_find_callback, ¶mVU, 0); sqlite3_free(zSql); assert(paramVU.hits<2); - if( eval!=0 ){ - /* ToDo: Run an eval-like update, leaving as-is if it's a bad expr. */ - // int rv = edit_one_param(db, name, 0, uses); - } if( paramVU.hits==1 && paramVU.uses==uses){ /* Editing an existing value of same kind. */ sqlite3_free(paramVU.value); - zSql = sqlite3_mprintf - ("UPDATE "PARAM_TABLE_SNAME" SET value=edit(value, %Q) WHERE" - " key=%Q AND uses=%d", zEditor, name, uses); + if( eval!=0 ){ + zSql = sqlite3_mprintf + ("SELECT edit(value, %Q) FROM " PARAM_TABLE_SNAME + " WHERE key=%Q AND uses=%d", zEditor, name, uses); + zVal = db_text(db, zSql, 1); + sqlite3_free(zSql); + zSql = sqlite3_mprintf + ("UPDATE "PARAM_TABLE_SNAME" SET value=(SELECT %s) WHERE" + " key=%Q AND uses=%d", zVal, name, uses); + }else{ + zSql = sqlite3_mprintf + ("UPDATE "PARAM_TABLE_SNAME" SET value=edit(value, %Q) WHERE" + " key=%Q AND uses=%d", zEditor, name, uses); + } }else{ /* Editing a new value of same kind. */ assert(paramVU.value==0 || paramVU.uses!=uses); - zSql = sqlite3_mprintf - ("INSERT INTO "PARAM_TABLE_SNAME"(key,value,uses)" - " VALUES (%Q,edit('-- %q%s', %Q),%d)", - name, name, "\n", zEditor, uses); + if( eval!=0 ){ + zSql = sqlite3_mprintf + ("SELECT edit('-- %q%s', %Q)", name, "\n", zEditor); + zVal = db_text(db, zSql, 1); + sqlite3_free(zSql); + zSql = sqlite3_mprintf + ("INSERT INTO "PARAM_TABLE_SNAME"(key,value,uses)" + " VALUES (%Q,(SELECT %s LIMIT 1),%d)", + name, zVal, uses); + }else{ + zSql = sqlite3_mprintf + ("INSERT INTO "PARAM_TABLE_SNAME"(key,value,uses)" + " VALUES (%Q,edit('-- %q%s', %Q),%d)", + name, name, "\n", zEditor, uses); + } } shell_check_oom(zSql); - sqlite3_exec(db, zSql, 0, 0, 0); + if( eval!=0 ){ + } + rc = sqlite3_exec(db, zSql, 0, 0, 0); sqlite3_free(zSql); - return 0; /* ToDo: add some error checks */ + sqlite3_free(zVal); + return rc!=SQLITE_OK; } #endif @@ -8563,7 +8608,7 @@ static int param_set(sqlite3 *db, char cCast, char *zValue = (zValGlom==0)? *valBeg : zValGlom; if( cCast ){ struct ParamSetOpts *pSO = param_set_opts; - for(; param_set_opts-pSO < ArraySize(param_set_opts); ++pSO ){ + for(; pSO-param_set_opts < ArraySize(param_set_opts); ++pSO ){ if( cCast==pSO->cCast ){ zCastTo = pSO->zTypename; needsEval = pSO->evalKind > 0; @@ -8623,8 +8668,8 @@ static void list_params(ShellState *p, ParamTableUse ptu){ if( len ){ utf8_printf(p->out, "%-*s %-8s %s\n", len, "name", "usage", "value"); rc = sqlite3_prepare_v2 - (p->db, "SELECT key, uses, quote(value) FROM " - PARAM_TABLE_SNAME" WHERE ?1=3 OR uses=?1", -1, &pStmt, 0); + (p->db, "SELECT key, uses, quote(value) FROM " PARAM_TABLE_SNAME + " WHERE ?1=3 OR uses=?1 ORDER BY key", -1, &pStmt, 0); sqlite3_bind_int(pStmt, 1, ptu); while( rc==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW ){ ParamTableUse ptux = sqlite3_column_int(pStmt,1); @@ -10381,7 +10426,7 @@ static int do_meta_command(char *zLine, ShellState *p){ "Either set env-var VISUAL to name an" " editor and restart, or rerun\n " ".parameter edit with an initial " - "edit option, --editor=EDITOR_NAME .\n"); + "edit option, --editor=EDITOR_COMMAND .\n"); rc = 1; goto meta_command_exit; } @@ -12527,7 +12572,7 @@ static int process_input(ShellState *p){ break; case Cmd: echo_group_input(p, *pzLineUse); - switch( do_meta_command(*pzLineUse, p) ){ + switch( do_meta_command(*pzLineUse+ndcLeadWhite, p) ){ default: ++nErrors; /* fall thru */ case 0: break; case 2: bExitDemand = 1; break; @@ -12839,6 +12884,7 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){ char *zErrMsg = 0; ShellState data; const char *zInitFile = 0; + int bQuiet = 0; /* for testing, to suppress banner and history actions */ int i; int rc = 0; int warnInmemoryDb = 0; @@ -12939,7 +12985,8 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){ /* Do an initial pass through the command-line argument to locate ** the name of the database file, the name of the initialization file, ** the size of the alternative malloc heap, - ** and the first command to execute. + ** the first command to execute, + ** and whether testing certain interactive behavior. */ verify_uninitialized(); for(i=1; i" + return 1 + } +} elseif {$::tcl_platform(platform)=="windows"} { + proc set_ed {sayWhat} { + global env + set env(VISUAL) "echo SELECT $sayWhat ; >" + return 1 + } +} else { return 0 } + +if {[set_ed @name]} { + set cmds { + .pa set @name Fido + .pa edit -t dog + .x dog +} + do_test shell9-3.4 { + set res [catchcmd ":memory: -quiet 1 -shxopts 1 -interactive" $cmds] + } {0 Fido} +} + #---------------------------------------------------------------------------- # Test cases shell9-4.*: .parameter save/load operation +set cmds { + .pa set -t x '.print Ex' + .pa set -i $n 7 + .pa save xn.db + .pa save x.db x + .pa clear + .pa load xn.db + .pa list + .pa clear + .pa load x.db + .pa list + .pa clear + .pa load xn.db $n + .pa list +} +do_test shell9-4.1 { + set res [catchcmd ":memory: -shxopts 1" $cmds] +} {0 {name usage value +$n binding 7 +x script '.print Ex' +name usage value +x script '.print Ex' +name usage value +$n binding 7}} + +forcedelete x.db xn.db + #---------------------------------------------------------------------------- # Test cases shell9-5.*: Ensure "dot" commands and SQL intermix ok. +set cmds { + .pa set -t mixed " + .print Hi. + select 'Hi.'; + .print 'Good\ + Bye.' + select 'Good'|| + ' Bye.'; + " + .x mixed +} +do_test shell9-5.1 { + set res [catchcmd ":memory: -shxopts 1" $cmds] +} {0 {Hi. +Hi. +Good Bye. +Good Bye.}} + #---------------------------------------------------------------------------- # Test cases shell9-6.*: .x command operation and refusal +set cmds { + .pa set -t $v '.print Ok' + .x $v +} +do_test shell9-6.1 { + set res [catchcmd ":memory: -bail -shxopts 1" $cmds] +} {1 {Skipping badly named $v. Run ".help x"}} finish_test