From: dan Date: Tue, 28 Feb 2023 19:39:59 +0000 (+0000) Subject: Add an sqlite3_db_config() option - SQLITE_DBCONFIG_STMT_SCANSTATS - for enabling... X-Git-Tag: version-3.42.0~307 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=45163fc45e138c5af15b24ea88c31c8b54581cec;p=thirdparty%2Fsqlite.git Add an sqlite3_db_config() option - SQLITE_DBCONFIG_STMT_SCANSTATS - for enabling and disabling the collection of sqlite3_stmt_scanstats() statistics in SQLITE_ENABLE_STMT_SCANSTATUS builds. Collection of statistics is disabled by default. FossilOrigin-Name: 0f5579bef27b84ee855065cfe87703c51e1f9773906a9e0d4e4dafc90bd0e553 --- diff --git a/manifest b/manifest index 5395254fff..c289db4cb6 100644 --- 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. diff --git a/manifest.uuid b/manifest.uuid index a57e5825b0..b5a7d79f5a 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -5916705c731604d2e6b51a307cc8d7b67f4c102062bfdfcbc716a2916e0b0d86 \ No newline at end of file +0f5579bef27b84ee855065cfe87703c51e1f9773906a9e0d4e4dafc90bd0e553 \ No newline at end of file diff --git a/src/global.c b/src/global.c index 799b1e47c4..b018c50027 100644 --- a/src/global.c +++ b/src/global.c @@ -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 }; diff --git a/src/main.c b/src/main.c index 9ec313e6fc..a0e5e65852 100644 --- a/src/main.c +++ b/src/main.c @@ -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 */ diff --git a/src/shell.c.in b/src/shell.c.in index 5c8d47e9a0..a983ec0c0e 100644 --- a/src/shell.c.in +++ b/src/shell.c.in @@ -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 diff --git a/src/sqlite.h.in b/src/sqlite.h.in index 06737e1c90..0a31ba033d 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -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. ** + +** [[SQLITE_DBCONFIG_STMT_SCANSTATS]] +**
SQLITE_DBCONFIG_STMT_SCANSTATS +**
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. ** */ #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 diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 40afc08dbb..21ad2fa7e1 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -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 */ diff --git a/src/test1.c b/src/test1.c index 421fad5403..a765a66fa6 100644 --- a/src/test1.c +++ b/src/test1.c @@ -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; diff --git a/src/vdbe.c b/src/vdbe.c index 61ff0b3cc0..2bb4964c37 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -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 diff --git a/src/vdbeaux.c b/src/vdbeaux.c index d04d8f1e17..87fd067322 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -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; iiaAddrRange); 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; iiaAddrRange); 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) */ /* diff --git a/src/where.c b/src/where.c index f71380592e..8f6bc24be9 100644 --- a/src/where.c +++ b/src/where.c @@ -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; diff --git a/src/wherecode.c b/src/wherecode.c index 860acb44cf..f74273cf18 100644 --- a/src/wherecode.c +++ b/src/wherecode.c @@ -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); + } } } } diff --git a/test/scanstatus.test b/test/scanstatus.test index fa00a356bc..1eab9a26a4 100644 --- a/test/scanstatus.test +++ b/test/scanstatus.test @@ -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 { diff --git a/test/scanstatus2.test b/test/scanstatus2.test index 497cbe67d8..7b8453f94b 100644 --- a/test/scanstatus2.test +++ b/test/scanstatus2.test @@ -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 (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) }