xref: /sqlite-3.40.0/ext/misc/explain.c (revision 84c501ba)
1 /*
2 ** 2018-09-16
3 **
4 ** The author disclaims copyright to this source code.  In place of
5 ** a legal notice, here is a blessing:
6 **
7 **    May you do good and not evil.
8 **    May you find forgiveness for yourself and forgive others.
9 **    May you share freely, never taking more than you give.
10 **
11 *************************************************************************
12 **
13 ** This file demonstrates an eponymous virtual table that returns the
14 ** EXPLAIN output from an SQL statement.
15 **
16 ** Usage example:
17 **
18 **     .load ./explain
19 **     SELECT p2 FROM explain('SELECT * FROM sqlite_master')
20 **      WHERE opcode='OpenRead';
21 */
22 #if !defined(SQLITEINT_H)
23 #include "sqlite3ext.h"
24 #endif
25 SQLITE_EXTENSION_INIT1
26 #include <assert.h>
27 #include <string.h>
28 
29 #ifndef SQLITE_OMIT_VIRTUALTABLE
30 
31 /* explain_vtab is a subclass of sqlite3_vtab which will
32 ** serve as the underlying representation of a explain virtual table
33 */
34 typedef struct explain_vtab explain_vtab;
35 struct explain_vtab {
36   sqlite3_vtab base;  /* Base class - must be first */
37   sqlite3 *db;        /* Database connection for this explain vtab */
38 };
39 
40 /* explain_cursor is a subclass of sqlite3_vtab_cursor which will
41 ** serve as the underlying representation of a cursor that scans
42 ** over rows of the result from an EXPLAIN operation.
43 */
44 typedef struct explain_cursor explain_cursor;
45 struct explain_cursor {
46   sqlite3_vtab_cursor base;  /* Base class - must be first */
47   sqlite3 *db;               /* Database connection for this cursor */
48   char *zSql;                /* Value for the EXPLN_COLUMN_SQL column */
49   sqlite3_stmt *pExplain;    /* Statement being explained */
50   int rc;                    /* Result of last sqlite3_step() on pExplain */
51 };
52 
53 /*
54 ** The explainConnect() method is invoked to create a new
55 ** explain_vtab that describes the explain virtual table.
56 **
57 ** Think of this routine as the constructor for explain_vtab objects.
58 **
59 ** All this routine needs to do is:
60 **
61 **    (1) Allocate the explain_vtab object and initialize all fields.
62 **
63 **    (2) Tell SQLite (via the sqlite3_declare_vtab() interface) what the
64 **        result set of queries against explain will look like.
65 */
66 static int explainConnect(
67   sqlite3 *db,
68   void *pAux,
69   int argc, const char *const*argv,
70   sqlite3_vtab **ppVtab,
71   char **pzErr
72 ){
73   explain_vtab *pNew;
74   int rc;
75 
76 /* Column numbers */
77 #define EXPLN_COLUMN_ADDR     0   /* Instruction address */
78 #define EXPLN_COLUMN_OPCODE   1   /* Opcode */
79 #define EXPLN_COLUMN_P1       2   /* Operand 1 */
80 #define EXPLN_COLUMN_P2       3   /* Operand 2 */
81 #define EXPLN_COLUMN_P3       4   /* Operand 3 */
82 #define EXPLN_COLUMN_P4       5   /* Operand 4 */
83 #define EXPLN_COLUMN_P5       6   /* Operand 5 */
84 #define EXPLN_COLUMN_COMMENT  7   /* Comment */
85 #define EXPLN_COLUMN_SQL      8   /* SQL that is being explained */
86 
87 
88   rc = sqlite3_declare_vtab(db,
89      "CREATE TABLE x(addr,opcode,p1,p2,p3,p4,p5,comment,sql HIDDEN)");
90   if( rc==SQLITE_OK ){
91     pNew = sqlite3_malloc( sizeof(*pNew) );
92     *ppVtab = (sqlite3_vtab*)pNew;
93     if( pNew==0 ) return SQLITE_NOMEM;
94     memset(pNew, 0, sizeof(*pNew));
95     pNew->db = db;
96   }
97   return rc;
98 }
99 
100 /*
101 ** This method is the destructor for explain_cursor objects.
102 */
103 static int explainDisconnect(sqlite3_vtab *pVtab){
104   sqlite3_free(pVtab);
105   return SQLITE_OK;
106 }
107 
108 /*
109 ** Constructor for a new explain_cursor object.
110 */
111 static int explainOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
112   explain_cursor *pCur;
113   pCur = sqlite3_malloc( sizeof(*pCur) );
114   if( pCur==0 ) return SQLITE_NOMEM;
115   memset(pCur, 0, sizeof(*pCur));
116   pCur->db = ((explain_vtab*)p)->db;
117   *ppCursor = &pCur->base;
118   return SQLITE_OK;
119 }
120 
121 /*
122 ** Destructor for a explain_cursor.
123 */
124 static int explainClose(sqlite3_vtab_cursor *cur){
125   explain_cursor *pCur = (explain_cursor*)cur;
126   sqlite3_finalize(pCur->pExplain);
127   sqlite3_free(pCur->zSql);
128   sqlite3_free(pCur);
129   return SQLITE_OK;
130 }
131 
132 
133 /*
134 ** Advance a explain_cursor to its next row of output.
135 */
136 static int explainNext(sqlite3_vtab_cursor *cur){
137   explain_cursor *pCur = (explain_cursor*)cur;
138   pCur->rc = sqlite3_step(pCur->pExplain);
139   if( pCur->rc!=SQLITE_DONE && pCur->rc!=SQLITE_ROW ) return pCur->rc;
140   return SQLITE_OK;
141 }
142 
143 /*
144 ** Return values of columns for the row at which the explain_cursor
145 ** is currently pointing.
146 */
147 static int explainColumn(
148   sqlite3_vtab_cursor *cur,   /* The cursor */
149   sqlite3_context *ctx,       /* First argument to sqlite3_result_...() */
150   int i                       /* Which column to return */
151 ){
152   explain_cursor *pCur = (explain_cursor*)cur;
153   if( i==EXPLN_COLUMN_SQL ){
154     sqlite3_result_text(ctx, pCur->zSql, -1, SQLITE_TRANSIENT);
155   }else{
156     sqlite3_result_value(ctx, sqlite3_column_value(pCur->pExplain, i));
157   }
158   return SQLITE_OK;
159 }
160 
161 /*
162 ** Return the rowid for the current row.  In this implementation, the
163 ** rowid is the same as the output value.
164 */
165 static int explainRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
166   explain_cursor *pCur = (explain_cursor*)cur;
167   *pRowid = sqlite3_column_int64(pCur->pExplain, 0);
168   return SQLITE_OK;
169 }
170 
171 /*
172 ** Return TRUE if the cursor has been moved off of the last
173 ** row of output.
174 */
175 static int explainEof(sqlite3_vtab_cursor *cur){
176   explain_cursor *pCur = (explain_cursor*)cur;
177   return pCur->rc!=SQLITE_ROW;
178 }
179 
180 /*
181 ** This method is called to "rewind" the explain_cursor object back
182 ** to the first row of output.  This method is always called at least
183 ** once prior to any call to explainColumn() or explainRowid() or
184 ** explainEof().
185 **
186 ** The argv[0] is the SQL statement that is to be explained.
187 */
188 static int explainFilter(
189   sqlite3_vtab_cursor *pVtabCursor,
190   int idxNum, const char *idxStr,
191   int argc, sqlite3_value **argv
192 ){
193   explain_cursor *pCur = (explain_cursor *)pVtabCursor;
194   char *zSql = 0;
195   int rc;
196   sqlite3_finalize(pCur->pExplain);
197   pCur->pExplain = 0;
198   if( sqlite3_value_type(argv[0])!=SQLITE_TEXT ){
199     pCur->rc = SQLITE_DONE;
200     return SQLITE_OK;
201   }
202   sqlite3_free(pCur->zSql);
203   pCur->zSql = sqlite3_mprintf("%s", sqlite3_value_text(argv[0]));
204   if( pCur->zSql ){
205     zSql = sqlite3_mprintf("EXPLAIN %s", pCur->zSql);
206   }
207   if( zSql==0 ){
208     rc = SQLITE_NOMEM;
209   }else{
210     rc = sqlite3_prepare_v2(pCur->db, zSql, -1, &pCur->pExplain, 0);
211     sqlite3_free(zSql);
212   }
213   if( rc ){
214     sqlite3_finalize(pCur->pExplain);
215     pCur->pExplain = 0;
216     sqlite3_free(pCur->zSql);
217     pCur->zSql = 0;
218   }else{
219     pCur->rc = sqlite3_step(pCur->pExplain);
220     rc = (pCur->rc==SQLITE_DONE || pCur->rc==SQLITE_ROW) ? SQLITE_OK : pCur->rc;
221   }
222   return rc;
223 }
224 
225 /*
226 ** SQLite will invoke this method one or more times while planning a query
227 ** that uses the explain virtual table.  This routine needs to create
228 ** a query plan for each invocation and compute an estimated cost for that
229 ** plan.
230 */
231 static int explainBestIndex(
232   sqlite3_vtab *tab,
233   sqlite3_index_info *pIdxInfo
234 ){
235   int i;
236 
237   pIdxInfo->estimatedCost = (double)1000000;
238   pIdxInfo->estimatedRows = 500;
239   for(i=0; i<pIdxInfo->nConstraint; i++){
240     struct sqlite3_index_constraint *p = &pIdxInfo->aConstraint[i];
241     if( p->usable
242      && p->iColumn==EXPLN_COLUMN_SQL
243      && p->op==SQLITE_INDEX_CONSTRAINT_EQ
244     ){
245       pIdxInfo->estimatedCost = 10.0;
246       pIdxInfo->idxNum = 1;
247       pIdxInfo->aConstraintUsage[i].argvIndex = 1;
248       pIdxInfo->aConstraintUsage[i].omit = 1;
249       break;
250     }
251   }
252   return SQLITE_OK;
253 }
254 
255 /*
256 ** This following structure defines all the methods for the
257 ** explain virtual table.
258 */
259 static sqlite3_module explainModule = {
260   0,                         /* iVersion */
261   0,                         /* xCreate */
262   explainConnect,            /* xConnect */
263   explainBestIndex,          /* xBestIndex */
264   explainDisconnect,         /* xDisconnect */
265   0,                         /* xDestroy */
266   explainOpen,               /* xOpen - open a cursor */
267   explainClose,              /* xClose - close a cursor */
268   explainFilter,             /* xFilter - configure scan constraints */
269   explainNext,               /* xNext - advance a cursor */
270   explainEof,                /* xEof - check for end of scan */
271   explainColumn,             /* xColumn - read data */
272   explainRowid,              /* xRowid - read data */
273   0,                         /* xUpdate */
274   0,                         /* xBegin */
275   0,                         /* xSync */
276   0,                         /* xCommit */
277   0,                         /* xRollback */
278   0,                         /* xFindMethod */
279   0,                         /* xRename */
280   0,                         /* xSavepoint */
281   0,                         /* xRelease */
282   0,                         /* xRollbackTo */
283   0,                         /* xShadowName */
284 };
285 
286 #endif /* SQLITE_OMIT_VIRTUALTABLE */
287 
288 int sqlite3ExplainVtabInit(sqlite3 *db){
289   int rc = SQLITE_OK;
290 #ifndef SQLITE_OMIT_VIRTUALTABLE
291   rc = sqlite3_create_module(db, "explain", &explainModule, 0);
292 #endif
293   return rc;
294 }
295 
296 #ifdef _WIN32
297 __declspec(dllexport)
298 #endif
299 int sqlite3_explain_init(
300   sqlite3 *db,
301   char **pzErrMsg,
302   const sqlite3_api_routines *pApi
303 ){
304   int rc = SQLITE_OK;
305   SQLITE_EXTENSION_INIT2(pApi);
306 #ifndef SQLITE_OMIT_VIRTUALTABLE
307   rc = sqlite3ExplainVtabInit(db);
308 #endif
309   return rc;
310 }
311