Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Move shell extension load functionality into its own .shxload command for usage and code simplicity. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | cli_extension |
Files: | files | file ages | folders |
SHA3-256: |
e2c8c88b4b4f2c23c42fb1fdb86c0ade |
User & Date: | larrybr 2022-04-17 19:22:42.509 |
Context
2022-04-17
| ||
21:03 | Get docs caught up with the .shxload change. (check-in: e21964480f user: larrybr tags: cli_extension) | |
19:22 | Move shell extension load functionality into its own .shxload command for usage and code simplicity. (check-in: e2c8c88b4b user: larrybr tags: cli_extension) | |
00:48 | For sqlite3x, rudimentary testing in place as make target shellxtest . More to come. (check-in: b73928befb user: larrybr tags: cli_extension) | |
Changes
Changes to Makefile.in.
︙ | ︙ | |||
1377 1378 1379 1380 1381 1382 1383 1384 | # A very fast test that checks basic sanity. The name comes from # the 60s-era electronics testing: "Turn it on and see if smoke # comes out." # smoketest: $(TESTPROGS) fuzzcheck$(TEXE) ./testfixture$(TEXE) $(TOP)/test/main.test $(TESTOPTS) shellxtest: $(TESTPROGS_SHX) | > > > > | | 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 | # A very fast test that checks basic sanity. The name comes from # the 60s-era electronics testing: "Turn it on and see if smoke # comes out." # smoketest: $(TESTPROGS) fuzzcheck$(TEXE) ./testfixture$(TEXE) $(TOP)/test/main.test $(TESTOPTS) TESTRUNS_SHX = \ $(TOP)/test/shell_x/shell9.test \ $(TOP)/test/shell_x/shell10.test shellxtest: $(TESTPROGS_SHX) ./testfixture$(TEXE) $(TESTRUNS_SHX) shelltest: $(TESTPROGS) ./testfixture$(TEXE) $(TOP)/test/permutations.test shell sqlite3_analyzer.c: sqlite3.c $(TOP)/src/tclsqlite.c $(TOP)/tool/spaceanal.tcl $(TOP)/tool/mkccode.tcl $(TOP)/tool/sqlite3_analyzer.c.in $(TCLSH_CMD) $(TOP)/tool/mkccode.tcl $(TOP)/tool/sqlite3_analyzer.c.in >sqlite3_analyzer.c |
︙ | ︙ |
Changes to src/shell.c.in.
︙ | ︙ | |||
1209 1210 1211 1212 1213 1214 1215 | */ #define NOT_IFDEF_BIT(x,bitnum) (x? (!(x & (1<<bitnum))) : !(x+0)) /* Whether build will include extended input parsing option */ #define SHEXT_PARSING_BIT 0 #define SHELL_EXTENDED_PARSING \ NOT_IFDEF_BIT(SHELL_OMIT_EXTENSIONS, SHEXT_PARSING_BIT) | | | 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 | */ #define NOT_IFDEF_BIT(x,bitnum) (x? (!(x & (1<<bitnum))) : !(x+0)) /* Whether build will include extended input parsing option */ #define SHEXT_PARSING_BIT 0 #define SHELL_EXTENDED_PARSING \ NOT_IFDEF_BIT(SHELL_OMIT_EXTENSIONS, SHEXT_PARSING_BIT) /* Whether build will include runtime extension via .shxload */ #define SHEXT_DYNEXT_BIT 1 #define SHELL_DYNAMIC_EXTENSION ( !SHELL_OMIT_LOAD_EXTENSION \ && NOT_IFDEF_BIT(SHELL_OMIT_EXTENSIONS, SHEXT_DYNEXT_BIT) ) /* Whether build will include expansion of variables in dot-commands */ #define SHEXT_VAREXP_BIT 2 #define SHELL_VARIABLE_EXPANSION \ NOT_IFDEF_BIT(SHELL_OMIT_EXTENSIONS, SHEXT_VAREXP_BIT) |
︙ | ︙ | |||
9946 9947 9948 9949 9950 9951 9952 9953 9954 9955 9956 9957 9958 9959 | return DCR_Error; }else{ sqlite3IoTrace = iotracePrintf; } } return DCR_Ok; } DISPATCHABLE_COMMAND( limits 5 1 3 ){ static const struct { const char *zLimitName; /* Name of a limit */ int limitCode; /* Integer code for that limit */ } aLimit[] = { { "length", SQLITE_LIMIT_LENGTH }, { "sql_length", SQLITE_LIMIT_SQL_LENGTH }, | > > > > > > > > > > > | 9946 9947 9948 9949 9950 9951 9952 9953 9954 9955 9956 9957 9958 9959 9960 9961 9962 9963 9964 9965 9966 9967 9968 9969 9970 | return DCR_Error; }else{ sqlite3IoTrace = iotracePrintf; } } return DCR_Ok; } /***************** * The .limits and .load commands */ COLLECT_HELP_TEXT[ ",limits ?LIMIT_NAME? Display limit selected by its name, or all limits", ".load FILE ?ENTRY? Load a SQLite extension library", " If ENTRY is provided, the entry point \"sqlite_ENTRY_init\" is called.", " Otherwise, the entry point name is derived from the FILE's name.", ]; DISPATCHABLE_COMMAND( limits 5 1 3 ){ static const struct { const char *zLimitName; /* Name of a limit */ int limitCode; /* Integer code for that limit */ } aLimit[] = { { "length", SQLITE_LIMIT_LENGTH }, { "sql_length", SQLITE_LIMIT_SQL_LENGTH }, |
︙ | ︙ | |||
10178 10179 10180 10181 10182 10183 10184 10185 10186 10187 10188 10189 10190 10191 | } }else{ *pzErr = smprintf("%s\n", sqlite3_errmsg(db)); } return DCR_Ok|(rc!=0); } DISPATCHABLE_COMMAND( log ? 2 2 ){ const char *zFile = azArg[1]; if( ISS(p)->bSafeMode ) return DCR_AbortError; output_file_close(ISS(p)->pLog); ISS(p)->pLog = output_file_open(zFile, 0); return DCR_Ok; | > > > > > > > > > > > > > > > | 10189 10190 10191 10192 10193 10194 10195 10196 10197 10198 10199 10200 10201 10202 10203 10204 10205 10206 10207 10208 10209 10210 10211 10212 10213 10214 10215 10216 10217 | } }else{ *pzErr = smprintf("%s\n", sqlite3_errmsg(db)); } return DCR_Ok|(rc!=0); } DISPATCHABLE_COMMAND( load ? 2 3 ){ const char *zFile = 0, *zProc = 0; int ai = 1, rc; if( ISS(p)->bSafeMode ) return DCR_AbortError; while( ai<nArg ){ const char *zA = azArg[ai++]; if( zFile==0 ) zFile = zA; else if( zProc==0 ) zProc = zA; else return DCR_TooMany|ai; } open_db(p, 0); rc = sqlite3_load_extension(DBX(p), zFile, zProc, pzErr); return DCR_Ok|(rc!=SQLITE_OK); } DISPATCHABLE_COMMAND( log ? 2 2 ){ const char *zFile = azArg[1]; if( ISS(p)->bSafeMode ) return DCR_AbortError; output_file_close(ISS(p)->pLog); ISS(p)->pLog = output_file_open(zFile, 0); return DCR_Ok; |
︙ | ︙ | |||
10253 10254 10255 10256 10257 10258 10259 | } if( zColSep!=0 ){ sqlite3_snprintf(sizeof(psi->colSeparator), psi->colSeparator, zColSep); } psi->mode = modeNominal; } | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 10279 10280 10281 10282 10283 10284 10285 10286 10287 10288 10289 10290 10291 10292 | } if( zColSep!=0 ){ sqlite3_snprintf(sizeof(psi->colSeparator), psi->colSeparator, zColSep); } psi->mode = modeNominal; } /***************** * The .mode command */ COLLECT_HELP_TEXT[ ".mode MODE ?OPTIONS? Set output mode", " MODE is one of:", " ascii Columns/rows delimited by 0x1F and 0x1E", |
︙ | ︙ | |||
12218 12219 12220 12221 12222 12223 12224 | shell_exec(p, zSql, 0); } sqlite3_free(zSql); return DCR_Ok; } /***************** | | < < < < < < < < < < < < | 12184 12185 12186 12187 12188 12189 12190 12191 12192 12193 12194 12195 12196 12197 12198 12199 12200 12201 12202 12203 12204 12205 12206 12207 12208 12209 | shell_exec(p, zSql, 0); } sqlite3_free(zSql); return DCR_Ok; } /***************** * The .selftest*, .shell, and .show commands */ CONDITION_COMMAND( selftest_bool defined(SQLITE_DEBUG) ); CONDITION_COMMAND( selftest_int defined(SQLITE_DEBUG) ); COLLECT_HELP_TEXT[ ",selftest ?OPTIONS? Run tests defined in the SELFTEST table", " Options:", " --init Create a new SELFTEST table", " -v Verbose output", ",selftest_bool ?ARGS? Show boolean values of ARGS as flag tokens", ",selftest_int ?ARGS? Show integer values of ARGS as integer tokens", ".show Show the current values for various settings", ]; DISPATCHABLE_COMMAND( selftest_bool 10 0 0 ){ int i, v; for(i=1; i<nArg; i++){ v = booleanValue(azArg[i]); utf8_printf(ISS(p)->out, "%s: %d 0x%x\n", azArg[i], v, v); |
︙ | ︙ | |||
12368 12369 12370 12371 12372 12373 12374 | sqlite3_finalize(pStmt); } /* End loop over k */ freeText(&str); utf8_printf(psi->out, "%d errors out of %d tests\n", nErr, nTest); return rc > 0; } | > > > | > > > > > > > > > > > > > > | < < > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 12322 12323 12324 12325 12326 12327 12328 12329 12330 12331 12332 12333 12334 12335 12336 12337 12338 12339 12340 12341 12342 12343 12344 12345 12346 12347 12348 12349 12350 12351 12352 12353 12354 12355 12356 12357 12358 12359 12360 12361 12362 12363 12364 12365 12366 12367 12368 12369 12370 12371 12372 12373 12374 12375 12376 12377 12378 12379 12380 12381 12382 12383 12384 12385 12386 12387 12388 12389 12390 12391 12392 12393 12394 12395 12396 12397 12398 12399 12400 12401 12402 12403 12404 12405 12406 12407 12408 12409 12410 12411 | sqlite3_finalize(pStmt); } /* End loop over k */ freeText(&str); utf8_printf(psi->out, "%d errors out of %d tests\n", nErr, nTest); return rc > 0; } /***************** * The .shell, .stats and .system commands */ CONDITION_COMMAND( shell !defined(SQLITE_NOHAVE_SYSTEM) ); CONDITION_COMMAND( system !defined(SQLITE_NOHAVE_SYSTEM) ); COLLECT_HELP_TEXT[ ".shell CMD ARGS... Run CMD ARGS... in a system shell", ".stats ?ARG? Show stats or turn stats on or off", " off Turn off automatic stat display", " on Turn on automatic stat display", " stmt Show statement stats", " vmstep Show the virtual machine step count only", ".system CMD ARGS... Run CMD ARGS... in a system shell", ]; #ifndef SQLITE_NOHAVE_SYSTEM static DotCmdRC shellOut(char *azArg[], int nArg, ShellExState *psx, char **pzErr){ char *zCmd; int i, x; if( ISS(psx)->bSafeMode ) return DCR_AbortError; zCmd = smprintf(strchr(azArg[1],' ')==0?"%s":"\"%s\"", azArg[1]); for(i=2; i<nArg; i++){ zCmd = smprintf(strchr(azArg[i],' ')==0?"%z %s":"%z \"%s\"", zCmd, azArg[i]); } shell_check_oom(zCmd); x = system(zCmd); sqlite3_free(zCmd); if( x ) raw_printf(STD_ERR, "%s command returns %d\n", azArg[0], x); return DCR_Ok; } #endif DISPATCHABLE_COMMAND( shell ? 2 0 ){ return shellOut(azArg, nArg, p, pzErr); } DISPATCHABLE_COMMAND( system ? 2 0 ){ return shellOut(azArg, nArg, p, pzErr); } /***************** * The .shxload and .shxopts commands */ CONDITION_COMMAND( shxload (SHELL_DYNAMIC_EXTENSION)!=0 ); CONDITION_COMMAND( shxopts (SHELL_EXTENSIONS)!=0 ); COLLECT_HELP_TEXT[ ".shxload FILE ?OPTIONS? Load a CLI shell extension library", " The first option may name the init function to be called upon load.", " Otherwise, its name is derived from FILE. Either way, the entry point" " \"sqlite_NAME_init\" is called. All options after \"--\" are passed to", " the extension's init function in the ShellExtensionLink struct.", ".shxopts ?SIGNED_OPTS? Show or alter shell extension options", " Run without arguments to see their self-descriptive names", ]; DISPATCHABLE_COMMAND( shxload 4 2 0 ){ const char *zFile = 0, *zProc = 0; int ai = 1, rc; char **pzExtArgs = 0; if( ISS(p)->bSafeMode ) return DCR_AbortError; while( ai<nArg ){ const char *zA = azArg[ai++]; if( strcmp(zA, "--")==0 ){ pzExtArgs = azArg + ai; break; } if( zFile==0 ) zFile = zA; else if( zProc==0 ) zProc = zA; } if( zFile==0 ) return DCR_Missing; if( pzExtArgs==0 ) pzExtArgs = azArg + ai; rc = load_shell_extension(p, zFile, zProc, pzErr, nArg-ai, pzExtArgs); return DCR_Ok|(rc!=SQLITE_OK); } DISPATCHABLE_COMMAND( shxopts 3 0 0 ){ static struct { const char *name; u8 mask; } shopts[] = { #if SHELL_DYNAMIC_COMMANDS {"dyn_cmds", 1<<SHEXT_DYNCMDS_BIT}, #endif #if SHELL_EXTENDED_PARSING {"parsing", 1<<SHEXT_PARSING_BIT}, |
︙ | ︙ | |||
12438 12439 12440 12441 12442 12443 12444 | } } return DCR_Ok; moan_error: raw_printf(STD_ERR, "Error: %s %s\n", zAbout, zMoan); return DCR_CmdErred; } | < < < | 12452 12453 12454 12455 12456 12457 12458 12459 12460 12461 12462 12463 12464 12465 | } } return DCR_Ok; moan_error: raw_printf(STD_ERR, "Error: %s %s\n", zAbout, zMoan); return DCR_CmdErred; } DISPATCHABLE_COMMAND( show ? 1 1 ){ static const char *azBool[] = { "off", "on", "trigger", "full"}; const char *zOut; ShellInState *psi = ISS(p); FILE *out = psi->out; int i; utf8_printf(out, "%12.12s: %s\n","echo", |
︙ | ︙ | |||
14011 14012 14013 14014 14015 14016 14017 | enum { HO_Tbd, HO_AllP, HO_AllX, HO_LikeP, HO_OneX, HO_LikeT, HO_Undoc } hoKind = bShowUndoc? HO_Undoc : HO_Tbd; if( hoKind==HO_Undoc ){ int ixct = 0; utf8_printf(out, "%s\n%s\n", | | | | 14022 14023 14024 14025 14026 14027 14028 14029 14030 14031 14032 14033 14034 14035 14036 14037 | enum { HO_Tbd, HO_AllP, HO_AllX, HO_LikeP, HO_OneX, HO_LikeT, HO_Undoc } hoKind = bShowUndoc? HO_Undoc : HO_Tbd; if( hoKind==HO_Undoc ){ int ixct = 0; utf8_printf(out, "%s\n%s\n", "The following commands are for SQLite diagnosis and internal testing.", "They are undocumented and subject to change without notice."); /* Bypass command lookup/resolution. This is just for internal commands. */ while( ixct<numCommands ){ struct CommandInfo *pci = &command_table[ixct]; const char *zH = pci->azHelp[0]; if( zH && *zH==cLead ){ utf8_printf(out, HELP_TEXT_FMTP, zH+1); zH = pci->azHelp[1]; |
︙ | ︙ |
Changes to test/shell_x/shell10.test.
︙ | ︙ | |||
38 39 40 41 42 43 44 | set rc [catch { exec $CLI :memory: << $cmd } msg] list $rc $msg } #---------------------------------------------------------------------------- # Test cases shell10-1.*: loading/running the {C,C++}-written test extensions set cmds ". | | > > > | | > > > | | 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 | set rc [catch { exec $CLI :memory: << $cmd } msg] list $rc $msg } #---------------------------------------------------------------------------- # Test cases shell10-1.*: loading/running the {C,C++}-written test extensions set cmds ". .shxload $blddir/test_shellext_cpp -- C++ .tables .quit " do_test shell10-1.1 { catch_mdb_cmd $cmds } {0 {BatBeing lives. Load arguments: C++ dbUser appeared dbUser closing dbShell closing BatBeing incommunicado. BatBeing unbecoming. BatBeing RIP.}} set cmds ". .shxload $blddir/test_shellext_c -- C .bat 10 20 30 .shxload $blddir/test_shellext_cpp -- C++ .bat 10 20 30 .tables " do_test shell10-1.2 { catch_mdb_cmd $cmds } {0 {Load arguments: C Column widths: 10 20 30 This execute has been called 1 times. BatBeing lives. Load arguments: C++ Column widths: 20 30 10 This execute has been called 2 times. dbUser appeared dbUser appeared dbUser closing dbUser closing dbShell closing dbShell closing BatBeing incommunicado. BatBeing incommunicado. BatBeing unbecoming. BatBeing unbecoming. BatBeing RIP.}} #---------------------------------------------------------------------------- # Test cases shell10-2.*: Tcl extension load and execution environment switching set ldtce ".shxload $blddir/tclshext" set cmds { .. puts Putsing for {set i 0} {$i<2} {incr i} {.print $i} puts [info commands ..] . |
︙ | ︙ |