]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Add an sqlite3_db_config() option - SQLITE_DBCONFIG_STMT_SCANSTATS - for enabling...
authordan <Dan Kennedy>
Tue, 28 Feb 2023 19:39:59 +0000 (19:39 +0000)
committerdan <Dan Kennedy>
Tue, 28 Feb 2023 19:39:59 +0000 (19:39 +0000)
FossilOrigin-Name: 0f5579bef27b84ee855065cfe87703c51e1f9773906a9e0d4e4dafc90bd0e553

14 files changed:
manifest
manifest.uuid
src/global.c
src/main.c
src/shell.c.in
src/sqlite.h.in
src/sqliteInt.h
src/test1.c
src/vdbe.c
src/vdbeaux.c
src/where.c
src/wherecode.c
test/scanstatus.test
test/scanstatus2.test

index 5395254fff12c60b92c6c7cba8f1b4469fd8bd3b..c289db4cb629abb726bcb16aba16e8930267eac7 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Only\suse\sa\sBloom\sfilter\son\san\sautomatic\sindex\sif\sone\sor\smore\sof\sthe\skey\ncolumns\sin\sthe\sindex\scan\stake\son\snon-TEXT\svalues.
-D 2023-02-28T18:06:52.731
+C Add\san\ssqlite3_db_config()\soption\s-\sSQLITE_DBCONFIG_STMT_SCANSTATS\s-\sfor\senabling\sand\sdisabling\sthe\scollection\sof\ssqlite3_stmt_scanstats()\sstatistics\sin\sSQLITE_ENABLE_STMT_SCANSTATUS\sbuilds.\sCollection\sof\sstatistics\sis\sdisabled\sby\sdefault.
+D 2023-02-28T19:39:59.514
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -577,7 +577,7 @@ F src/expr.c 2e5e67e800c9416996df52409746a2f3c7dadf5d38b5a367ce379b239e3f40c8
 F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
 F src/fkey.c 722f20779f5342a787922deded3628d8c74b5249cab04098cf17ee2f2aaff002
 F src/func.c d187be57a886ddf4e6b7ef584a494361899be3df5eee6d4a747b68ff4aff4122
-F src/global.c e06ff8e0acd85aec13563c9ecb44fbbf38232ccf73594998fd880b92d619594b
+F src/global.c 428d2580a1cdf5dbe1f356d1feab83710ae0cc862ece0fb57bc8259e43838c74
 F src/hash.c c6af5f96a7a76d000f07c5402c48c318c2566beecdee9e78b9d9f60ce7119565
 F src/hash.h 3340ab6e1d13e725571d7cee6d3e3135f0779a7d8e76a9ce0a85971fa3953c51
 F src/hwtime.h b638809e083b601b618df877b2e89cb87c2a47a01f4def10be4c4ebb54664ac7
@@ -586,7 +586,7 @@ F src/insert.c 7940fce7d4aa855606432d82d20694e17c18a03956f5f5776f2404e2df7c18a8
 F src/json.c c85ed6fce06f43d414b0d7fff64749d43a0dbd1067123ee407bd3a0752454161
 F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa
 F src/loadext.c b04eb648cedc45efe4298e1ef439ac4f0096ae27b5f01accb0a1f49d57789128
-F src/main.c cb5b7277b525ac8f7663426485332bb4f3c1fd9d07f4051980dcab806b780808
+F src/main.c 834e257234fdf9e74c204c1a130920941618e48b2065747162862773ba5416b5
 F src/malloc.c 47b82c5daad557d9b963e3873e99c22570fb470719082c6658bf64e3012f7d23
 F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
 F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de
@@ -624,16 +624,16 @@ F src/random.c 606b00941a1d7dd09c381d3279a058d771f406c5213c9932bbd93d5587be4b9c
 F src/resolve.c d62c5665279cc7485f9d45b5e20911cc7b19c203f268321a90d05d74f4725750
 F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92
 F src/select.c 230dc0601f55ae4909b5f88bc002bfa1f1fb331e51f2c6d670d3effc2ced365e
-F src/shell.c.in cb763c332be668ecba48c85de52df52a86f992867b813460d55c3bccaaf4c0eb
-F src/sqlite.h.in 5f308635ad467b50af858f271e403d14f8bcc574c2610f7cfd2d00f5bb37f616
+F src/shell.c.in a319e2a6cdb166d65a91ad0e69a2e9dea6afd066acbf9adce883a6762b43ec49
+F src/sqlite.h.in 7a2fed8c11df276bc35bc9ac47981cb0a7f9db39b85761a7dd50028fe77d28ce
 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
 F src/sqlite3ext.h da473ce2b3d0ae407a6300c4a164589b9a6bfdbec9462688a8593ff16f3bb6e4
