#define eputz(z) cli_puts(z,stderr)
#define sputz(fp,z) cli_puts(z,fp)
-/* True if the timer is enabled */
-static int enableTimer = 0;
-
/* A version of strcmp() that works with NULL values */
static int cli_strcmp(const char *a, const char *b){
if( a==0 ) a = "";
#endif
}
-#if !defined(_WIN32) && !defined(WIN32) && !defined(__minux)
-#include <sys/time.h>
-#include <sys/resource.h>
-
-/* VxWorks does not support getrusage() as far as we can determine */
-#if defined(_WRS_KERNEL) || defined(__RTP__)
-struct rusage {
- struct timeval ru_utime; /* user CPU time used */
- struct timeval ru_stime; /* system CPU time used */
-};
-#define getrusage(A,B) memset(B,0,sizeof(*B))
-#endif
-
-
-/* Saved resource information for the beginning of an operation */
-static struct rusage sBegin; /* CPU time at start */
-static sqlite3_int64 iBegin; /* Wall-clock time at start */
-
-/*
-** Begin timing an operation
-*/
-static void beginTimer(void){
- if( enableTimer ){
- getrusage(RUSAGE_SELF, &sBegin);
- iBegin = timeOfDay();
- }
-}
-
-/* Return the difference of two time_structs in seconds */
-static double timeDiff(struct timeval *pStart, struct timeval *pEnd){
- return (pEnd->tv_usec - pStart->tv_usec)*0.000001 +
- (double)(pEnd->tv_sec - pStart->tv_sec);
-}
-
-/*
-** Print the timing results.
-*/
-static void endTimer(FILE *out){
- if( enableTimer ){
- sqlite3_int64 iEnd = timeOfDay();
- struct rusage sEnd;
- getrusage(RUSAGE_SELF, &sEnd);
- cli_printf(out, "Run Time: real %.6f user %.6f sys %.6f\n",
- (iEnd - iBegin)*0.000001,
- timeDiff(&sBegin.ru_utime, &sEnd.ru_utime),
- timeDiff(&sBegin.ru_stime, &sEnd.ru_stime));
- }
-}
-
-#define BEGIN_TIMER beginTimer()
-#define END_TIMER(X) endTimer(X)
-#define HAS_TIMER 1
-
-#elif (defined(_WIN32) || defined(WIN32))
-
-/* Saved resource information for the beginning of an operation */
-static HANDLE hProcess;
-static FILETIME ftKernelBegin;
-static FILETIME ftUserBegin;
-static sqlite3_int64 ftWallBegin;
-typedef BOOL (WINAPI *GETPROCTIMES)(HANDLE, LPFILETIME, LPFILETIME,
- LPFILETIME, LPFILETIME);
-static GETPROCTIMES getProcessTimesAddr = NULL;
-
-/*
-** Check to see if we have timer support. Return 1 if necessary
-** support found (or found previously).
-*/
-static int hasTimer(void){
- if( getProcessTimesAddr ){
- return 1;
- } else {
- /* GetProcessTimes() isn't supported in WIN95 and some other Windows
- ** versions. See if the version we are running on has it, and if it
- ** does, save off a pointer to it and the current process handle.
- */
- hProcess = GetCurrentProcess();
- if( hProcess ){
- HINSTANCE hinstLib = LoadLibrary(TEXT("Kernel32.dll"));
- if( NULL != hinstLib ){
- getProcessTimesAddr =
- (GETPROCTIMES) GetProcAddress(hinstLib, "GetProcessTimes");
- if( NULL != getProcessTimesAddr ){
- return 1;
- }
- FreeLibrary(hinstLib);
- }
- }
- }
- return 0;
-}
-
-/*
-** Begin timing an operation
-*/
-static void beginTimer(void){
- if( enableTimer && getProcessTimesAddr ){
- FILETIME ftCreation, ftExit;
- getProcessTimesAddr(hProcess,&ftCreation,&ftExit,
- &ftKernelBegin,&ftUserBegin);
- ftWallBegin = timeOfDay();
- }
-}
-
-/* Return the difference of two FILETIME structs in seconds */
-static double timeDiff(FILETIME *pStart, FILETIME *pEnd){
- sqlite_int64 i64Start = *((sqlite_int64 *) pStart);
- sqlite_int64 i64End = *((sqlite_int64 *) pEnd);
- return (double) ((i64End - i64Start) / 10000000.0);
-}
-
-/*
-** Print the timing results.
-*/
-static void endTimer(FILE *out){
- if( enableTimer && getProcessTimesAddr){
- FILETIME ftCreation, ftExit, ftKernelEnd, ftUserEnd;
- sqlite3_int64 ftWallEnd = timeOfDay();
- getProcessTimesAddr(hProcess,&ftCreation,&ftExit,&ftKernelEnd,&ftUserEnd);
-#ifdef _WIN64
- /* microsecond precision on 64-bit windows */
- cli_printf(out, "Run Time: real %.6f user %f sys %f\n",
- (ftWallEnd - ftWallBegin)*0.000001,
- timeDiff(&ftUserBegin, &ftUserEnd),
- timeDiff(&ftKernelBegin, &ftKernelEnd));
-#else
- /* millisecond precisino on 32-bit windows */
- cli_printf(out, "Run Time: real %.3f user %.3f sys %.3f\n",
- (ftWallEnd - ftWallBegin)*0.000001,
- timeDiff(&ftUserBegin, &ftUserEnd),
- timeDiff(&ftKernelBegin, &ftKernelEnd));
-#endif
- }
-}
-
-#define BEGIN_TIMER beginTimer()
-#define END_TIMER(X) endTimer(X)
-#define HAS_TIMER hasTimer()
-
-#else
-#define BEGIN_TIMER
-#define END_TIMER(X) /*no-op*/
-#define HAS_TIMER 0
-#endif
/*
** Used to prevent warnings about unused parameters
unsigned mEqpLines; /* Mask of vertical lines in the EQP output graph */
u8 nPopOutput; /* Revert .output settings when reaching zero */
u8 nPopMode; /* Revert .mode settings when reaching zero */
+ u8 enableTimer; /* Enable the timer. 2: permanently 1: only once */
int inputNesting; /* Track nesting level of .read and other redirects */
+ double prevTimer; /* Last reported timer value */
i64 lineno; /* Line number of last line read from in */
const char *zInFile; /* Name of the input file */
int openFlags; /* Additional flags to open. (SQLITE_OPEN_NOFOLLOW) */
*/
#define MAX_INPUT_NESTING 25
+/************************* BEGIN PERFORMANCE TIMER *****************************/
+#if !defined(_WIN32) && !defined(WIN32) && !defined(__minux)
+#include <sys/time.h>
+#include <sys/resource.h>
+/* VxWorks does not support getrusage() as far as we can determine */
+#if defined(_WRS_KERNEL) || defined(__RTP__)
+struct rusage {
+ struct timeval ru_utime; /* user CPU time used */
+ struct timeval ru_stime; /* system CPU time used */
+};
+#define getrusage(A,B) memset(B,0,sizeof(*B))
+#endif
+
+/* Saved resource information for the beginning of an operation */
+static struct rusage sBegin; /* CPU time at start */
+static sqlite3_int64 iBegin; /* Wall-clock time at start */
+
+/*
+** Begin timing an operation
+*/
+static void beginTimer(ShellState *p){
+ if( p->enableTimer ){
+ getrusage(RUSAGE_SELF, &sBegin);
+ iBegin = timeOfDay();
+ }
+}
+
+/* Return the difference of two time_structs in seconds */
+static double timeDiff(struct timeval *pStart, struct timeval *pEnd){
+ return (pEnd->tv_usec - pStart->tv_usec)*0.000001 +
+ (double)(pEnd->tv_sec - pStart->tv_sec);
+}
+
+/*
+** Print the timing results.
+*/
+static void endTimer(ShellState *p){
+ if( p->enableTimer ){
+ sqlite3_int64 iEnd = timeOfDay();
+ struct rusage sEnd;
+ getrusage(RUSAGE_SELF, &sEnd);
+ p->prevTimer = (iEnd - iBegin)*0.000001;
+ cli_printf(p->out, "Run Time: real %.6f user %.6f sys %.6f\n",
+ p->prevTimer,
+ timeDiff(&sBegin.ru_utime, &sEnd.ru_utime),
+ timeDiff(&sBegin.ru_stime, &sEnd.ru_stime));
+ if( p->enableTimer==1 ) p->enableTimer = 0;
+ }
+}
+
+#define BEGIN_TIMER(X) beginTimer(X)
+#define END_TIMER(X) endTimer(X)
+#define HAS_TIMER 1
+
+#elif (defined(_WIN32) || defined(WIN32))
+
+/* Saved resource information for the beginning of an operation */
+static HANDLE hProcess;
+static FILETIME ftKernelBegin;
+static FILETIME ftUserBegin;
+static sqlite3_int64 ftWallBegin;
+typedef BOOL (WINAPI *GETPROCTIMES)(HANDLE, LPFILETIME, LPFILETIME,
+ LPFILETIME, LPFILETIME);
+static GETPROCTIMES getProcessTimesAddr = NULL;
+
+/*
+** Check to see if we have timer support. Return 1 if necessary
+** support found (or found previously).
+*/
+static int hasTimer(void){
+ if( getProcessTimesAddr ){
+ return 1;
+ } else {
+ /* GetProcessTimes() isn't supported in WIN95 and some other Windows
+ ** versions. See if the version we are running on has it, and if it
+ ** does, save off a pointer to it and the current process handle.
+ */
+ hProcess = GetCurrentProcess();
+ if( hProcess ){
+ HINSTANCE hinstLib = LoadLibrary(TEXT("Kernel32.dll"));
+ if( NULL != hinstLib ){
+ getProcessTimesAddr =
+ (GETPROCTIMES) GetProcAddress(hinstLib, "GetProcessTimes");
+ if( NULL != getProcessTimesAddr ){
+ return 1;
+ }
+ FreeLibrary(hinstLib);
+ }
+ }
+ }
+ return 0;
+}
+
+/*
+** Begin timing an operation
+*/
+static void beginTimer(ShellState *p){
+ if( p->enableTimer && getProcessTimesAddr ){
+ FILETIME ftCreation, ftExit;
+ getProcessTimesAddr(hProcess,&ftCreation,&ftExit,
+ &ftKernelBegin,&ftUserBegin);
+ ftWallBegin = timeOfDay();
+ }
+}
+
+/* Return the difference of two FILETIME structs in seconds */
+static double timeDiff(FILETIME *pStart, FILETIME *pEnd){
+ sqlite_int64 i64Start = *((sqlite_int64 *) pStart);
+ sqlite_int64 i64End = *((sqlite_int64 *) pEnd);
+ return (double) ((i64End - i64Start) / 10000000.0);
+}
+
+/*
+** Print the timing results.
+*/
+static void endTimer(ShellState *p){
+ if( p->enableTimer && getProcessTimesAddr){
+ FILETIME ftCreation, ftExit, ftKernelEnd, ftUserEnd;
+ sqlite3_int64 ftWallEnd = timeOfDay();
+ getProcessTimesAddr(hProcess,&ftCreation,&ftExit,&ftKernelEnd,&ftUserEnd);
+ p->prevTimer = (ftWallEnd - ftWallBegin)*0.000001;
+#ifdef _WIN64
+ /* microsecond precision on 64-bit windows */
+ cli_printf(p->out, "Run Time: real %.6f user %f sys %f\n",
+ p->prevTimer,
+ timeDiff(&ftUserBegin, &ftUserEnd),
+ timeDiff(&ftKernelBegin, &ftKernelEnd));
+#else
+ /* millisecond precisino on 32-bit windows */
+ cli_printf(p->out, "Run Time: real %.3f user %.3f sys %.3f\n",
+ p->prevTimer,
+ timeDiff(&ftUserBegin, &ftUserEnd),
+ timeDiff(&ftKernelBegin, &ftKernelEnd));
+#endif
+ if( p->enableTimer==1 ) p->enableTimer = 0;
+ }
+}
+
+#define BEGIN_TIMER(X) beginTimer(X)
+#define END_TIMER(X) endTimer(X)
+#define HAS_TIMER hasTimer()
+
+#else
+#define BEGIN_TIMER(X) /* no-op */
+#define END_TIMER(X) /*no-op*/
+#define HAS_TIMER 0
+#endif
+/************************* END PERFORMANCE TIMER ******************************/
/*
** Clear a display mode, freeing any allocated memory that it
memcpy(zBuf, &zVar[6], szVar-5);
sqlite3_bind_text64(pStmt, i, zBuf, szVar-6, sqlite3_free, SQLITE_UTF8);
}
+ }else if( strcmp(zVar, "$TIMER")==0 ){
+ sqlite3_bind_double(pStmt, i, pArg->prevTimer);
#ifdef SQLITE_ENABLE_CARRAY
}else if( strncmp(zVar, "$carray_", 8)==0 ){
static char *azColorNames[] = {
isExplain = sqlite3_stmt_isexplain(pStmt);
if( pArg && pArg->mode.autoEQP && isExplain==0 && pArg->dot.nArg==0 ){
int triggerEQP = 0;
+ u8 savedEnableTimer = pArg->enableTimer;
+ pArg->enableTimer = 0;
disable_debug_trace_modes();
sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, -1, &triggerEQP);
if( pArg->mode.autoEQP>=AUTOEQP_trigger ){
sqlite3_reset(pStmt);
sqlite3_stmt_explain(pStmt, 0);
restore_debug_trace_modes();
+ pArg->enableTimer = savedEnableTimer;
}
bind_prepared_stmt(pArg, pStmt);
",testctrl CMD ... Run various sqlite3_test_control() operations",
" Run \".testctrl\" with no arguments for details",
".timeout MS Try opening locked tables for MS milliseconds",
- ".timer on|off Turn SQL timer on or off",
+ ".timer on|off|once Turn SQL timer on or off.",
#ifndef SQLITE_OMIT_TRACE
".trace ?OPTIONS? Output each SQL statement as it is run",
" FILE Send output to FILE",
if( c=='t' && n>=5 && cli_strncmp(azArg[0], "timer", n)==0 ){
if( nArg==2 ){
- enableTimer = booleanValue(azArg[1]);
- if( enableTimer && !HAS_TIMER ){
+ if( cli_strcmp(azArg[1],"once")==0 ){
+ p->enableTimer = 1;
+ }else{
+ p->enableTimer = 2*booleanValue(azArg[1]);
+ }
+ if( p->enableTimer && !HAS_TIMER ){
eputz("Error: timer not available on this system.\n");
- enableTimer = 0;
+ p->enableTimer = 0;
}
}else{
- eputz("Usage: .timer on|off\n");
+ eputz("Usage: .timer on|off|once\n");
rc = 1;
}
}else
open_db(p, 0);
if( ShellHasFlag(p,SHFLG_Backslash) ) resolve_backslashes(zSql);
if( p->flgProgress & SHELL_PROGRESS_RESET ) p->nProgress = 0;
- BEGIN_TIMER;
+ BEGIN_TIMER(p);
rc = shell_exec(p, zSql, &zErrMsg);
- END_TIMER(p->out);
+ END_TIMER(p);
if( rc || zErrMsg ){
char zPrefix[100];
const char *zErrorTail;