1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-08-07 02:42:48 +03:00

Enhance the sqlite3_stmt_scanstatus() API and add sqlite3_stmt_scanstatus_v2(). For creation of easier to read query performance reports.

FossilOrigin-Name: 55800833645739efeddcacef464c623931cb6aeb43f4219b4e4faf473c25c8bb
This commit is contained in:
dan
2022-12-02 20:32:22 +00:00
parent bb4e4a4840
commit 231ff4b027
17 changed files with 546 additions and 137 deletions

View File

@@ -2111,23 +2111,60 @@ int sqlite3_preupdate_new(sqlite3 *db, int iIdx, sqlite3_value **ppValue){
/*
** Return status data for a single loop within query pStmt.
*/
int sqlite3_stmt_scanstatus(
int sqlite3_stmt_scanstatus_v2(
sqlite3_stmt *pStmt, /* Prepared statement being queried */
int idx, /* Index of loop to report on */
int iScan, /* Index of loop to report on */
int iScanStatusOp, /* Which metric to return */
int flags,
void *pOut /* OUT: Write the answer here */
){
Vdbe *p = (Vdbe*)pStmt;
ScanStatus *pScan;
if( idx<0 || idx>=p->nScan ) return 1;
pScan = &p->aScan[idx];
int idx;
/* If the v2 flag is clear, then this function must ignore any ScanStatus
** structures with ScanStatus.addrLoop set to 0. */
if( iScan<0 ){
int ii;
if( iScanStatusOp==SQLITE_SCANSTAT_NCYCLE ){
i64 res = 0;
for(ii=0; ii<p->nOp; ii++){
res += p->anCycle[ii];
}
*(i64*)pOut = res;
return 0;
}
return 1;
}
if( flags & SQLITE_SCANSTAT_COMPLEX ){
idx = iScan;
pScan = &p->aScan[idx];
}else{
for(idx=0; idx<p->nScan; idx++){
pScan = &p->aScan[idx];
if( pScan->addrLoop ){
iScan--;
if( iScan<0 ) break;
}
}
}
if( idx>=p->nScan ) return 1;
switch( iScanStatusOp ){
case SQLITE_SCANSTAT_NLOOP: {
*(sqlite3_int64*)pOut = p->anExec[pScan->addrLoop];
if( pScan->addrLoop>0 ){
*(sqlite3_int64*)pOut = p->anExec[pScan->addrLoop];
}else{
*(sqlite3_int64*)pOut = -1;
}
break;
}
case SQLITE_SCANSTAT_NVISIT: {
*(sqlite3_int64*)pOut = p->anExec[pScan->addrVisit];
if( pScan->addrVisit>0 ){
*(sqlite3_int64*)pOut = p->anExec[pScan->addrVisit];
}else{
*(sqlite3_int64*)pOut = -1;
}
break;
}
case SQLITE_SCANSTAT_EST: {
@@ -2160,6 +2197,26 @@ int sqlite3_stmt_scanstatus(
}
break;
}
case SQLITE_SCANSTAT_PARENTID: {
if( pScan->addrExplain ){
*(int*)pOut = p->aOp[ pScan->addrExplain ].p2;
}else{
*(int*)pOut = -1;
}
break;
}
case SQLITE_SCANSTAT_NCYCLE: {
i64 res = -1;
if( pScan->addrEndRange ){
int ii;
res = 0;
for(ii=pScan->addrExplain; ii<=pScan->addrEndRange; ii++){
res += p->anCycle[ii];
}
}
*(i64*)pOut = res;
break;
}
default: {
return 1;
}
@@ -2167,11 +2224,25 @@ int sqlite3_stmt_scanstatus(
return 0;
}
/*
** Return status data for a single loop within query pStmt.
*/
int sqlite3_stmt_scanstatus(
sqlite3_stmt *pStmt, /* Prepared statement being queried */
int iScan, /* Index of loop to report on */
int iScanStatusOp, /* Which metric to return */
void *pOut /* OUT: Write the answer here */
){
return sqlite3_stmt_scanstatus_v2(pStmt, iScan, iScanStatusOp, 0, pOut);
}
/*
** Zero all counters associated with the sqlite3_stmt_scanstatus() data.
*/
void sqlite3_stmt_scanstatus_reset(sqlite3_stmt *pStmt){
Vdbe *p = (Vdbe*)pStmt;
memset(p->anExec, 0, p->nOp * sizeof(i64));
memset(p->anCycle, 0, p->nOp * sizeof(u64));
}
#endif /* SQLITE_ENABLE_STMT_SCANSTATUS */