-F src/sqliteInt.h cb7182dcdc9910d5f1352c90762545cc5ffb79c4a47f4ae7c5ee044fdb80423b
+F src/sqliteInt.h e40980dd50f31aa57bed8dbb32c8fecf64b3ad9bc235a3abb24a3b95734cafeb
 F src/sqliteLimit.h d7323ffea5208c6af2734574bae933ca8ed2ab728083caa117c9738581a31657
 F src/status.c 160c445d7d28c984a0eae38c144f6419311ed3eace59b44ac6dafc20db4af749
 F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
 F src/tclsqlite.c 8522a04fb9c84faa1d80354430ae0ee9349727a3a4b32e3cfe39b9be8324cabd
-F src/test1.c ad4a8503c4290d37805f107107a503874ff42d8405dd1558fbe2a1a71039816d
+F src/test1.c 5ca9cb48a5dfef5980417bf5f76594071ae94795cbb8d065f8a1290c3b308ec6
 F src/test2.c 827446e259a3b7ab949da1542953edda7b5117982576d3e6f1c24a0dd20a5cef
 F src/test3.c 61798bb0d38b915067a8c8e03f5a534b431181f802659a6616f9b4ff7d872644
 F src/test4.c 4533b76419e7feb41b40582554663ed3cd77aaa54e135cf76b3205098cd6e664
@@ -693,11 +693,11 @@ F src/upsert.c 5303dc6c518fa7d4b280ec65170f465c7a70b7ac2b22491598f6d0b4875b3145
 F src/utf.c ee39565f0843775cc2c81135751ddd93eceb91a673ea2c57f61c76f288b041a0
 F src/util.c 3ff7bc2b48dd425b1448304bb86273b05da1621f136d51dbb9789f8803559a1f
 F src/vacuum.c 84ce7f01f8a7a08748e107a441db83bcec13970190ddcb0c9ff522adbc1c23fd
-F src/vdbe.c 523fbe2086179b42dfdc07093f592443f0a3e9583d1ff17ef0d03a25777c1347
+F src/vdbe.c 1ddcb8a799d1a4e0c3dcc5c3641923d1343439070b35872c1801a78a0059234e
 F src/vdbe.h 73b904a6b3bb27f308c6cc287a5751ebc7f1f89456be0ed068a12b92844c6e8c
 F src/vdbeInt.h a4147a4ddf613cb1bcb555ace9e9e74a9c099d65facd88155f191b1fb4d74cfb
 F src/vdbeapi.c 40c47b1528d308a322203de21d2e0d711753257ed9771771b6129214b1d65932
-F src/vdbeaux.c 3f9e3b6585e7434aa11300169dd66ddf0fc963a0c6f7940bdc058335dadeb353
+F src/vdbeaux.c 0f5201346a83a35a08e833c3a03abe626119c07b7361c28bc6a259b98540f1d6
 F src/vdbeblob.c 5e61ce31aca17db8fb60395407457a8c1c7fb471dde405e0cd675974611dcfcd
 F src/vdbemem.c 0388576b7cf0be13ce14b9e3b8aa90b8a1b923b60321d0242131ae0b5732b43b
 F src/vdbesort.c 43756031ca7430f7aec3ef904824a7883c4ede783e51f280d99b9b65c0796e35
@@ -708,9 +708,9 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
 F src/wal.c b9df133a705093da8977da5eb202eaadb844839f1c7297c08d33471f5491843d
 F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a
 F src/walker.c f890a3298418d7cba3b69b8803594fdc484ea241206a8dfa99db6dd36f8cbb3b
-F src/where.c 76d2014b1e69935cc9b50a710f08321d63f7827f2cf6fd9f21cde7e909a61a6c
+F src/where.c 6b45dc4c47d636f5adb0d78ed71cefab5ab2a7287fb80c86604a5f7874d2ba22
 F src/whereInt.h e25203e5bfee149f5f1225ae0166cfb4f1e65490c998a024249e98bb0647377c
-F src/wherecode.c b82d0d33315e1526904b95155e55e61149c4462147668e1cc4567c812735eff1
+F src/wherecode.c 9919e5a22f4b24dd96c49b8981484cbe6bbfcf466ff73ac40a06e1356aa8bf87
 F src/whereexpr.c 1dfda1695e4480c24248157df55bb4d66c732dc8d14ac16b4f076bb15de93d63
 F src/window.c 76a27cff9ea2ded0c2c3527187029259440fabcc4cc4c07b11d942c78494a614
 F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
