1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-11-06 15:49:35 +03:00

Modify CLI to optionally display "stats".

FossilOrigin-Name: 419ce0ed89d10252492b2926817259899ee74e71
This commit is contained in:
shaneh
2010-07-28 16:05:34 +00:00
parent 39539804c6
commit 642d8b87fe
5 changed files with 281 additions and 31 deletions

View File

@@ -1,8 +1,5 @@
-----BEGIN PGP SIGNED MESSAGE----- C Modify\sCLI\sto\soptionally\sdisplay\s"stats".
Hash: SHA1 D 2010-07-28T16:05:35
C Lookaside\smemory\sis\snot\sused\sto\sstore\sschemas.\s\sChange\sthe\nSQLITE_DBSATUS_SCHEMA_USED\sdocumentation\sto\sreflect\sthis\sfact.
D 2010-07-28T15:52:09
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in ec08dc838fd8110fe24c92e5130bcd91cbb1ff2e F Makefile.in ec08dc838fd8110fe24c92e5130bcd91cbb1ff2e
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -172,7 +169,7 @@ F src/random.c cd4a67b3953b88019f8cd4ccd81394a8ddfaba50
F src/resolve.c 1c0f32b64f8e3f555fe1f732f9d6f501a7f05706 F src/resolve.c 1c0f32b64f8e3f555fe1f732f9d6f501a7f05706
F src/rowset.c 69afa95a97c524ba6faf3805e717b5b7ae85a697 F src/rowset.c 69afa95a97c524ba6faf3805e717b5b7ae85a697
F src/select.c 74fef1334bec27e606ef0b19e5c41cd0a639e69c F src/select.c 74fef1334bec27e606ef0b19e5c41cd0a639e69c
F src/shell.c fd4ccdb37c3b68de0623eb938a649e0990710714 F src/shell.c 74c82a4ecfd833900a5bacc5f32abd18b93079d1
F src/sqlite.h.in 373dedd8489ecd9dfb33d6d4378ee9f34a3c2386 F src/sqlite.h.in 373dedd8489ecd9dfb33d6d4378ee9f34a3c2386
F src/sqlite3ext.h 69dfb8116af51b84a029cddb3b35062354270c89 F src/sqlite3ext.h 69dfb8116af51b84a029cddb3b35062354270c89
F src/sqliteInt.h a9be6badc6cd6a3c1ae54475a98661cf351ecad5 F src/sqliteInt.h a9be6badc6cd6a3c1ae54475a98661cf351ecad5
@@ -826,9 +823,10 @@ F tool/mksqlite3internalh.tcl 7b43894e21bcb1bb39e11547ce7e38a063357e87
F tool/omittest.tcl 27d6f6e3b1e95aeb26a1c140e6eb57771c6d794a F tool/omittest.tcl 27d6f6e3b1e95aeb26a1c140e6eb57771c6d794a
F tool/opcodeDoc.awk b3a2a3d5d3075b8bd90b7afe24283efdd586659c F tool/opcodeDoc.awk b3a2a3d5d3075b8bd90b7afe24283efdd586659c
F tool/restore_jrnl.tcl 6957a34f8f1f0f8285e07536225ec3b292a9024a F tool/restore_jrnl.tcl 6957a34f8f1f0f8285e07536225ec3b292a9024a
F tool/shell1.test a738c71bc08ea9162baee9a14b3cf9994f181921 F tool/shell1.test 930444cadb71ce9ce78bc6cd14ec21e6b69776ea
F tool/shell2.test 5dc76b8005b465f420fed8241621da7513060ff3 F tool/shell2.test 5dc76b8005b465f420fed8241621da7513060ff3
F tool/shell3.test 4fad469e8003938426355afdf34155f08c587836 F tool/shell3.test 4fad469e8003938426355afdf34155f08c587836
F tool/shell4.test 0c82af2b7ce4e8e84565078a8690d1c46ec4e8f6
F tool/showdb.c 01c20e8181941b714fe07f72c64a7560fee17ff9 F tool/showdb.c 01c20e8181941b714fe07f72c64a7560fee17ff9
F tool/showjournal.c ec3b171be148656827c4949fbfb8ab4370822f87 F tool/showjournal.c ec3b171be148656827c4949fbfb8ab4370822f87
F tool/showwal.c f09e5a80a293919290ec85a6a37c85a5ddcf37d9 F tool/showwal.c f09e5a80a293919290ec85a6a37c85a5ddcf37d9
@@ -841,14 +839,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
P dbfbdb60c00b5aeae29c85acec0ae910b82dbdba P 07abfd5268564c18afd1074c2069d65c64f4b8eb
R db99aad6ade6f84bf548bac1cfdabd10 R 685d62477503a0184c458ad36031979f
U drh U shaneh
Z 87e1fd645b598e91788e82cf253f48fb Z 72eb3f2af1f8ca9f1cfbf340110562c7
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.6 (GNU/Linux)
iD8DBQFMUFIsoxKgR168RlERAicpAKCHH5v5EXtY/BOEo/lp30OkqVQK0wCgisZZ
js0Ce6xvYCx8PUpn/o0QZSQ=
=7PD/
-----END PGP SIGNATURE-----

