xref: /sqlite-3.40.0/ext/misc/explain.c (revision 9b84f035)
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   }
212   if( rc ){
213     sqlite3_finalize(pCur->pExplain);
214     pCur->pExplain = 0;
215     sqlite3_free(pCur->zSql);
216     pCur->zSql = 0;
217   }else{
218     pCur->rc = sqlite3_step(pCur->pExplain);
219     rc = (pCur->rc==SQLITE_DONE || pCur->rc==SQLITE_ROW) ? SQLITE_OK : pCur->rc;
220   }
221   return rc;
222 }
223 
224 /*
225 ** SQLite will invoke this method one or more times while planning a query
226 ** that uses the explain virtual table.  This routine needs to create
227 ** a query plan for each invocation and compute an estimated cost for that
228 ** plan.
229 */
230 static int explainBestIndex(
231   sqlite3_vtab *tab,
232   sqlite3_index_info *pIdxInfo
233 ){
234   int i;
235 
236   pIdxInfo->estimatedCost = (double)1000000;
237   pIdxInfo->estimatedRows = 500;
238   for(i=0; i<pIdxInfo->nConstraint; i++){
239     struct sqlite3_index_constraint *p = &pIdxInfo->aConstraint[i];
240     if( p->usable
241      && p->iColumn==EXPLN_COLUMN_SQL
242      && p->op==SQLITE_INDEX_CONSTRAINT_EQ
243     ){
244       pIdxInfo->estimatedCost = 10.0;
245       pIdxInfo->idxNum = 1;
246       pIdxInfo->aConstraintUsage[i].argvIndex = 1;
247       pIdxInfo->aConstraintUsage[i].omit = 1;
248       break;
249     }
250   }
251   return SQLITE_OK;
252 }
253 
254 /*
255 ** This following structure defines all the methods for the
256 ** explain virtual table.
257 */
258 static sqlite3_module explainModule = {
259   0,                         /* iVersion */
260   0,                         /* xCreate */
261   explainConnect,            /* xConnect */
262   explainBestIndex,          /* xBestIndex */
263   explainDisconnect,         /* xDisconnect */
264   0,                         /* xDestroy */
265   explainOpen,               /* xOpen - open a cursor */
266   explainClose,              /* xClose - close a cursor */
267   explainFilter,             /* xFilter - configure scan constraints */
268   explainNext,               /* xNext - advance a cursor */
269   explainEof,                /* xEof - check for end of scan */
270   explainColumn,             /* xColumn - read data */
271   explainRowid,              /* xRowid - read data */
272   0,                         /* xUpdate */
273   0,                         /* xBegin */
274   0,                         /* xSync */
275   0,                         /* xCommit */
276   0,                         /* xRollback */
277   0,                         /* xFindMethod */
278   0,                         /* xRename */
279   0,                         /* xSavepoint */
280   0,                         /* xRelease */
281   0,                         /* xRollbackTo */
282 };
283 
284 #endif /* SQLITE_OMIT_VIRTUALTABLE */
285 
286 int sqlite3ExplainVtabInit(sqlite3 *db){
287   int rc = SQLITE_OK;
288 #ifndef SQLITE_OMIT_VIRTUALTABLE
289   rc = sqlite3_create_module(db, "explain", &explainModule, 0);
290 #endif
291   return rc;
292 }
293 
294 #ifdef _WIN32
295 __declspec(dllexport)
296 #endif
297 int sqlite3_explain_init(
298   sqlite3 *db,
299   char **pzErrMsg,
300   const sqlite3_api_routines *pApi
301 ){
302   int rc = SQLITE_OK;
303   SQLITE_EXTENSION_INIT2(pApi);
304 #ifndef SQLITE_OMIT_VIRTUALTABLE
305   rc = sqlite3ExplainVtabInit(db);
306 #endif
307   return rc;
308 }
309