mirror of
https://github.com/sqlite/sqlite.git
synced 2025-08-05 15:55:57 +03:00
Enhance the sqlite3_stmt_explain() interface so that avoids unnecessary
reprepare operations. FossilOrigin-Name: 050f773addd605f6690348c98e9000a9a3663bbc26288a71973fd7b40468e8ab
This commit is contained in:
@@ -1126,7 +1126,8 @@ int sqlite3_aggregate_count(sqlite3_context *p){
|
||||
*/
|
||||
int sqlite3_column_count(sqlite3_stmt *pStmt){
|
||||
Vdbe *pVm = (Vdbe *)pStmt;
|
||||
return pVm ? pVm->nResColumn : 0;
|
||||
if( pVm==0 ) return 0;
|
||||
return pVm->nResColumn;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1299,6 +1300,32 @@ int sqlite3_column_type(sqlite3_stmt *pStmt, int i){
|
||||
return iType;
|
||||
}
|
||||
|
||||
/*
|
||||
** Column names appropriate for EXPLAIN or EXPLAIN QUERY PLAN.
|
||||
*/
|
||||
static const char * const azExplainColNames8[] = {
|
||||
"addr", "opcode", "p1", "p2", "p3", "p4", "p5", "comment", /* EXPLAIN */
|
||||
"id", "parent", "notused", "detail" /* EQP */
|
||||
};
|
||||
static const u16 azExplainColNames16data[] = {
|
||||
/* 0 */ 'a', 'd', 'd', 'r', 0,
|
||||
/* 5 */ 'o', 'p', 'c', 'o', 'd', 'e', 0,
|
||||
/* 12 */ 'p', '1', 0,
|
||||
/* 15 */ 'p', '2', 0,
|
||||
/* 18 */ 'p', '3', 0,
|
||||
/* 21 */ 'p', '4', 0,
|
||||
/* 24 */ 'p', '5', 0,
|
||||
/* 27 */ 'c', 'o', 'm', 'm', 'e', 'n', 't', 0,
|
||||
/* 35 */ 'i', 'd', 0,
|
||||
/* 38 */ 'p', 'a', 'r', 'e', 'n', 't', 0,
|
||||
/* 45 */ 'n', 'o', 't', 'u', 's', 'e', 'd', 0,
|
||||
/* 53 */ 'd', 'e', 't', 'a', 'i', 'l', 0
|
||||
};
|
||||
static const u8 iExplainColNames16[] = {
|
||||
0, 5, 12, 15, 18, 21, 24, 27,
|
||||
35, 38, 45, 53
|
||||
};
|
||||
|
||||
/*
|
||||
** Convert the N-th element of pStmt->pColName[] into a string using
|
||||
** xFunc() then return that string. If N is out of range, return 0.
|
||||
@@ -1331,15 +1358,29 @@ static const void *columnName(
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
if( N<0 ) return 0;
|
||||
ret = 0;
|
||||
p = (Vdbe *)pStmt;
|
||||
db = p->db;
|
||||
assert( db!=0 );
|
||||
n = sqlite3_column_count(pStmt);
|
||||
if( N<n && N>=0 ){
|
||||
sqlite3_mutex_enter(db->mutex);
|
||||
|
||||
if( p->explain ){
|
||||
if( useType>0 ) goto columnName_end;
|
||||
n = p->explain==1 ? 8 : 4;
|
||||
if( N>=n ) goto columnName_end;
|
||||
if( useUtf16 ){
|
||||
int i = iExplainColNames16[N + 8*p->explain - 8];
|
||||
ret = (void*)&azExplainColNames16data[i];
|
||||
}else{
|
||||
ret = (void*)azExplainColNames8[N + 8*p->explain - 8];
|
||||
}
|
||||
goto columnName_end;
|
||||
}
|
||||
n = p->nResColumn;
|
||||
if( N<n ){
|
||||
u8 prior_mallocFailed = db->mallocFailed;
|
||||
N += useType*n;
|
||||
sqlite3_mutex_enter(db->mutex);
|
||||
#ifndef SQLITE_OMIT_UTF16
|
||||
if( useUtf16 ){
|
||||
ret = sqlite3_value_text16((sqlite3_value*)&p->aColName[N]);
|
||||
@@ -1356,8 +1397,9 @@ static const void *columnName(
|
||||
sqlite3OomClear(db);
|
||||
ret = 0;
|
||||
}
|
||||
sqlite3_mutex_leave(db->mutex);
|
||||
}
|
||||
columnName_end:
|
||||
sqlite3_mutex_leave(db->mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1824,8 +1866,21 @@ int sqlite3_stmt_explain(sqlite3_stmt *pStmt, int eMode){
|
||||
if( v->explain==eMode ) return SQLITE_OK;
|
||||
if( v->zSql==0 || eMode<0 || eMode>2 ) return SQLITE_ERROR;
|
||||
sqlite3_mutex_enter(v->db->mutex);
|
||||
v->explain = eMode;
|
||||
rc = sqlite3Reprepare(v);
|
||||
if( v->nMem>=10 && (eMode!=2 || v->haveEqpOps) ){
|
||||
/* No reprepare necessary */
|
||||
v->explain = eMode;
|
||||
rc = SQLITE_OK;
|
||||
}else{
|
||||
int haveEqpOps = v->explain==2 || v->haveEqpOps;
|
||||
v->explain = eMode;
|
||||
rc = sqlite3Reprepare(v);
|
||||
v->haveEqpOps = haveEqpOps!=0;
|
||||
}
|
||||
if( v->explain ){
|
||||
v->nResColumn = 12 - 4*v->explain;
|
||||
}else{
|
||||
v->nResColumn = v->nResAlloc;
|
||||
}
|
||||
sqlite3_mutex_leave(v->db->mutex);
|
||||
return rc;
|
||||
}
|
||||
|
Reference in New Issue
Block a user