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:
@@ -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 */
|
||||
|
Reference in New Issue
Block a user