Fix harmless compiler warnings. Enhance the CLI prompt mechanism to make

it more easily reusable by other projects, and to add the /h, /H, and /u
escape sequences.

FossilOrigin-Name: 354ce4f5e2a86b621b2058a6372495a5919cf3dc88ce1ed3637642f720c48002
This commit is contained in:
drh
2026-04-23 20:13:14 +00:00
parent 323b3fc121
commit 67d4e0226f
5 changed files with 177 additions and 91 deletions
+24 -23
View File
@@ -419,7 +419,7 @@ static void analyzeFunc(
int rc;
sqlite3_stmt *pStmt;
int n;
sqlite3_int64 i64;
sqlite3_int64 ii;
sqlite3_int64 pgsz;
sqlite3_int64 nPage;
sqlite3_int64 nPageInUse;
@@ -429,6 +429,7 @@ static void analyzeFunc(
Analysis s;
sqlite3_uint64 r[2];
(void)argc;
memset(&s, 0, sizeof(s));
s.db = sqlite3_context_db_handle(context);
s.context = context;
@@ -445,10 +446,10 @@ static void analyzeFunc(
sqlite3_result_text(context, "cannot analyze \"temp\"",-1,SQLITE_STATIC);
return;
}
i64 = 0;
rc = analysisSqlInt(&s,&i64,"SELECT 1 FROM pragma_database_list"
ii = 0;
rc = analysisSqlInt(&s,&ii,"SELECT 1 FROM pragma_database_list"
" WHERE name=%Q COLLATE nocase",s.zSchema);
if( rc || i64==0 ){
if( rc || ii==0 ){
analysisReset(&s);
sqlite3_result_text(context,"no such database",-1,SQLITE_STATIC);
return;
@@ -570,25 +571,25 @@ static void analyzeFunc(
analysisLine(&s, "Pages on the freelist", "%-11lld ", nFreeList);
analysisPercent(&s, (nFreeList*100.0)/(double)nPage);
i64 = 0;
rc = analysisSqlInt(&s, &i64, "PRAGMA \"%w\".auto_vacuum", s.zSchema);
ii = 0;
rc = analysisSqlInt(&s, &ii, "PRAGMA \"%w\".auto_vacuum", s.zSchema);
if( rc ) return;
if( i64==0 || nPage<=1 ){
i64 = 0;
if( ii==0 || nPage<=1 ){
ii = 0;
}else{
double rPtrsPerPage = pgsz/5;
double rAvPage = (nPage-1.0)/(rPtrsPerPage+1.0);
i64 = (sqlite3_int64)ceil(rAvPage);
ii = (sqlite3_int64)ceil(rAvPage);
}
analysisLine(&s, "Pages of auto-vacuum overhead", "%-11lld ", i64);
analysisPercent(&s, (i64*100.0)/(double)nPage);
analysisLine(&s, "Pages of auto-vacuum overhead", "%-11lld ", ii);
analysisPercent(&s, (ii*100.0)/(double)nPage);
i64 = 0;
rc = analysisSqlInt(&s, &i64,
ii = 0;
rc = analysisSqlInt(&s, &ii,
"SELECT count(*)+1 FROM \"%w\".sqlite_schema WHERE type='table'",
s.zSchema);
if( rc ) return;
analysisLine(&s, "Number of tables", "%lld\n", i64);
analysisLine(&s, "Number of tables", "%lld\n", ii);
nWORowid = 0;
rc = analysisSqlInt(&s, &nWORowid,
"SELECT count(*) FROM \"%w\".pragma_table_list WHERE wr",
@@ -596,7 +597,7 @@ static void analyzeFunc(
if( rc ) return;
if( nWORowid>0 ){
analysisLine(&s, "Number of WITHOUT ROWID tables", "%lld\n", nWORowid);
analysisLine(&s, "Number of rowid tables", "%lld\n", i64 - nWORowid);
analysisLine(&s, "Number of rowid tables", "%lld\n", ii - nWORowid);
}
nIndex = 0;
rc = analysisSqlInt(&s, &nIndex,
@@ -604,23 +605,23 @@ static void analyzeFunc(
s.zSchema);
if( rc ) return;
analysisLine(&s, "Number of indexes", "%lld\n", nIndex);
i64 = 0;
rc = analysisSqlInt(&s, &i64,
ii = 0;
rc = analysisSqlInt(&s, &ii,
"SELECT count(*) FROM \"%w\".sqlite_schema"
" WHERE name GLOB 'sqlite_autoindex_*' AND type='index'",
s.zSchema);
if( rc ) return;
analysisLine(&s, "Number of defined indexes", "%lld\n", nIndex - i64);
analysisLine(&s, "Number of implied indexes", "%lld\n", i64);
analysisLine(&s, "Number of defined indexes", "%lld\n", nIndex - ii);
analysisLine(&s, "Number of implied indexes", "%lld\n", ii);
analysisLine(&s, "Size of the database in bytes", "%lld\n", pgsz*nPage);
i64 = 0;
rc = analysisSqlInt(&s, &i64,
ii = 0;
rc = analysisSqlInt(&s, &ii,
"SELECT sum(payload) FROM temp.%s"
" WHERE NOT is_index AND name NOT LIKE 'sqlite_schema'",
s.zSU);
if( rc ) return;
analysisLine(&s, "Bytes of payload", "%-11lld ", i64);
analysisPercent(&s, i64*100.0/(double)(pgsz*nPage));
analysisLine(&s, "Bytes of payload", "%-11lld ", ii);
analysisPercent(&s, ii*100.0/(double)(pgsz*nPage));
analysisTitle(&s, "Page counts for all tables with their indexes");
pStmt = analysisPrepare(&s,
+8 -8
View File
@@ -1,5 +1,5 @@
C Fix\sa\sbug\sin\s[dbc1d6f0a3452607]\sthat\sdisrupts\sthe\sdisplay\swhen\srunning\non\sa\sWindows\sconsole\s(not\sredirecting\sto\sa\sfile).
D 2026-04-23T20:06:16.114
C Fix\sharmless\scompiler\swarnings.\s\sEnhance\sthe\sCLI\sprompt\smechanism\sto\smake\nit\smore\seasily\sreusable\sby\sother\sprojects,\sand\sto\sadd\sthe\s/h,\s/H,\sand\s/u\nescape\ssequences.
D 2026-04-23T20:13:14.517
F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
@@ -358,7 +358,7 @@ F ext/jni/src/tests/000-001-ignored.test e17e874c6ab3c437f1293d88093cf06286083b6
F ext/jni/src/tests/900-001-fts.test bf0ce17a8d082773450e91f2388f5bbb2dfa316d0b676c313c637a91198090f0
F ext/misc/README.md 6243cdc4d7eb791c41ef0716f3980b8b5f6aa8c61ff76a3958cbf0031c6ebfa7
F ext/misc/amatch.c 8d237cc014b3736922c26a76a451050d244aa4980c47c531f368f817b1e77b49
F ext/misc/analyze.c 13caf932d591d7c0ce3f0470023a5c835aa24caddec673c41d296ac89de98220
F ext/misc/analyze.c 77e0f45a44c13d66f30922db553072305521c0fb3a448b920e641fccd2498527
F ext/misc/anycollseq.c 5ffdfde9829eeac52219136ad6aa7cd9a4edb3b15f4f2532de52f4a22525eddb
F ext/misc/appendvfs.c 9642c7a194a2a25dca7ad3e36af24a0a46d7702168c4ad7e59c9f9b0e16a3824
F ext/misc/base64.c 1445761667c16356e827fc6418294c869468be934429aaa8315035e76dd58acf
@@ -736,7 +736,7 @@ F src/random.c 606b00941a1d7dd09c381d3279a058d771f406c5213c9932bbd93d5587be4b9c
F src/resolve.c 928ff887f2a7c64275182060d94d06fdddbe32226c569781cf7e7edc6f58d7fd
F src/rowset.c 8432130e6c344b3401a8874c3cb49fefe6873fec593294de077afea2dce5ec97
F src/select.c 4c05cde130f26991b7411d8c6809e0630625e18078742c963a047b4b9cc01d49
F src/shell.c.in 19a71294b76b4a2dc75a9a5dfd5f4ac287c4fbbe489602e50b90d8146a8029a9
F src/shell.c.in 32751b1cd5f2aca27d56316195f452082c540435ccd5c97a45a0a77ded627618
F src/sqlite.h.in 39d2e09114d2bdb7afd998f4a469c8f8cd065f8093835a7d0422f260fc78fb4f
F src/sqlite3.rc 015537e6ac1eec6c7050e17b616c2ffe6f70fca241835a84a4f0d5937383c479
F src/sqlite3ext.h 9788c301f95370fa30e808861f1d2e6f022a816ddbe2a4f67486784c1b31db2e
@@ -1624,7 +1624,7 @@ F test/sharedA.test 64bdd21216dda2c6a3bd3475348ccdc108160f34682c97f2f51c19fc0e21
F test/sharedB.test 1a84863d7a2204e0d42f2e1606577c5e92e4473fa37ea0f5bdf829e4bf8ee707
F test/shared_err.test 32634e404a3317eeb94abc7a099c556a346fdb8fb3858dbe222a4cbb8926a939
F test/sharedlock.test 5ede3c37439067c43b0198f580fd374ebf15d304
F test/shell-prompt.sql c3517832b8570025619707bf5883847f6894e958bd92a5e0d2e2f157f768c2a1
F test/shell-prompt.sql 489c77873ac415d998fe890e9df16e91feadf4fb03d91e60987af59630e8452f
F test/shell1.test c84eff209f93ad17ccdf7e1634969fc8231684254edeb21d9b13d67c3179cdb5
F test/shell2.test dc541d2681503e55466a24d35a4cbf8ca5b90b8fcdef37fc4db07373a67d31d3
F test/shell3.test 91efdd545097a61a1f72cf79c9ad5b49da080f3f10282eaf4c3c272cd1012db2
@@ -2203,8 +2203,8 @@ F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee
F tool/warnings.sh a554d13f6e5cf3760f041b87939e3d616ec6961859c3245e8ef701d1eafc2ca2
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
F tool/winmain.c 00c8fb88e365c9017db14c73d3c78af62194d9644feaf60e220ab0f411f3604c
P e5f8840d11c1863cfc5c0b4a3d16c9ec9ab6ca6ecb7ff1a3a9a237715eed5d30
R 7b58cc45620d6bb85954ae1a36085212
P 75b5df2b0046827e985712b5725488b59667e2cfd171cde9f1194f2917165205
R fd058ac589f9118b570fa976b65d4d70
U drh
Z e5ccd1ba0db6445e6ed11772a6126f1d
Z 922f9e0b5137212d3bd8a15f5e6080f6
# Remove this line to create a well-formed Fossil manifest.
+1 -1
View File
@@ -1 +1 @@
75b5df2b0046827e985712b5725488b59667e2cfd171cde9f1194f2917165205
354ce4f5e2a86b621b2058a6372495a5919cf3dc88ce1ed3637642f720c48002
+126 -41
View File
@@ -922,46 +922,76 @@ static char *local_getline(char *zLine, FILE *in){
}
/*
** The default prompts.
** The SQLITE_PS_APPDEF macro should be set to the name of a function
** that accepts a single "int" argument and returns a "const char *"
** that is guaranteed to be non-NULL. The value returned depends on the
** argument:
**
** 1 Default main prompt.
** 2 Default continuation prompt.
** 3 Environment variable to override main prompt ("SQLITE_PS1")
** 4 Environment variable to override continuatio ("SQLITE_PS2")
** 'A' The name of the application. (Nominally "SQLite")
** 'V' Version number including patch. (ex: "3.54.1")
** 'v' Version number without patch. (ex: "3.54")
**
*/
#ifndef SQLITE_PS1
# define SQLITE_PS1 "/A /f> "
#endif
#ifndef SQLITE_PS2
# define SQLITE_PS2 "/B.../H> "
#endif
/*
** Redefinable name of a function that is used to find the text for
** some prompt expansions: /A /V /v
*/
#ifndef SQLITE_PS_APPDEF
# define SQLITE_PS_APPDEF shellPromptAppDef
#else
#ifdef SQLITE_PS_APPDEF
extern const char *SQLITE_PS_APPDEF(int);
#else
# define SQLITE_PS_APPDEF shellPromptAppDef
static const char *shellPromptAppDef(int c){
switch( c ){
/* The default main prompt string */
case 1:
#if defined(SQLITE_PS1)
return SQLITE_PS1;
#elif defined(SQLITE_PS_NOANSI)
return "/A-/v /~> ";
#else
return "/e[1;/x33/:36/;m/A-/v /~>/e[0m ";
#endif
/*
** Return a string appropriate for various prompt expansion characters.
** Return an empty string at least. Always return a valid string pointer.
*/
static const char *shellPromptAppDef(int c){
if( c=='A' ) return "SQLite";
if( c=='V' ) return sqlite3_libversion();
if( c=='v' ){
static char zRel[16];
const char *zF = sqlite3_libversion();
const char *zD = strrchr(zF,'.');
if( zD && (size_t)(zD-zF)<sizeof(zRel)-1 ){
memcpy(zRel,zF,(size_t)(zD-zF));
zRel[(size_t)(zD-zF)] = 0;
return zRel;
}else{
return zF;
/* The default continuation prompt string */
case 2:
#if defined(SQLITE_PS2)
return SQLITE_PS2;
#elif defined(SQLITE_PS_NOANSI)
return "/B/C> ";
#else
return "/B/e[1;/x33/:36/;m/C>/e[0m ";
#endif
/* Name of environment variables that override the prompt strings
** of cases 1 and 2 */
case 3: return "SQLITE_PS1";
case 4: return "SQLITE_PS2";
/* Name of the application */
case 'A': return "SQLite";
/* Full version number of the application, including patch level */
case 'V': return sqlite3_libversion();
/* Version number without the patch level */
case 'v': {
static char zRel[16];
const char *zF = sqlite3_libversion();
const char *zD = strrchr(zF,'.');
if( zD && (size_t)(zD-zF)<sizeof(zRel)-1 ){
memcpy(zRel,zF,(size_t)(zD-zF));
zRel[(size_t)(zD-zF)] = 0;
return zRel;
}else{
return zF;
}
}
}
return "";
}
#endif /* !defined(SQLITE_PS_APPDEF) */
/*
** Return the raw (unexpanded) prompt string. This will be the
@@ -981,14 +1011,10 @@ static const char *prompt_string(ShellState *p, int bContinue){
return p->azPrompt[bContinue];
}
#ifndef SQLITE_SHELL_FIDDLE
zPS = getenv(bContinue ? "SQLITE_PS2" : "SQLITE_PS1");
zPS = getenv(SQLITE_PS_APPDEF(3+bContinue));
if( zPS ) return zPS;
#endif
if( bContinue ){
return SQLITE_PS2;
}else{
return SQLITE_PS1;
}
return SQLITE_PS_APPDEF(1+bContinue);
}
/*
@@ -1012,6 +1038,45 @@ static const char *prompt_filename(ShellState *p){
return zFN;
}
/*
** Return the name of the computer on which we are running.
*/
static const char *prompt_hostname(int bFull){
#ifdef _WIN32
const char *z = getenv("COMPUTERNAME");
if( z==0 || z[0]==0 ) z = "?";
return z;
#else
static char zHost[256];
if( gethostname(zHost, sizeof(zHost)) ){
zHost[0] = '?';
zHost[1] = 0;
}
if( !bFull ){
char *p = strchr(zHost,'.');
if( p ) p[0] = 0;
}
return zHost;
#endif
}
/*
** Return the username. This is taken from an environment variable
** and can thus be forged. Do not depend on it.
*/
static const char *prompt_user(void){
const char *z;
#ifdef _WIN32
z = getenv("USERNAME");
if( z==0 || z[0]==0 ) z = "?";
#else
z = getenv("USER");
if( z==0 || z[0]==0 ) z = getenv("LOGNAME");
if( z==0 || z[0]==0 ) z = "?";
#endif
return z;
}
/*
** Expand escapes in the given input prompt string. Return the
** expanded prompt in memory obtained from sqlite3_malloc(). The
@@ -1157,8 +1222,28 @@ static char *expand_prompt(
continue;
}
if( c=='H' ){
/* /H becomes text needed to terminate current input */
if( c=='h' || c=='H' ){
/* /h becomes hostname up to the first '.' */
/* /H is the full hostname */
if( !mOff ){
sqlite3_str_appendall(pOut, prompt_hostname(c=='H'));
}
zPrompt += 2;
i = -1;
continue;
}
if( c=='u' ){
/* /u becomes the username (taken from environment variables) */
if( !mOff ){
sqlite3_str_appendall(pOut, prompt_user());
}
zPrompt += 2;
i = -1;
continue;
}
if( c=='C' ){
/* /C becomes text needed to terminate current input */
if( !mOff ){
sqlite3_int64 R = zPrior ? sqlite3_incomplete(zPrior) : 0;
int cc = (R>>16)&0xff;
@@ -13610,7 +13695,7 @@ int SQLITE_CDECL main(int argc, char **argv){
#ifndef SQLITE_SHELL_FIDDLE
sqlite3_appendvfs_init(0,0,0);
#ifdef SQLITE_DEBUG
sqlite3_auto_extension( (void (*)())auto_ext_leak_tester );
sqlite3_auto_extension( (void(*)(void))auto_ext_leak_tester );
#endif
#endif
modeDefault(&data);
+18 -18
View File
@@ -28,9 +28,9 @@
.testcase 110
.prompt --show
.check <<END
Main prompt: '/A /f> '
Continuation: '/B.../H> '
.check --glob <<END
Main prompt: '*/A*/~>*'
Continuation: '/B*/C>*'
END
.testcase 111
.prompt 'abc> ' '123> ' -show
@@ -47,9 +47,9 @@ Continuation: '--second'
END
.testcase 113
.prompt --reset --show
.check <<END
Main prompt: '/A /f> '
Continuation: '/B.../H> '
.check --glob <<END
Main prompt: '*/A*/~>*'
Continuation: '/B*/C>*'
END
.testcase 120 --error-prefix ERROR:
@@ -64,9 +64,9 @@ END
.check ''
.testcase 122
.prompt --show
.check <<END
.check --glob <<END
Main prompt: 'show'
Continuation: '/B.../H> '
Continuation: '/B*/C>*'
END
.testcase 130
@@ -90,31 +90,31 @@ END
.testcase 1000
SELECT shell_prompt_test(NULL);
.check 'SQLite test.db> ';
.check --glob '*SQLite-3*test.db>*';
.testcase 1001
SELECT shell_prompt_test(NULL,'SELECT');
.check ' ...;> ';
.check --glob ' *;>*';
.testcase 1002
SELECT shell_prompt_test(NULL,'SELECT ((("');
.check ' ...")));> ';
.check --glob ' *[ m]")));>*';
.testcase 1003
SELECT shell_prompt_test(NULL,'SELECT ((()[');
.check ' ...]));> ';
.check --glob ' *[ m]]));>*';
.testcase 1004
SELECT shell_prompt_test(NULL,'SELECT ''');
.check " ...';> ";
.check --glob " *[ m]';>*";
.testcase 1005
SELECT shell_prompt_test(NULL,'CREATE TRIGGER t1 BEGIN');
.check " ...;END;> ";
.check --glob " *[ m];END;>*";
.testcase 1006
SELECT shell_prompt_test(NULL,'CREATE TRIGGER t1 BEGIN SELECT ((([');
.check " ...])));END;> ";
.check --glob " *[ m]])));END;>*";
.testcase 1007
SELECT shell_prompt_test(NULL,'CREATE TRIGGER t1 BEGIN SELECT ((/*a(((''bc');
.check " ...*/));END;> ";
.check --glob " *[ m][*]/));END;>*";
.testcase 1008
SELECT shell_prompt_test(NULL,'CREATE TRIGGER t1 BEGIN SELECT 1;');
.check " ...END;> ";
.check --glob " *[ m]END;>*";
.testcase 2000
.prompt 'SQLite/x-txn$/:>/; '
@@ -135,7 +135,7 @@ SELECT shell_prompt_test(NULL);
.testcase 2004
.prompt --reset
SELECT shell_prompt_test(NULL);
.check 'SQLite test.db> ';
.check --glob '*SQLite-3.# *[/\]test.db>*';
.testcase 3000
SELECT shell_prompt_test('(/A-/V)');