aboutsummaryrefslogtreecommitdiff
path: root/src/vdbeapi.c
diff options
context:
space:
mode:
authordrh <>2023-07-18 17:29:05 +0000
committerdrh <>2023-07-18 17:29:05 +0000
commitd1db37a2f32b06d0cd53e66b18ee47ffea91ca87 (patch)
treed4fd8a0c78f90a147e6469513c09ad420fd51b1c /src/vdbeapi.c
parente393f6eff00bd78bbda6ecfaf1feb957a845226b (diff)
downloadsqlite-d1db37a2f32b06d0cd53e66b18ee47ffea91ca87.tar.gz
sqlite-d1db37a2f32b06d0cd53e66b18ee47ffea91ca87.zip
Enhance the sqlite3_stmt_explain() interface so that avoids unnecessary
reprepare operations. FossilOrigin-Name: 050f773addd605f6690348c98e9000a9a3663bbc26288a71973fd7b40468e8ab
Diffstat (limited to 'src/vdbeapi.c')
-rw-r--r--src/vdbeapi.c69
1 files changed, 62 insertions, 7 deletions
diff --git a/src/vdbeapi.c b/src/vdbeapi.c
index 885b17f76..3185191ed 100644
--- a/src/vdbeapi.c
+++ b/src/vdbeapi.c
@@ -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;
}
/*
@@ -1300,6 +1301,32 @@ int sqlite3_column_type(sqlite3_stmt *pStmt, int i){
}
/*
+** 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;
}