View File

@@ -1 +1 @@
07abfd5268564c18afd1074c2069d65c64f4b8eb 419ce0ed89d10252492b2926817259899ee74e71

View File

@@ -398,6 +398,7 @@ struct previous_mode_data {
struct callback_data { struct callback_data {
sqlite3 *db; /* The database */ sqlite3 *db; /* The database */
int echoOn; /* True to echo input commands */ int echoOn; /* True to echo input commands */
int statsOn; /* True to display memory stats before each finalize */
int cnt; /* Number of records displayed so far */ int cnt; /* Number of records displayed so far */
FILE *out; /* Write results here */ FILE *out; /* Write results here */
int mode; /* An output mode setting */ int mode; /* An output mode setting */
@@ -961,6 +962,86 @@ static char *save_err_msg(
return zErrMsg; return zErrMsg;
} }
/*
** Display memory stats.
*/
static int display_stats(
sqlite3 *db, /* Database to query */
struct callback_data *pArg, /* Pointer to struct callback_data */
int bReset /* True to reset the stats */
){
int iCur;
int iHiwtr;
if( pArg && pArg->out ){
iHiwtr = iCur = -1;
sqlite3_status(SQLITE_STATUS_MEMORY_USED, &iCur, &iHiwtr, bReset);
fprintf(pArg->out, "Mem Used (Excludes Scratch/Pcache): %d (max %d) bytes\n", iCur, iHiwtr);
iHiwtr = iCur = -1;
sqlite3_status(SQLITE_STATUS_MALLOC_COUNT, &iCur, &iHiwtr, bReset);
fprintf(pArg->out, "Number of Allocations: %d (max %d)\n", iCur, iHiwtr);
/*
** Not currently used by the CLI.
** iHiwtr = iCur = -1;
** sqlite3_status(SQLITE_STATUS_PAGECACHE_USED, &iCur, &iHiwtr, bReset);
** fprintf(pArg->out, "Number of Pcache Pages Used: %d (max %d) pages\n", iCur, iHiwtr);
*/
iHiwtr = iCur = -1;
sqlite3_status(SQLITE_STATUS_PAGECACHE_OVERFLOW, &iCur, &iHiwtr, bReset);
fprintf(pArg->out, "Number of Pcache Overflow Bytes: %d (max %d) bytes\n", iCur, iHiwtr);
/*
** Not currently used by the CLI.
** iHiwtr = iCur = -1;
** sqlite3_status(SQLITE_STATUS_SCRATCH_USED, &iCur, &iHiwtr, bReset);
** fprintf(pArg->out, "Number of Scratch Allocations Used: %d (max %d)\n", iCur, iHiwtr);
*/
iHiwtr = iCur = -1;
sqlite3_status(SQLITE_STATUS_SCRATCH_OVERFLOW, &iCur, &iHiwtr, bReset);
fprintf(pArg->out, "Number of Scratch Overflow Bytes: %d (max %d) bytes\n", iCur, iHiwtr);
iHiwtr = iCur = -1;
sqlite3_status(SQLITE_STATUS_MALLOC_SIZE, &iCur, &iHiwtr, bReset);
fprintf(pArg->out, "Largest Allocation: %d bytes\n", iHiwtr);
iHiwtr = iCur = -1;
sqlite3_status(SQLITE_STATUS_PAGECACHE_SIZE, &iCur, &iHiwtr, bReset);
fprintf(pArg->out, "Largest Pcache Allocation: %d bytes\n", iHiwtr);
iHiwtr = iCur = -1;
sqlite3_status(SQLITE_STATUS_SCRATCH_SIZE, &iCur, &iHiwtr, bReset);
fprintf(pArg->out, "Largest Scratch Allocation: %d bytes\n", iHiwtr);
#ifdef YYTRACKMAXSTACKDEPTH
iHiwtr = iCur = -1;
sqlite3_status(SQLITE_STATUS_PARSER_STACK, &iCur, &iHiwtr, bReset);
fprintf(pArg->out, "Deepest Parser Stack: %d (max %d)\n", iCur, iHiwtr);
#endif
}
if( pArg && pArg->out && db ){
iHiwtr = iCur = -1;
sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_USED, &iCur, &iHiwtr, bReset);
fprintf(pArg->out, "Lookaside Slots Used: %d (max %d)\n", iCur, iHiwtr);
iHiwtr = iCur = -1;
sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_USED, &iCur, &iHiwtr, bReset);
fprintf(pArg->out, "Pcache Heap Usage: %d bytes\n", iCur);
iHiwtr = iCur = -1;
sqlite3_db_status(db, SQLITE_DBSTATUS_SCHEMA_USED, &iCur, &iHiwtr, bReset);
fprintf(pArg->out, "Schema Heap Usage: %d bytes\n", iCur);
iHiwtr = iCur = -1;
sqlite3_db_status(db, SQLITE_DBSTATUS_STMT_USED, &iCur, &iHiwtr, bReset);
fprintf(pArg->out, "Statement Heap/Lookaside Usage: %d bytes\n", iCur);
}
if( pArg && pArg->out && db && pArg->pStmt ){
iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_FULLSCAN_STEP, bReset);
fprintf(pArg->out, "Fullscan Steps: %d\n", iCur);
iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_SORT, bReset);
fprintf(pArg->out, "Sort Operations: %d\n", iCur);
iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_AUTOINDEX, bReset);
fprintf(pArg->out, "Autoindex Inserts: %d\n", iCur);
}
return 0;
}
/* /*
** Execute a statement or set of statements. Print ** Execute a statement or set of statements. Print
** any result rows/columns depending on the current mode ** any result rows/columns depending on the current mode
@@ -1000,8 +1081,14 @@ static int shell_exec(
continue; continue;
} }
/* save off the prepared statment handle and reset row count */
if( pArg ){
pArg->pStmt = pStmt;
pArg->cnt = 0;
}
/* echo the sql statement if echo on */ /* echo the sql statement if echo on */
if( pArg->echoOn ){ if( pArg && pArg->echoOn ){
const char *zStmtSql = sqlite3_sql(pStmt); const char *zStmtSql = sqlite3_sql(pStmt);
fprintf(pArg->out, "%s\n", zStmtSql ? zStmtSql : zSql); fprintf(pArg->out, "%s\n", zStmtSql ? zStmtSql : zSql);
} }
@@ -1029,11 +1116,6 @@ static int shell_exec(
for(i=0; i<nCol; i++){ for(i=0; i<nCol; i++){
azCols[i] = (char *)sqlite3_column_name(pStmt, i); azCols[i] = (char *)sqlite3_column_name(pStmt, i);
} }
/* save off the prepared statment handle and reset row count */
if( pArg ){
pArg->pStmt = pStmt;
pArg->cnt = 0;
}
do{ do{
/* extract the data and data types */ /* extract the data and data types */
for(i=0; i<nCol; i++){ for(i=0; i<nCol; i++){
@@ -1056,9 +1138,6 @@ static int shell_exec(
} }
} while( SQLITE_ROW == rc ); } while( SQLITE_ROW == rc );
sqlite3_free(pData); sqlite3_free(pData);
if( pArg ){
pArg->pStmt = NULL;
}
} }
}else{ }else{
do{ do{
@@ -1067,6 +1146,11 @@ static int shell_exec(
} }
} }
/* print usage stats if stats on */
if( pArg && pArg->statsOn ){
display_stats(db, pArg, 0);
}
/* Finalize the statement just executed. If this fails, save a /* Finalize the statement just executed. If this fails, save a
** copy of the error message. Otherwise, set zSql to point to the ** copy of the error message. Otherwise, set zSql to point to the
** next statement to execute. */ ** next statement to execute. */
@@ -1077,6 +1161,11 @@ static int shell_exec(
}else if( pzErrMsg ){ }else if( pzErrMsg ){
*pzErrMsg = save_err_msg(db); *pzErrMsg = save_err_msg(db);
} }
/* clear saved stmt handle */
if( pArg ){
pArg->pStmt = NULL;
}
} }
} /* end while */ } /* end while */
@@ -1256,6 +1345,7 @@ static char zHelp[] =
" LIKE pattern TABLE.\n" " LIKE pattern TABLE.\n"
".separator STRING Change separator used by output mode and .import\n" ".separator STRING Change separator used by output mode and .import\n"
".show Show the current values for various settings\n" ".show Show the current values for various settings\n"
".stats ON|OFF Turn stats on or off\n"
".tables ?TABLE? List names of tables\n" ".tables ?TABLE? List names of tables\n"
" If TABLE specified, only list tables matching\n" " If TABLE specified, only list tables matching\n"
" LIKE pattern TABLE.\n" " LIKE pattern TABLE.\n"
@@ -2001,6 +2091,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){
fprintf(p->out,"%9.9s: ", "separator"); fprintf(p->out,"%9.9s: ", "separator");
output_c_string(p->out, p->separator); output_c_string(p->out, p->separator);
fprintf(p->out, "\n"); fprintf(p->out, "\n");
fprintf(p->out,"%9.9s: %s\n","stats", p->statsOn ? "on" : "off");
fprintf(p->out,"%9.9s: ","width"); fprintf(p->out,"%9.9s: ","width");
for (i=0;i<(int)ArraySize(p->colWidth) && p->colWidth[i] != 0;i++) { for (i=0;i<(int)ArraySize(p->colWidth) && p->colWidth[i] != 0;i++) {
fprintf(p->out,"%d ",p->colWidth[i]); fprintf(p->out,"%d ",p->colWidth[i]);
@@ -2008,6 +2099,10 @@ static int do_meta_command(char *zLine, struct callback_data *p){
fprintf(p->out,"\n"); fprintf(p->out,"\n");
}else }else
if( c=='s' && strncmp(azArg[0], "stats", n)==0 && nArg>1 && nArg<3 ){
p->statsOn = booleanValue(azArg[1]);
}else
if( c=='t' && n>1 && strncmp(azArg[0], "tables", n)==0 && nArg<3 ){ if( c=='t' && n>1 && strncmp(azArg[0], "tables", n)==0 && nArg<3 ){
char **azResult; char **azResult;
int nRow; int nRow;
@@ -2391,6 +2486,7 @@ static const char zOptions[] =
" -line set output mode to 'line'\n" " -line set output mode to 'line'\n"
" -list set output mode to 'list'\n" " -list set output mode to 'list'\n"
" -separator 'x' set output field separator (|)\n" " -separator 'x' set output field separator (|)\n"
" -stats print memory stats before each finalize\n"
" -nullvalue 'text' set text string for NULL values\n" " -nullvalue 'text' set text string for NULL values\n"
" -version show SQLite version\n" " -version show SQLite version\n"
; ;
@@ -2555,6 +2651,8 @@ int main(int argc, char **argv){
data.showHeader = 0; data.showHeader = 0;
}else if( strcmp(z,"-echo")==0 ){ }else if( strcmp(z,"-echo")==0 ){
data.echoOn = 1; data.echoOn = 1;
}else if( strcmp(z,"-stats")==0 ){
data.statsOn = 1;
}else if( strcmp(z,"-bail")==0 ){ }else if( strcmp(z,"-bail")==0 ){
bail_on_error = 1; bail_on_error = 1;
}else if( strcmp(z,"-version")==0 ){ }else if( strcmp(z,"-version")==0 ){

View File

@@ -178,6 +178,11 @@ do_test shell1-1.14.3 {
[regexp {Error: missing argument for option: -separator} $res] [regexp {Error: missing argument for option: -separator} $res]
} {1 1} } {1 1}
# -stats print memory stats before each finalize
do_test shell1-1.14b.1 {
catchcmd "-stats test.db" ""
} {0 {}}
# -nullvalue 'text' set text string for NULL values # -nullvalue 'text' set text string for NULL values
do_test shell1-1.15.1 { do_test shell1-1.15.1 {
catchcmd "-nullvalue 'x' test.db" "" catchcmd "-nullvalue 'x' test.db" ""
@@ -195,7 +200,7 @@ do_test shell1-1.15.3 {
# -version show SQLite version # -version show SQLite version
do_test shell1-1.16.1 { do_test shell1-1.16.1 {
catchcmd "-version test.db" "" catchcmd "-version test.db" ""
} {0 3.7.0} } {0 3.7.1}
#---------------------------------------------------------------------------- #----------------------------------------------------------------------------
# Test cases shell1-2.*: Basic "dot" command token parsing. # Test cases shell1-2.*: Basic "dot" command token parsing.
@@ -621,13 +626,29 @@ do_test shell1-3.23.1 {
[regexp {nullvalue:} $res] \ [regexp {nullvalue:} $res] \
[regexp {output:} $res] \ [regexp {output:} $res] \
[regexp {separator:} $res] \ [regexp {separator:} $res] \
[regexp {stats:} $res] \
[regexp {width:} $res] [regexp {width:} $res]
} {1 1 1 1 1 1 1 1} } {1 1 1 1 1 1 1 1 1}
do_test shell1-3.23.2 { do_test shell1-3.23.2 {
# too many arguments # too many arguments
catchcmd "test.db" ".show BAD" catchcmd "test.db" ".show BAD"
} {1 {Error: unknown command or invalid arguments: "show". Enter ".help" for help}} } {1 {Error: unknown command or invalid arguments: "show". Enter ".help" for help}}
# .stats ON|OFF Turn stats on or off
do_test shell1-3.23b.1 {
catchcmd "test.db" ".stats"
} {1 {Error: unknown command or invalid arguments: "stats". Enter ".help" for help}}
do_test shell1-3.23b.2 {
catchcmd "test.db" ".stats ON"
} {0 {}}
do_test shell1-3.23b.3 {
catchcmd "test.db" ".stats OFF"
} {0 {}}
do_test shell1-3.23b.4 {
# too many arguments
catchcmd "test.db" ".stats OFF BAD"
} {1 {Error: unknown command or invalid arguments: "stats". Enter ".help" for help}}
# .tables ?TABLE? List names of tables # .tables ?TABLE? List names of tables
# If TABLE specified, only list tables matching # If TABLE specified, only list tables matching
# LIKE pattern TABLE. # LIKE pattern TABLE.

140
tool/shell4.test Normal file
View File

@@ -0,0 +1,140 @@
# 2010 July 28
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
#
# The focus of this file is testing the CLI shell tool.
#
# $Id: shell4.test,v 1.7 2009/07/17 16:54:48 shaneh Exp $
#
# Test plan:
#
# shell4-1.*: Basic tests specific to the "stats" command.
#
package require sqlite3
set CLI "./sqlite3"
proc do_test {name cmd expected} {
puts -nonewline "$name ..."
set res [uplevel $cmd]
if {$res eq $expected} {
puts Ok
} else {
puts Error
puts " Got: $res"
puts " Expected: $expected"
exit
}
}
proc execsql {sql} {
uplevel [list db eval $sql]
}
proc catchsql {sql} {
set rc [catch {uplevel [list db eval $sql]} msg]
list $rc $msg
}
proc catchcmd {db {cmd ""}} {
global CLI
set out [open cmds.txt w]
puts $out $cmd
close $out
set line "exec $CLI $db < cmds.txt"
set rc [catch { eval $line } msg]
list $rc $msg
}
file delete -force test.db test.db.journal
sqlite3 db test.db
#----------------------------------------------------------------------------
# Test cases shell4-1.*: Tests specific to the "stats" command.
#
# should default to off
do_test shell4-1.1.1 {
set res [catchcmd "test.db" ".show"]
list [regexp {stats: off} $res]
} {1}
do_test shell4-1.1.2 {
set res [catchcmd "test.db" ".show"]
list [regexp {stats: on} $res]
} {0}
# -stats should turn it on
do_test shell4-1.2.1 {
set res [catchcmd "-stats test.db" ".show"]
list [regexp {stats: on} $res]
} {1}
do_test shell4-1.2.2 {
set res [catchcmd "-stats test.db" ".show"]
list [regexp {stats: off} $res]
} {0}
# .stats ON|OFF Turn stats on or off
do_test shell4-1.3.1 {
catchcmd "test.db" ".stats"
} {1 {Error: unknown command or invalid arguments: "stats". Enter ".help" for help}}
do_test shell4-1.3.2 {
catchcmd "test.db" ".stats ON"
} {0 {}}
do_test shell4-1.3.3 {
catchcmd "test.db" ".stats OFF"
} {0 {}}
do_test shell4-1.3.4 {
# too many arguments
catchcmd "test.db" ".stats OFF BAD"
} {1 {Error: unknown command or invalid arguments: "stats". Enter ".help" for help}}
# NB. whitespace is important
do_test shell4-1.4.1 {
set res [catchcmd "test.db" {.show}]
list [regexp {stats: off} $res]
} {1}
do_test shell4-1.4.2 {
set res [catchcmd "test.db" {.stats ON
.show
}]
list [regexp {stats: on} $res]
} {1}
do_test shell4-1.4.3 {
set res [catchcmd "test.db" {.stats OFF
.show
}]
list [regexp {stats: off} $res]
} {1}
# make sure stats not present when off
do_test shell4-1.5.1 {
set res [catchcmd "test.db" {SELECT 1;}]
list [regexp {Mem Used} $res] \
[regexp {Heap Usage} $res] \
[regexp {Autoindex Inserts} $res]
} {0 0 0}
# make sure stats are present when on
do_test shell4-1.5.2 {
set res [catchcmd "test.db" {.stats ON
SELECT 1;
}]
list [regexp {Mem Used} $res] \
[regexp {Heap Usage} $res] \
[regexp {Autoindex Inserts} $res]
} {1 1 1}
puts "CLI tests completed successfully"