@@ -1436,8 +1436,8 @@ F test/savepoint5.test 0735db177e0ebbaedc39812c8d065075d563c4fd
 F test/savepoint6.test f41279c5e137139fa5c21485773332c7adb98cd7
 F test/savepoint7.test cde525ea3075283eb950cdcdefe23ead4f700daa
 F test/savepointfault.test f044eac64b59f09746c7020ee261734de82bf9b2
-F test/scanstatus.test 74391c2c0926994bf0962db6c04c9ff5b95d15a41d2e076fe011b73f92815e70
-F test/scanstatus2.test ca6c258425977e5935f0ff3a8670d9b5d813dd5b83cf0bbe39acfc0fd2b5a0b1
+F test/scanstatus.test 177fe0fea60898b2190328fbe358bafa2637e81856f90fb527a792efaf249c14
+F test/scanstatus2.test 7c367a5c818bad1936f291d33f688a3daa42279d4e989d920660c7002d67d3a2
 F test/schema.test 5dd11c96ba64744de955315d2e4f8992e447533690153b93377dffb2a5ef5431
 F test/schema2.test 906408621ea881fdb496d878b1822572a34e32c5
 F test/schema3.test 8ed4ae66e082cdd8b1b1f22d8549e1e7a0db4527a8e6ee8b6193053ee1e5c9ce
@@ -2048,8 +2048,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 090304b870419acb5b05205a07fc75830b556928149f76a843cda526f77a6fc0
-R 192a8af525d9a67c0614fb52e425206b
-U drh
-Z d906284cbfaa2356b8109e77d4c16f08
+P 5916705c731604d2e6b51a307cc8d7b67f4c102062bfdfcbc716a2916e0b0d86
+R 62c12b75bd9869fbb782d0697362eb0c
+U dan
+Z 823edb92d517eed03d3961ba1e99b0c0
 # Remove this line to create a well-formed Fossil manifest.
index a57e5825b0de19538ae3942be961e5a701acbec4..b5a7d79f5a4f4da3509742803108cfbb5b386f54 100644 (file)
@@ -1 +1 @@
-5916705c731604d2e6b51a307cc8d7b67f4c102062bfdfcbc716a2916e0b0d86
\ No newline at end of file
+0f5579bef27b84ee855065cfe87703c51e1f9773906a9e0d4e4dafc90bd0e553
\ No newline at end of file
index 799b1e47c47f11b3f8d419f6f16b301995bd035f..b018c50027517512e3294356418d33859e0ba9a3 100644 (file)
@@ -291,7 +291,7 @@ SQLITE_WSD struct Sqlite3Config sqlite3Config = {
    SQLITE_DEFAULT_SORTERREF_SIZE,   /* szSorterRef */
    0,                         /* iPrngSeed */
 #ifdef SQLITE_DEBUG
-   {0,0,0,0,0,0}              /* aTune */
+   {0,0,0,0,0,0},             /* aTune */
 #endif
 };
 
index 9ec313e6fce2b10ec8ef6159dc8de98449a85e90..a0e5e658524b2b1fc034d1b7044cdfc69391a6a1 100644 (file)
@@ -970,6 +970,7 @@ int sqlite3_db_config(sqlite3 *db, int op, ...){
         { SQLITE_DBCONFIG_DQS_DML,               SQLITE_DqsDML         },
         { SQLITE_DBCONFIG_LEGACY_FILE_FORMAT,    SQLITE_LegacyFileFmt  },
         { SQLITE_DBCONFIG_TRUSTED_SCHEMA,        SQLITE_TrustedSchema  },
+        { SQLITE_DBCONFIG_STMT_SCANSTATS,        SQLITE_StmtScanStats  },
       };
       unsigned int i;
       rc = SQLITE_ERROR; /* IMP: R-42790-23372 */
index 5c8d47e9a0b703e524632b88cc0eb83e6464dfaf..a983ec0c0eb3f08f9b4738a4c94782de7630651c 100644 (file)
@@ -5416,8 +5416,13 @@ static void open_db(ShellState *p, int openFlags){
     }
 #endif
   }
-  if( p->bSafeModePersist && p->db!=0 ){
-    sqlite3_set_authorizer(p->db, safeModeAuth, p);
+  if( p->db!=0 ){
+    if( p->bSafeModePersist ){
+      sqlite3_set_authorizer(p->db, safeModeAuth, p);
+    }
+    sqlite3_db_config(
+        p->db, SQLITE_DBCONFIG_STMT_SCANSTATS, p->scanstatsOn, (int*)0
+    );
   }
 }
 
@@ -9769,6 +9774,9 @@ static int do_meta_command(char *zLine, ShellState *p){
       }else{
         p->scanstatsOn = (u8)booleanValue(azArg[1]);
       }
