xref: /sqlite-3.40.0/src/vdbevtab.c (revision cf08f08d)
1 /*
2 ** 2020-03-23
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 implements virtual-tables for examining the bytecode content
14 ** of a prepared statement.
15 */
16 #ifdef SQLITE_ENABLE_BYTECODE_VTAB
17 #include "sqliteInt.h"
18 #include "vdbeInt.h"
19 
20 /* An instance of the bytecode() table-valued function.
21 */
22 typedef struct bytecodevtab bytecodevtab;
23 struct bytecodevtab {
24   sqlite3_vtab base;     /* Base class - must be first */
25   sqlite3 *db;           /* Database connection */
26 };
27 
28 /* A cursor for scanning through the bytecode
29 */
30 typedef struct bytecodevtab_cursor bytecodevtab_cursor;
31 struct bytecodevtab_cursor {
32   sqlite3_vtab_cursor base;  /* Base class - must be first */
33   sqlite3_stmt *pStmt;       /* The statement whose bytecode is displayed */
34   int iRowid;                /* The rowid of the output table */
35   int iAddr;                 /* Address */
36   int needFinalize;          /* Cursors owns pStmt and must finalize it */
37   Op *aOp;                   /* Operand array */
38   char *zP4;                 /* Rendered P4 value */
39   Mem sub;                   /* Subprograms */
40 };
41 
42 /*
43 ** Create a new bytecode() table-valued function.
44 */
45 static int bytecodevtabConnect(
46   sqlite3 *db,
47   void *pAux,
48   int argc, const char *const*argv,
49   sqlite3_vtab **ppVtab,
50   char **pzErr
51 ){
52   bytecodevtab *pNew;
53   int rc;
54 
55   rc = sqlite3_declare_vtab(db,
56          "CREATE TABLE x("
57            "addr INT,"
58            "opcode TEXT,"
59            "p1 INT,"
60            "p2 INT,"
61            "p3 INT,"
62            "p4 TEXT,"
63            "p5 INT,"
64            "comment TEXT,"
65            "subprog TEXT,"
66            "stmt HIDDEN"
67          ");"
68        );
69   if( rc==SQLITE_OK ){
70     pNew = sqlite3_malloc( sizeof(*pNew) );
71     *ppVtab = (sqlite3_vtab*)pNew;
72     if( pNew==0 ) return SQLITE_NOMEM;
73     memset(pNew, 0, sizeof(*pNew));
74     pNew->db = db;
75   }
76   return rc;
77 }
78 
79 /*
80 ** This method is the destructor for bytecodevtab objects.
81 */
82 static int bytecodevtabDisconnect(sqlite3_vtab *pVtab){
83   bytecodevtab *p = (bytecodevtab*)pVtab;
84   sqlite3_free(p);
85   return SQLITE_OK;
86 }
87 
88 /*
89 ** Constructor for a new bytecodevtab_cursor object.
90 */
91 static int bytecodevtabOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
92   bytecodevtab *pVTab = (bytecodevtab*)p;
93   bytecodevtab_cursor *pCur;
94   pCur = sqlite3_malloc( sizeof(*pCur) );
95   if( pCur==0 ) return SQLITE_NOMEM;
96   memset(pCur, 0, sizeof(*pCur));
97   sqlite3VdbeMemInit(&pCur->sub, pVTab->db, 1);
98   *ppCursor = &pCur->base;
99   return SQLITE_OK;
100 }
101 
102 /*
103 ** Clear all internal content from a bytecodevtab cursor.
104 */
105 static void bytecodevtabCursorClear(bytecodevtab_cursor *pCur){
106   sqlite3_free(pCur->zP4);
107   pCur->zP4 = 0;
108   sqlite3VdbeMemRelease(&pCur->sub);
109   sqlite3VdbeMemSetNull(&pCur->sub);
110   if( pCur->needFinalize ){
111     sqlite3_finalize(pCur->pStmt);
112   }
113   pCur->pStmt = 0;
114   pCur->needFinalize = 0;
115 }
116 
117 /*
118 ** Destructor for a bytecodevtab_cursor.
119 */
120 static int bytecodevtabClose(sqlite3_vtab_cursor *cur){
121   bytecodevtab_cursor *pCur = (bytecodevtab_cursor*)cur;
122   bytecodevtabCursorClear(pCur);
123   sqlite3_free(pCur);
124   return SQLITE_OK;
125 }
126 
127 
128 /*
129 ** Advance a bytecodevtab_cursor to its next row of output.
130 */
131 static int bytecodevtabNext(sqlite3_vtab_cursor *cur){
132   bytecodevtab_cursor *pCur = (bytecodevtab_cursor*)cur;
133   int rc;
134   if( pCur->zP4 ){
135     sqlite3_free(pCur->zP4);
136     pCur->zP4 = 0;
137   }
138   rc = sqlite3VdbeNextOpcode((Vdbe*)pCur->pStmt, &pCur->sub, 0,
139                              &pCur->iRowid, &pCur->iAddr, &pCur->aOp);
140   if( rc!=SQLITE_OK ){
141     sqlite3VdbeMemSetNull(&pCur->sub);
142     pCur->aOp = 0;
143   }
144   return SQLITE_OK;
145 }
146 
147 /*
148 ** Return TRUE if the cursor has been moved off of the last
149 ** row of output.
150 */
151 static int bytecodevtabEof(sqlite3_vtab_cursor *cur){
152   bytecodevtab_cursor *pCur = (bytecodevtab_cursor*)cur;
153   return pCur->aOp==0;
154 }
155 
156 /*
157 ** Return values of columns for the row at which the bytecodevtab_cursor
158 ** is currently pointing.
159 */
160 static int bytecodevtabColumn(
161   sqlite3_vtab_cursor *cur,   /* The cursor */
162   sqlite3_context *ctx,       /* First argument to sqlite3_result_...() */
163   int i                       /* Which column to return */
164 ){
165   bytecodevtab_cursor *pCur = (bytecodevtab_cursor*)cur;
166   bytecodevtab *pVTab;
167   Op *pOp = pCur->aOp + pCur->iAddr;
168   switch( i ){
169     case 0:   /* addr */
170       sqlite3_result_int(ctx, pCur->iAddr);
171       break;
172     case 1:   /* opcode */
173       sqlite3_result_text(ctx, (char*)sqlite3OpcodeName(pOp->opcode),
174                           -1, SQLITE_STATIC);
175       break;
176     case 2:   /* p1 */
177       sqlite3_result_int(ctx, pOp->p1);
178       break;
179     case 3:   /* p2 */
180       sqlite3_result_int(ctx, pOp->p2);
181       break;
182     case 4:   /* p3 */
183       sqlite3_result_int(ctx, pOp->p3);
184       break;
185     case 5:   /* p4 */
186     case 7:   /* comment */
187       pVTab = (bytecodevtab*)cur->pVtab;
188       if( pCur->zP4==0 ){
189         pCur->zP4 = sqlite3VdbeDisplayP4(pVTab->db, pOp);
190       }
191       if( i==5 ){
192         sqlite3_result_text(ctx, pCur->zP4, -1, SQLITE_STATIC);
193       }else{
194 #ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
195         char *zCom = sqlite3VdbeDisplayComment(pVTab->db, pOp, pCur->zP4);
196         sqlite3_result_text(ctx, zCom, -1, sqlite3_free);
197 #endif
198       }
199       break;
200     case 6:     /* p5 */
201       sqlite3_result_int(ctx, pOp->p5);
202       break;
203     case 8: {   /* subprog */
204       Op *aOp = pCur->aOp;
205       if( pCur->iRowid==pCur->iAddr+1 ){
206         break;  /* Result is NULL for the main program */
207       }else if( aOp[0].p4type==P4_DYNAMIC
208        && aOp[0].p4.z!=0
209        && strncmp(aOp[0].p4.z,"-- ", 3)==0 ){
210          sqlite3_result_text(ctx, aOp[0].p4.z+3, -1, SQLITE_STATIC);
211       }else{
212          sqlite3_result_text(ctx, "(FK)", 4, SQLITE_STATIC);
213       }
214       break;
215     }
216   }
217   return SQLITE_OK;
218 }
219 
220 /*
221 ** Return the rowid for the current row.  In this implementation, the
222 ** rowid is the same as the output value.
223 */
224 static int bytecodevtabRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
225   bytecodevtab_cursor *pCur = (bytecodevtab_cursor*)cur;
226   *pRowid = pCur->iRowid;
227   return SQLITE_OK;
228 }
229 
230 /*
231 ** Initialize a cursor to use a new
232 ** to the first row of output.  This method is always called at least
233 ** once prior to any call to bytecodevtabColumn() or bytecodevtabRowid() or
234 ** bytecodevtabEof().
235 */
236 static int bytecodevtabFilter(
237   sqlite3_vtab_cursor *pVtabCursor,
238   int idxNum, const char *idxStr,
239   int argc, sqlite3_value **argv
240 ){
241   bytecodevtab_cursor *pCur = (bytecodevtab_cursor *)pVtabCursor;
242   bytecodevtab *pVTab = (bytecodevtab *)pVtabCursor->pVtab;
243   int rc = SQLITE_OK;
244 
245   bytecodevtabCursorClear(pCur);
246   pCur->iRowid = 0;
247   pCur->iAddr = 0;
248   assert( argc==1 );
249   if( sqlite3_value_type(argv[0])==SQLITE_TEXT ){
250     const char *zSql = (const char*)sqlite3_value_text(argv[0]);
251     if( zSql==0 ){
252       rc = SQLITE_NOMEM;
253     }else{
254       rc = sqlite3_prepare_v2(pVTab->db, zSql, -1, &pCur->pStmt, 0);
255       pCur->needFinalize = 1;
256     }
257   }else{
258     pCur->pStmt = (sqlite3_stmt*)sqlite3_value_pointer(argv[0],"stmt-pointer");
259   }
260   if( pCur->pStmt==0 ){
261     pVTab->base.zErrMsg = sqlite3_mprintf(
262        "argument to bytecode() is not a valid SQL statement"
263     );
264     rc = SQLITE_ERROR;
265   }else{
266     bytecodevtabNext(pVtabCursor);
267   }
268   return rc;
269 }
270 
271 /*
272 ** We must have a single stmt=? constraint that will be passed through
273 ** into the xFilter method.  If there is no valid stmt=? constraint,
274 ** then return an SQLITE_CONSTRAINT error.
275 */
276 static int bytecodevtabBestIndex(
277   sqlite3_vtab *tab,
278   sqlite3_index_info *pIdxInfo
279 ){
280   int i;
281   int rc = SQLITE_CONSTRAINT;
282   pIdxInfo->estimatedCost = (double)100;
283   pIdxInfo->estimatedRows = 100;
284   for(i=0; i<pIdxInfo->nConstraint; i++){
285     if( pIdxInfo->aConstraint[i].usable==0 ) continue;
286     if( pIdxInfo->aConstraint[i].op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue;
287     if( pIdxInfo->aConstraint[i].iColumn!=9 ) continue;
288     rc = SQLITE_OK;
289     pIdxInfo->aConstraintUsage[i].omit = 1;
290     pIdxInfo->aConstraintUsage[i].argvIndex = 1;
291     break;
292   }
293   return rc;
294 }
295 
296 /*
297 ** This following structure defines all the methods for the
298 ** virtual table.
299 */
300 static sqlite3_module bytecodevtabModule = {
301   /* iVersion    */ 0,
302   /* xCreate     */ 0,
303   /* xConnect    */ bytecodevtabConnect,
304   /* xBestIndex  */ bytecodevtabBestIndex,
305   /* xDisconnect */ bytecodevtabDisconnect,
306   /* xDestroy    */ 0,
307   /* xOpen       */ bytecodevtabOpen,
308   /* xClose      */ bytecodevtabClose,
309   /* xFilter     */ bytecodevtabFilter,
310   /* xNext       */ bytecodevtabNext,
311   /* xEof        */ bytecodevtabEof,
312   /* xColumn     */ bytecodevtabColumn,
313   /* xRowid      */ bytecodevtabRowid,
314   /* xUpdate     */ 0,
315   /* xBegin      */ 0,
316   /* xSync       */ 0,
317   /* xCommit     */ 0,
318   /* xRollback   */ 0,
319   /* xFindMethod */ 0,
320   /* xRename     */ 0,
321   /* xSavepoint  */ 0,
322   /* xRelease    */ 0,
323   /* xRollbackTo */ 0,
324   /* xShadowName */ 0
325 };
326 
327 
328 int sqlite3VdbeBytecodeVtabInit(sqlite3 *db){
329   int rc;
330   rc = sqlite3_create_module(db, "bytecode", &bytecodevtabModule, 0);
331   return rc;
332 }
333 #endif /* SQLITE_ENABLE_BYTECODE_VTAB */
334