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