+      sqlite3_db_config(
+          p->db, SQLITE_DBCONFIG_STMT_SCANSTATS, p->scanstatsOn, (int*)0
+      );
 #ifndef SQLITE_ENABLE_STMT_SCANSTATUS
       raw_printf(stderr, "Warning: .scanstats not available in this build.\n");
 #endif
index 06737e1c901d28c84aa62f653d76fba61281eb93..0a31ba033db702a1f50a4c7908fb39f8d16067d7 100644 (file)
@@ -2456,6 +2456,16 @@ struct sqlite3_mem_methods {
 ** not considered a bug since SQLite versions 3.3.0 and earlier do not support
 ** either generated columns or decending indexes.
 ** </dd>
+
+** [[SQLITE_DBCONFIG_STMT_SCANSTATS]]
+** <dt>SQLITE_DBCONFIG_STMT_SCANSTATS</td>
+** <dd>The SQLITE_DBCONFIG_STMT_SCANSTATS option is only useful in
+** SQLITE_ENABLE_STMT_SCANSTATS builds. In this case, it sets or clears
+** a flag that enables collection of the sqlite3_stmt_scanstatus_v2()
+** statistics. For statistics to be collected, the flag must be set on
+** the database handle both when the SQL statement is prepared and when it 
+** is stepped. The flag is clear (collection of statistics is disabled)
+** by default.
 ** </dl>
 */
 #define SQLITE_DBCONFIG_MAINDBNAME            1000 /* const char* */
@@ -2476,7 +2486,8 @@ struct sqlite3_mem_methods {
 #define SQLITE_DBCONFIG_ENABLE_VIEW           1015 /* int int* */
 #define SQLITE_DBCONFIG_LEGACY_FILE_FORMAT    1016 /* int int* */
 #define SQLITE_DBCONFIG_TRUSTED_SCHEMA        1017 /* int int* */
-#define SQLITE_DBCONFIG_MAX                   1017 /* Largest DBCONFIG */
+#define SQLITE_DBCONFIG_STMT_SCANSTATS        1018 /* int int* */
+#define SQLITE_DBCONFIG_MAX                   1018 /* Largest DBCONFIG */
 
 /*
 ** CAPI3REF: Enable Or Disable Extended Result Codes
index 40afc08dbb5dfed0072cd2c77e267982a4250a4e..21ad2fa7e119c8e6c7749f57899c539496129357 100644 (file)
@@ -1757,7 +1757,7 @@ struct sqlite3 {
 #define SQLITE_NullCallback   0x00000100  /* Invoke the callback once if the */
                                           /*   result set is empty */
 #define SQLITE_IgnoreChecks   0x00000200  /* Do not enforce check constraints */
-#define SQLITE_ReadUncommit   0x00000400  /* READ UNCOMMITTED in shared-cache */
+#define SQLITE_StmtScanStats  0x00000400  /* Enable stmt_scanstats() counters */
 #define SQLITE_NoCkptOnClose  0x00000800  /* No checkpoint on close()/DETACH */
 #define SQLITE_ReverseOrder   0x00001000  /* Reverse unordered SELECTs */
 #define SQLITE_RecTriggers    0x00002000  /* Enable recursive triggers */
@@ -1783,6 +1783,7 @@ struct sqlite3 {
                                           /*   DELETE, or UPDATE and return */
                                           /*   the count using a callback. */
 #define SQLITE_CorruptRdOnly  HI(0x00002) /* Prohibit writes due to error */
+#define SQLITE_ReadUncommit   HI(0x00004) /* READ UNCOMMITTED in shared-cache */
 
 /* Flags used only if debugging */
 #ifdef SQLITE_DEBUG
@@ -5581,4 +5582,10 @@ int sqlite3KvvfsInit(void);
 sqlite3_uint64 sqlite3Hwtime(void);
 #endif
 
+#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
+# define IS_STMT_SCANSTATUS(db) (db->flags & SQLITE_StmtScanStats)
+#else
+# define IS_STMT_SCANSTATUS(db) 0
+#endif
+
 #endif /* SQLITEINT_H */
index 421fad54039d4df4ba4394f86e3c72a12eecf2b5..a765a66fa64113740f41a568a846554f7ff5b1ba 100644 (file)
@@ -2400,7 +2400,6 @@ static int SQLITE_TCLAPI test_create_null_module(
   int objc,
   Tcl_Obj *CONST objv[]
 ){
-  int rc;
   sqlite3 *db;
   char *zName;
 
@@ -8314,6 +8313,7 @@ static int SQLITE_TCLAPI test_sqlite3_db_config(
     { "DQS_DML",            SQLITE_DBCONFIG_DQS_DML },
     { "DQS_DDL",            SQLITE_DBCONFIG_DQS_DDL },
     { "LEGACY_FILE_FORMAT", SQLITE_DBCONFIG_LEGACY_FILE_FORMAT },
+    { "STMT_SCANSTATS",     SQLITE_DBCONFIG_STMT_SCANSTATS },
   };
   int i;
   int v = 0;
index 61ff0b3cc0992f833bd0c3d300887cc6dd5dc4e2..2bb4964c37588eb247aae1b9ce8dc78b60fc620d 100644 (file)
@@ -736,6 +736,7 @@ int sqlite3VdbeExec(
   Mem *pOut = 0;             /* Output operand */
 #if defined(SQLITE_ENABLE_STMT_SCANSTATUS) || defined(VDBE_PROFILE)
   u64 *pnCycle = 0;
+  int bStmtScanStatus = IS_STMT_SCANSTATUS(db)!=0;
 #endif
   /*** INSERT STACK UNION HERE ***/
 
@@ -800,13 +801,17 @@ int sqlite3VdbeExec(
 
     assert( pOp>=aOp && pOp<&aOp[p->nOp]);
     nVmStep++;
-#if defined(SQLITE_ENABLE_STMT_SCANSTATUS) || defined(VDBE_PROFILE)
+
+#if defined(VDBE_PROFILE)
     pOp->nExec++;
     pnCycle = &pOp->nCycle;
-# ifdef VDBE_PROFILE
-    if( sqlite3NProfileCnt==0 )
-# endif
+    if( sqlite3NProfileCnt==0 ) *pnCycle -= sqlite3Hwtime();
+#elif defined(SQLITE_ENABLE_STMT_SCANSTATUS)
+    if( bStmtScanStatus ){
+      pOp->nExec++;
+      pnCycle = &pOp->nCycle;
       *pnCycle -= sqlite3Hwtime();
+    }
 #endif
 
     /* Only allow tracing if SQLITE_DEBUG is defined.
@@ -8758,8 +8763,10 @@ default: {          /* This is really OP_Noop, OP_Explain */
     *pnCycle += sqlite3NProfileCnt ? sqlite3NProfileCnt : sqlite3Hwtime();
     pnCycle = 0;
 #elif defined(SQLITE_ENABLE_STMT_SCANSTATUS)
-    *pnCycle += sqlite3Hwtime();
-    pnCycle = 0;
+    if( pnCycle ){
+      *pnCycle += sqlite3Hwtime();
+      pnCycle = 0;
+    }
 #endif
 
     /* The following code adds nothing to the actual functionality
index d04d8f1e176e22dba143bc90e491d5d6e1cb6695..87fd067322d483a9bd39682c59481bf2cd0224e1 100644 (file)
@@ -443,10 +443,10 @@ void sqlite3ExplainBreakpoint(const char *z1, const char *z2){
 */
 int sqlite3VdbeExplain(Parse *pParse, u8 bPush, const char *zFmt, ...){
   int addr = 0;
-#if !defined(SQLITE_DEBUG) && !defined(SQLITE_ENABLE_STMT_SCANSTATUS)
+#if !defined(SQLITE_DEBUG)
   /* Always include the OP_Explain opcodes if SQLITE_DEBUG is defined.
   ** But omit them (for performance) during production builds */
-  if( pParse->explain==2 )
+  if( pParse->explain==2 || IS_STMT_SCANSTATUS(pParse->db) )
 #endif
   {
     char *zMsg;
@@ -1122,18 +1122,20 @@ void sqlite3VdbeScanStatus(
   LogEst nEst,                    /* Estimated number of output rows */
   const char *zName               /* Name of table or index being scanned */
 ){
-  sqlite3_int64 nByte = (p->nScan+1) * sizeof(ScanStatus);
-  ScanStatus *aNew;
-  aNew = (ScanStatus*)sqlite3DbRealloc(p->db, p->aScan, nByte);
-  if( aNew ){
-    ScanStatus *pNew = &aNew[p->nScan++];
-    memset(pNew, 0, sizeof(ScanStatus));
-    pNew->addrExplain = addrExplain;
-    pNew->addrLoop = addrLoop;
-    pNew->addrVisit = addrVisit;
-    pNew->nEst = nEst;
-    pNew->zName = sqlite3DbStrDup(p->db, zName);
-    p->aScan = aNew;
+  if( IS_STMT_SCANSTATUS(p->db) ){
+    sqlite3_int64 nByte = (p->nScan+1) * sizeof(ScanStatus);
+    ScanStatus *aNew;
+    aNew = (ScanStatus*)sqlite3DbRealloc(p->db, p->aScan, nByte);
+    if( aNew ){
+      ScanStatus *pNew = &aNew[p->nScan++];
+      memset(pNew, 0, sizeof(ScanStatus));
+      pNew->addrExplain = addrExplain;
+      pNew->addrLoop = addrLoop;
+      pNew->addrVisit = addrVisit;
+      pNew->nEst = nEst;
+      pNew->zName = sqlite3DbStrDup(p->db, zName);
+      p->aScan = aNew;
+    }
   }
 }
 
@@ -1150,20 +1152,22 @@ void sqlite3VdbeScanStatusRange(
   int addrStart, 
   int addrEnd
 ){
-  ScanStatus *pScan = 0;
-  int ii;
-  for(ii=p->nScan-1; ii>=0; ii--){
-    pScan = &p->aScan[ii];
-    if( pScan->addrExplain==addrExplain ) break;
-    pScan = 0;
-  }
-  if( pScan ){
-    if( addrEnd<0 ) addrEnd = sqlite3VdbeCurrentAddr(p)-1;
-    for(ii=0; ii<ArraySize(pScan->aAddrRange); ii+=2){
-      if( pScan->aAddrRange[ii]==0 ){
-        pScan->aAddrRange[ii] = addrStart;
-        pScan->aAddrRange[ii+1] = addrEnd;
-        break;
+  if( IS_STMT_SCANSTATUS(p->db) ){
+    ScanStatus *pScan = 0;
+    int ii;
+    for(ii=p->nScan-1; ii>=0; ii--){
+      pScan = &p->aScan[ii];
+      if( pScan->addrExplain==addrExplain ) break;
+      pScan = 0;
+    }
+    if( pScan ){
+      if( addrEnd<0 ) addrEnd = sqlite3VdbeCurrentAddr(p)-1;
+      for(ii=0; ii<ArraySize(pScan->aAddrRange); ii+=2){
+        if( pScan->aAddrRange[ii]==0 ){
+          pScan->aAddrRange[ii] = addrStart;
+          pScan->aAddrRange[ii+1] = addrEnd;
+          break;
+        }
       }
     }
   }
@@ -1180,19 +1184,21 @@ void sqlite3VdbeScanStatusCounters(
   int addrLoop, 
   int addrVisit
 ){
-  ScanStatus *pScan = 0;
-  int ii;
-  for(ii=p->nScan-1; ii>=0; ii--){
-    pScan = &p->aScan[ii];
-    if( pScan->addrExplain==addrExplain ) break;
-    pScan = 0;
-  }
-  if( pScan ){
-    pScan->addrLoop = addrLoop;
-    pScan->addrVisit = addrVisit;
+  if( IS_STMT_SCANSTATUS(p->db) ){
+    ScanStatus *pScan = 0;
+    int ii;
+    for(ii=p->nScan-1; ii>=0; ii--){
+      pScan = &p->aScan[ii];
+      if( pScan->addrExplain==addrExplain ) break;
+      pScan = 0;
+    }
+    if( pScan ){
+      pScan->addrLoop = addrLoop;
+      pScan->addrVisit = addrVisit;
+    }
   }
 }
-#endif
+#endif /* defined(SQLITE_ENABLE_STMT_SCANSTATUS) */
 
 
 /*
index f71380592ed3ef90a0603f263a78af00874e9173..8f6bc24be9a7086033749da57e4e5b09c82bff20 100644 (file)
@@ -831,7 +831,7 @@ static void explainAutomaticIndex(
   int bPartial,                   /* True if pIdx is a partial index */
   int *pAddrExplain               /* OUT: Address of OP_Explain */
 ){
-  if( pParse->explain!=2 ){
+  if( IS_STMT_SCANSTATUS(pParse->db) && pParse->explain!=2 ){
     Table *pTab = pIdx->pTable;
     const char *zSep = "";
     char *zText = 0;
index 860acb44cf55a4fa655e8df1449602d7a3b76cfb..f74273cf1819b9707b70826255a949595b932e75 100644 (file)
@@ -111,9 +111,9 @@ static void explainIndexRange(StrAccum *pStr, WhereLoop *pLoop){
 
 /*
 ** This function is a no-op unless currently processing an EXPLAIN QUERY PLAN
-** command, or if either SQLITE_DEBUG or SQLITE_ENABLE_STMT_SCANSTATUS was
-** defined at compile-time. If it is not a no-op, a single OP_Explain opcode 
-** is added to the output to describe the table scan strategy in pLevel.
+** command, or if stmt_scanstatus_v2() stats are enabled, or if SQLITE_DEBUG 
+** was defined at compile-time. If it is not a no-op, a single OP_Explain
+** opcode is added to the output to describe the table scan strategy in pLevel.
 **
 ** If an OP_Explain opcode is added to the VM, its address is returned.
 ** Otherwise, if no OP_Explain is coded, zero is returned.
@@ -125,8 +125,8 @@ int sqlite3WhereExplainOneScan(
   u16 wctrlFlags                  /* Flags passed to sqlite3WhereBegin() */
 ){
   int ret = 0;
-#if !defined(SQLITE_DEBUG) && !defined(SQLITE_ENABLE_STMT_SCANSTATUS)
-  if( sqlite3ParseToplevel(pParse)->explain==2 )
+#if !defined(SQLITE_DEBUG)
+  if( sqlite3ParseToplevel(pParse)->explain==2 || IS_STMT_SCANSTATUS(pParse->db) )
 #endif
   {
     SrcItem *pItem = &pTabList->a[pLevel->iFrom];
@@ -292,27 +292,29 @@ void sqlite3WhereAddScanStatus(
   WhereLevel *pLvl,               /* Level to add scanstatus() entry for */
   int addrExplain                 /* Address of OP_Explain (or 0) */
 ){
-  const char *zObj = 0;
-  WhereLoop *pLoop = pLvl->pWLoop;
-  int wsFlags = pLoop->wsFlags;
-  int viaCoroutine = 0;
-
-  if( (wsFlags & WHERE_VIRTUALTABLE)==0  &&  pLoop->u.btree.pIndex!=0 ){
-    zObj = pLoop->u.btree.pIndex->zName;
-  }else{
-    zObj = pSrclist->a[pLvl->iFrom].zName;
-    viaCoroutine = pSrclist->a[pLvl->iFrom].fg.viaCoroutine;
-  }
-  sqlite3VdbeScanStatus(
-      v, addrExplain, pLvl->addrBody, pLvl->addrVisit, pLoop->nOut, zObj
-  );
-
-  if( viaCoroutine==0 ){
-    if( (wsFlags & (WHERE_MULTI_OR|WHERE_AUTO_INDEX))==0 ){
-      sqlite3VdbeScanStatusRange(v, addrExplain, -1, pLvl->iTabCur);
+  if( IS_STMT_SCANSTATUS( sqlite3VdbeDb(v) ) ){
+    const char *zObj = 0;
+    WhereLoop *pLoop = pLvl->pWLoop;
+    int wsFlags = pLoop->wsFlags;
+    int viaCoroutine = 0;
+
+    if( (wsFlags & WHERE_VIRTUALTABLE)==0  &&  pLoop->u.btree.pIndex!=0 ){
+      zObj = pLoop->u.btree.pIndex->zName;
+    }else{
+      zObj = pSrclist->a[pLvl->iFrom].zName;
+      viaCoroutine = pSrclist->a[pLvl->iFrom].fg.viaCoroutine;
     }
-    if( wsFlags & WHERE_INDEXED ){
-      sqlite3VdbeScanStatusRange(v, addrExplain, -1, pLvl->iIdxCur);
+    sqlite3VdbeScanStatus(
+        v, addrExplain, pLvl->addrBody, pLvl->addrVisit, pLoop->nOut, zObj
+    );
+
+    if( viaCoroutine==0 ){
+      if( (wsFlags & (WHERE_MULTI_OR|WHERE_AUTO_INDEX))==0 ){
+        sqlite3VdbeScanStatusRange(v, addrExplain, -1, pLvl->iTabCur);
+      }
+      if( wsFlags & WHERE_INDEXED ){
+        sqlite3VdbeScanStatusRange(v, addrExplain, -1, pLvl->iIdxCur);
+      }
     }
   }
 }
index fa00a356bc93824f650c45cd8e7e4c185ffd0344..1eab9a26a46eecb74a4e1cf478b863efa1c9bc37 100644 (file)
@@ -45,6 +45,11 @@ proc do_scanstatus_test {tn res} {
   uplevel [list do_test $tn [list set {} $ret] [list {*}$res]]
 }
 
+do_execsql_test 1.0a { SELECT count(*) FROM t1, t2; } 6
+do_scanstatus_test 1.0b { }
+
+sqlite3_db_config db STMT_SCANSTATS 1
+
 do_execsql_test 1.1 { SELECT count(*) FROM t1, t2; } 6
 do_scanstatus_test 1.2 {
   nLoop 1 nVisit 2 nEst 1048576.0 zName t1 zExplain {SCAN t1}
@@ -94,6 +99,7 @@ do_scanstatus_test 1.10 {
 # Try a few different types of scans.
 #
 reset_db
+sqlite3_db_config db STMT_SCANSTATS 1
 do_execsql_test 2.1 {
   CREATE TABLE x1(i INTEGER PRIMARY KEY, j);
   INSERT INTO x1 VALUES(1, 'one');
@@ -277,6 +283,7 @@ do_scanstatus_test 4.2.2 {
 # Further tests of different scan types.
 #
 reset_db
+sqlite3_db_config db STMT_SCANSTATS 1
 proc tochar {i} {
   set alphabet {a b c d e f g h i j k l m n o p q r s t u v w x y z}
   return [lindex $alphabet [expr $i % [llength $alphabet]]]
@@ -365,6 +372,7 @@ do_eqp_test 5.5.1 {
 } {
   QUERY PLAN
   |--SCAN t3
+  |--BLOOM FILTER ON t1 (c=?)
   `--SEARCH t1 USING AUTOMATIC COVERING INDEX (c=?)
 }
 do_execsql_test 5.5.2 {
index 497cbe67d82b7bf3d64a1e884bfecca015728aec..7b8453f94b034ad642132bbf09bd2f0d2ccf3038 100644 (file)
@@ -19,6 +19,8 @@ ifcapable !scanstatus {
   return
 }
 
+sqlite3_db_config db STMT_SCANSTATS 1
+
 do_execsql_test 1.0 {
   CREATE TABLE t1(a, b);
   CREATE TABLE t2(x, y);
@@ -141,6 +143,7 @@ QUERY (nCycle=nnn)
 #-------------------------------------------------------------------------
 ifcapable fts5 {
   reset_db
+  sqlite3_db_config db STMT_SCANSTATS 1
   do_execsql_test 2.0 {
     CREATE VIRTUAL TABLE ft USING fts5(a);
     INSERT INTO ft VALUES('abc');
@@ -158,6 +161,7 @@ QUERY (nCycle=nnn)
 
 #-------------------------------------------------------------------------
 reset_db
+sqlite3_db_config db STMT_SCANSTATS 1
 do_execsql_test 3.0 {
   CREATE TABLE x1(a, b);
   CREATE TABLE x2(c, d);
@@ -173,11 +177,13 @@ do_graph_test 2.1 {
 QUERY (nCycle=nnn)
 --SCAN x1 (nCycle=nnn)
 --CREATE AUTOMATIC INDEX ON x2(c, d) (nCycle=nnn)
+--BLOOM FILTER ON x2 (c=?)
 --SEARCH x2 USING AUTOMATIC COVERING INDEX (c=?) (nCycle=nnn)
 }
 
 #-------------------------------------------------------------------------
 reset_db
+sqlite3_db_config db STMT_SCANSTATS 1
 do_execsql_test 4.0 {
   CREATE TABLE rt1 (id INTEGER PRIMARY KEY, x1, x2);
   CREATE TABLE rt2 (id, x1, x2);
@@ -189,6 +195,7 @@ do_graph_test 4.1 {
 QUERY (nCycle=nnn)
 --SCAN rt1 (nCycle=nnn)
 --CREATE AUTOMATIC INDEX ON rt2(x1, id, x2) (nCycle=nnn)
+--BLOOM FILTER ON rt2 (x1=?)
 --SEARCH rt2 USING AUTOMATIC COVERING INDEX (x1=?) (nCycle=nnn)
 }
 
@@ -198,6 +205,7 @@ do_graph_test 4.2 {
 QUERY (nCycle=nnn)
 --SCAN rt1 (nCycle=nnn)
 --CREATE AUTOMATIC INDEX ON rt2(x1, id) (nCycle=nnn)
+--BLOOM FILTER ON rt2 (x1=?)
 --SEARCH rt2 USING AUTOMATIC COVERING INDEX (x1=?) (nCycle=nnn)
 }
 
@@ -215,6 +223,7 @@ do_graph_test 4.4 {
 QUERY (nCycle=nnn)
 --SCAN rt1 (nCycle=nnn)
 --CREATE AUTOMATIC INDEX ON rt2(x1, id) WHERE <expr> (nCycle=nnn)
+--BLOOM FILTER ON rt2 (x1=?)
 --SEARCH rt2 USING AUTOMATIC PARTIAL COVERING INDEX (x1=?) (nCycle=nnn)
 }
 
@@ -229,6 +238,7 @@ QUERY (nCycle=nnn)
 ----USE TEMP B-TREE FOR GROUP BY
 --SCAN rt1 (nCycle=nnn)
 --CREATE AUTOMATIC INDEX ON v1(x1, cnt) (nCycle=nnn)
+--BLOOM FILTER ON v1 (x1=?)
 --SEARCH v1 USING AUTOMATIC COVERING INDEX (x1=?) (nCycle=nnn)
 }