xref: /sqlite-3.40.0/src/vdbevtab.c (revision 013e7bb7)
1691b5c54Sdrh /*
2691b5c54Sdrh ** 2020-03-23
3691b5c54Sdrh **
4691b5c54Sdrh ** The author disclaims copyright to this source code.  In place of
5691b5c54Sdrh ** a legal notice, here is a blessing:
6691b5c54Sdrh **
7691b5c54Sdrh **    May you do good and not evil.
8691b5c54Sdrh **    May you find forgiveness for yourself and forgive others.
9691b5c54Sdrh **    May you share freely, never taking more than you give.
10691b5c54Sdrh **
11691b5c54Sdrh *************************************************************************
12691b5c54Sdrh **
13691b5c54Sdrh ** This file implements virtual-tables for examining the bytecode content
14691b5c54Sdrh ** of a prepared statement.
15691b5c54Sdrh */
16691b5c54Sdrh #include "sqliteInt.h"
17d48eafb9Sdan #if defined(SQLITE_ENABLE_BYTECODE_VTAB) && !defined(SQLITE_OMIT_VIRTUALTABLE)
18691b5c54Sdrh #include "vdbeInt.h"
19691b5c54Sdrh 
20691b5c54Sdrh /* An instance of the bytecode() table-valued function.
21691b5c54Sdrh */
228c5163a6Sdrh typedef struct bytecodevtab bytecodevtab;
238c5163a6Sdrh struct bytecodevtab {
24691b5c54Sdrh   sqlite3_vtab base;     /* Base class - must be first */
258c5163a6Sdrh   sqlite3 *db;           /* Database connection */
268f78a528Sdrh   int bTablesUsed;       /* 2 for tables_used().  0 for bytecode(). */
27691b5c54Sdrh };
28691b5c54Sdrh 
29691b5c54Sdrh /* A cursor for scanning through the bytecode
30691b5c54Sdrh */
31691b5c54Sdrh typedef struct bytecodevtab_cursor bytecodevtab_cursor;
32691b5c54Sdrh struct bytecodevtab_cursor {
33691b5c54Sdrh   sqlite3_vtab_cursor base;  /* Base class - must be first */
348c5163a6Sdrh   sqlite3_stmt *pStmt;       /* The statement whose bytecode is displayed */
358c5163a6Sdrh   int iRowid;                /* The rowid of the output table */
368c5163a6Sdrh   int iAddr;                 /* Address */
378c5163a6Sdrh   int needFinalize;          /* Cursors owns pStmt and must finalize it */
3877972075Sdrh   int showSubprograms;       /* Provide a listing of subprograms */
398c5163a6Sdrh   Op *aOp;                   /* Operand array */
408c5163a6Sdrh   char *zP4;                 /* Rendered P4 value */
418f78a528Sdrh   const char *zType;         /* tables_used.type */
428f78a528Sdrh   const char *zSchema;       /* tables_used.schema */
438f78a528Sdrh   const char *zName;         /* tables_used.name */
448c5163a6Sdrh   Mem sub;                   /* Subprograms */
45691b5c54Sdrh };
46691b5c54Sdrh 
47691b5c54Sdrh /*
48691b5c54Sdrh ** Create a new bytecode() table-valued function.
49691b5c54Sdrh */
bytecodevtabConnect(sqlite3 * db,void * pAux,int argc,const char * const * argv,sqlite3_vtab ** ppVtab,char ** pzErr)50691b5c54Sdrh static int bytecodevtabConnect(
51691b5c54Sdrh   sqlite3 *db,
52691b5c54Sdrh   void *pAux,
53691b5c54Sdrh   int argc, const char *const*argv,
54691b5c54Sdrh   sqlite3_vtab **ppVtab,
55691b5c54Sdrh   char **pzErr
56691b5c54Sdrh ){
578c5163a6Sdrh   bytecodevtab *pNew;
58691b5c54Sdrh   int rc;
598f78a528Sdrh   int isTabUsed = pAux!=0;
608f78a528Sdrh   const char *azSchema[2] = {
618f78a528Sdrh     /* bytecode() schema */
62691b5c54Sdrh     "CREATE TABLE x("
63691b5c54Sdrh       "addr INT,"
64691b5c54Sdrh       "opcode TEXT,"
65691b5c54Sdrh       "p1 INT,"
66691b5c54Sdrh       "p2 INT,"
67691b5c54Sdrh       "p3 INT,"
68691b5c54Sdrh       "p4 TEXT,"
69691b5c54Sdrh       "p5 INT,"
70691b5c54Sdrh       "comment TEXT,"
71691b5c54Sdrh       "subprog TEXT,"
72691b5c54Sdrh       "stmt HIDDEN"
738f78a528Sdrh     ");",
748f78a528Sdrh 
758f78a528Sdrh     /* Tables_used() schema */
768f78a528Sdrh     "CREATE TABLE x("
778f78a528Sdrh       "type TEXT,"
788f78a528Sdrh       "schema TEXT,"
798f78a528Sdrh       "name TEXT,"
808f78a528Sdrh       "wr INT,"
818f78a528Sdrh       "subprog TEXT,"
828f78a528Sdrh       "stmt HIDDEN"
83691b5c54Sdrh    ");"
848f78a528Sdrh   };
858f78a528Sdrh 
868f78a528Sdrh   rc = sqlite3_declare_vtab(db, azSchema[isTabUsed]);
87691b5c54Sdrh   if( rc==SQLITE_OK ){
88691b5c54Sdrh     pNew = sqlite3_malloc( sizeof(*pNew) );
89691b5c54Sdrh     *ppVtab = (sqlite3_vtab*)pNew;
90691b5c54Sdrh     if( pNew==0 ) return SQLITE_NOMEM;
91691b5c54Sdrh     memset(pNew, 0, sizeof(*pNew));
928c5163a6Sdrh     pNew->db = db;
938f78a528Sdrh     pNew->bTablesUsed = isTabUsed*2;
94691b5c54Sdrh   }
95691b5c54Sdrh   return rc;
96691b5c54Sdrh }
97691b5c54Sdrh 
98691b5c54Sdrh /*
998c5163a6Sdrh ** This method is the destructor for bytecodevtab objects.
100691b5c54Sdrh */
bytecodevtabDisconnect(sqlite3_vtab * pVtab)101691b5c54Sdrh static int bytecodevtabDisconnect(sqlite3_vtab *pVtab){
1028c5163a6Sdrh   bytecodevtab *p = (bytecodevtab*)pVtab;
103691b5c54Sdrh   sqlite3_free(p);
104691b5c54Sdrh   return SQLITE_OK;
105691b5c54Sdrh }
106691b5c54Sdrh 
107691b5c54Sdrh /*
108691b5c54Sdrh ** Constructor for a new bytecodevtab_cursor object.
109691b5c54Sdrh */
bytecodevtabOpen(sqlite3_vtab * p,sqlite3_vtab_cursor ** ppCursor)110691b5c54Sdrh static int bytecodevtabOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
1118c5163a6Sdrh   bytecodevtab *pVTab = (bytecodevtab*)p;
112691b5c54Sdrh   bytecodevtab_cursor *pCur;
113691b5c54Sdrh   pCur = sqlite3_malloc( sizeof(*pCur) );
114691b5c54Sdrh   if( pCur==0 ) return SQLITE_NOMEM;
115691b5c54Sdrh   memset(pCur, 0, sizeof(*pCur));
1168c5163a6Sdrh   sqlite3VdbeMemInit(&pCur->sub, pVTab->db, 1);
117691b5c54Sdrh   *ppCursor = &pCur->base;
118691b5c54Sdrh   return SQLITE_OK;
119691b5c54Sdrh }
120691b5c54Sdrh 
121691b5c54Sdrh /*
1228c5163a6Sdrh ** Clear all internal content from a bytecodevtab cursor.
1238c5163a6Sdrh */
bytecodevtabCursorClear(bytecodevtab_cursor * pCur)1248c5163a6Sdrh static void bytecodevtabCursorClear(bytecodevtab_cursor *pCur){
1258c5163a6Sdrh   sqlite3_free(pCur->zP4);
1268c5163a6Sdrh   pCur->zP4 = 0;
127cf08f08dSdrh   sqlite3VdbeMemRelease(&pCur->sub);
1288c5163a6Sdrh   sqlite3VdbeMemSetNull(&pCur->sub);
1298c5163a6Sdrh   if( pCur->needFinalize ){
1308c5163a6Sdrh     sqlite3_finalize(pCur->pStmt);
1318c5163a6Sdrh   }
1328c5163a6Sdrh   pCur->pStmt = 0;
1338c5163a6Sdrh   pCur->needFinalize = 0;
1348f78a528Sdrh   pCur->zType = 0;
1358f78a528Sdrh   pCur->zSchema = 0;
1368f78a528Sdrh   pCur->zName = 0;
1378c5163a6Sdrh }
1388c5163a6Sdrh 
1398c5163a6Sdrh /*
140691b5c54Sdrh ** Destructor for a bytecodevtab_cursor.
141691b5c54Sdrh */
bytecodevtabClose(sqlite3_vtab_cursor * cur)142691b5c54Sdrh static int bytecodevtabClose(sqlite3_vtab_cursor *cur){
143691b5c54Sdrh   bytecodevtab_cursor *pCur = (bytecodevtab_cursor*)cur;
1448c5163a6Sdrh   bytecodevtabCursorClear(pCur);
145691b5c54Sdrh   sqlite3_free(pCur);
146691b5c54Sdrh   return SQLITE_OK;
147691b5c54Sdrh }
148691b5c54Sdrh 
149691b5c54Sdrh 
150691b5c54Sdrh /*
151691b5c54Sdrh ** Advance a bytecodevtab_cursor to its next row of output.
152691b5c54Sdrh */
bytecodevtabNext(sqlite3_vtab_cursor * cur)153691b5c54Sdrh static int bytecodevtabNext(sqlite3_vtab_cursor *cur){
154691b5c54Sdrh   bytecodevtab_cursor *pCur = (bytecodevtab_cursor*)cur;
1558f78a528Sdrh   bytecodevtab *pTab = (bytecodevtab*)cur->pVtab;
1568c5163a6Sdrh   int rc;
1578c5163a6Sdrh   if( pCur->zP4 ){
1588c5163a6Sdrh     sqlite3_free(pCur->zP4);
1598c5163a6Sdrh     pCur->zP4 = 0;
1608c5163a6Sdrh   }
1618f78a528Sdrh   if( pCur->zName ){
1628f78a528Sdrh     pCur->zName = 0;
1638f78a528Sdrh     pCur->zType = 0;
1648f78a528Sdrh     pCur->zSchema = 0;
1658f78a528Sdrh   }
16677972075Sdrh   rc = sqlite3VdbeNextOpcode(
16777972075Sdrh            (Vdbe*)pCur->pStmt,
16877972075Sdrh            pCur->showSubprograms ? &pCur->sub : 0,
1698f78a528Sdrh            pTab->bTablesUsed,
17077972075Sdrh            &pCur->iRowid,
17177972075Sdrh            &pCur->iAddr,
17277972075Sdrh            &pCur->aOp);
1738c5163a6Sdrh   if( rc!=SQLITE_OK ){
1748c5163a6Sdrh     sqlite3VdbeMemSetNull(&pCur->sub);
1758c5163a6Sdrh     pCur->aOp = 0;
1768c5163a6Sdrh   }
177691b5c54Sdrh   return SQLITE_OK;
178691b5c54Sdrh }
179691b5c54Sdrh 
180691b5c54Sdrh /*
1818c5163a6Sdrh ** Return TRUE if the cursor has been moved off of the last
1828c5163a6Sdrh ** row of output.
1838c5163a6Sdrh */
bytecodevtabEof(sqlite3_vtab_cursor * cur)1848c5163a6Sdrh static int bytecodevtabEof(sqlite3_vtab_cursor *cur){
1858c5163a6Sdrh   bytecodevtab_cursor *pCur = (bytecodevtab_cursor*)cur;
1868c5163a6Sdrh   return pCur->aOp==0;
1878c5163a6Sdrh }
1888c5163a6Sdrh 
1898c5163a6Sdrh /*
190691b5c54Sdrh ** Return values of columns for the row at which the bytecodevtab_cursor
191691b5c54Sdrh ** is currently pointing.
192691b5c54Sdrh */
bytecodevtabColumn(sqlite3_vtab_cursor * cur,sqlite3_context * ctx,int i)193691b5c54Sdrh static int bytecodevtabColumn(
194691b5c54Sdrh   sqlite3_vtab_cursor *cur,   /* The cursor */
195691b5c54Sdrh   sqlite3_context *ctx,       /* First argument to sqlite3_result_...() */
196691b5c54Sdrh   int i                       /* Which column to return */
197691b5c54Sdrh ){
198691b5c54Sdrh   bytecodevtab_cursor *pCur = (bytecodevtab_cursor*)cur;
1998f78a528Sdrh   bytecodevtab *pVTab = (bytecodevtab*)cur->pVtab;
2008c5163a6Sdrh   Op *pOp = pCur->aOp + pCur->iAddr;
2018f78a528Sdrh   if( pVTab->bTablesUsed ){
2028f78a528Sdrh     if( i==4 ){
2038f78a528Sdrh       i = 8;
2048f78a528Sdrh     }else{
2058f78a528Sdrh       if( i<=2 && pCur->zType==0 ){
2068f78a528Sdrh         Schema *pSchema;
2078f78a528Sdrh         HashElem *k;
2088f78a528Sdrh         int iDb = pOp->p3;
209*013e7bb7Sdrh         Pgno iRoot = (Pgno)pOp->p2;
2108f78a528Sdrh         sqlite3 *db = pVTab->db;
2118f78a528Sdrh         pSchema = db->aDb[iDb].pSchema;
2128f78a528Sdrh         pCur->zSchema = db->aDb[iDb].zDbSName;
2138f78a528Sdrh         for(k=sqliteHashFirst(&pSchema->tblHash); k; k=sqliteHashNext(k)){
2148f78a528Sdrh           Table *pTab = (Table*)sqliteHashData(k);
2158f78a528Sdrh           if( !IsVirtual(pTab) && pTab->tnum==iRoot ){
2168f78a528Sdrh             pCur->zName = pTab->zName;
2178f78a528Sdrh             pCur->zType = "table";
2188f78a528Sdrh             break;
2198f78a528Sdrh           }
2208f78a528Sdrh         }
2218f78a528Sdrh         if( pCur->zName==0 ){
2228f78a528Sdrh           for(k=sqliteHashFirst(&pSchema->idxHash); k; k=sqliteHashNext(k)){
2238f78a528Sdrh             Index *pIdx = (Index*)sqliteHashData(k);
2248f78a528Sdrh             if( pIdx->tnum==iRoot ){
2258f78a528Sdrh               pCur->zName = pIdx->zName;
2268f78a528Sdrh               pCur->zType = "index";
2278f78a528Sdrh             }
2288f78a528Sdrh           }
2298f78a528Sdrh         }
2308f78a528Sdrh       }
2318f78a528Sdrh       i += 10;
2328f78a528Sdrh     }
2338f78a528Sdrh   }
234691b5c54Sdrh   switch( i ){
2350518d061Sdrh     case 0:   /* addr */
2368c5163a6Sdrh       sqlite3_result_int(ctx, pCur->iAddr);
237691b5c54Sdrh       break;
2380518d061Sdrh     case 1:   /* opcode */
2398c5163a6Sdrh       sqlite3_result_text(ctx, (char*)sqlite3OpcodeName(pOp->opcode),
2408c5163a6Sdrh                           -1, SQLITE_STATIC);
2418c5163a6Sdrh       break;
2420518d061Sdrh     case 2:   /* p1 */
2438c5163a6Sdrh       sqlite3_result_int(ctx, pOp->p1);
2448c5163a6Sdrh       break;
2450518d061Sdrh     case 3:   /* p2 */
2468c5163a6Sdrh       sqlite3_result_int(ctx, pOp->p2);
2478c5163a6Sdrh       break;
2480518d061Sdrh     case 4:   /* p3 */
2498c5163a6Sdrh       sqlite3_result_int(ctx, pOp->p3);
2508c5163a6Sdrh       break;
2510518d061Sdrh     case 5:   /* p4 */
2520518d061Sdrh     case 7:   /* comment */
2538c5163a6Sdrh       if( pCur->zP4==0 ){
2548c5163a6Sdrh         pCur->zP4 = sqlite3VdbeDisplayP4(pVTab->db, pOp);
2558c5163a6Sdrh       }
2568c5163a6Sdrh       if( i==5 ){
2578c5163a6Sdrh         sqlite3_result_text(ctx, pCur->zP4, -1, SQLITE_STATIC);
2588c5163a6Sdrh       }else{
259eeb55d86Sdrh #ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
2608c5163a6Sdrh         char *zCom = sqlite3VdbeDisplayComment(pVTab->db, pOp, pCur->zP4);
2618c5163a6Sdrh         sqlite3_result_text(ctx, zCom, -1, sqlite3_free);
262eeb55d86Sdrh #endif
2638c5163a6Sdrh       }
2648c5163a6Sdrh       break;
2650518d061Sdrh     case 6:     /* p5 */
2668c5163a6Sdrh       sqlite3_result_int(ctx, pOp->p5);
267691b5c54Sdrh       break;
2680518d061Sdrh     case 8: {   /* subprog */
2690518d061Sdrh       Op *aOp = pCur->aOp;
2707e088a6cSdrh       assert( aOp[0].opcode==OP_Init );
2717e088a6cSdrh       assert( aOp[0].p4.z==0 || strncmp(aOp[0].p4.z,"-" "- ",3)==0 );
2720518d061Sdrh       if( pCur->iRowid==pCur->iAddr+1 ){
2730518d061Sdrh         break;  /* Result is NULL for the main program */
2747e088a6cSdrh       }else if( aOp[0].p4.z!=0 ){
2750518d061Sdrh          sqlite3_result_text(ctx, aOp[0].p4.z+3, -1, SQLITE_STATIC);
2760518d061Sdrh       }else{
2770518d061Sdrh          sqlite3_result_text(ctx, "(FK)", 4, SQLITE_STATIC);
2780518d061Sdrh       }
2790518d061Sdrh       break;
2800518d061Sdrh     }
2818f78a528Sdrh     case 10:  /* tables_used.type */
2828f78a528Sdrh       sqlite3_result_text(ctx, pCur->zType, -1, SQLITE_STATIC);
2838f78a528Sdrh       break;
2848f78a528Sdrh     case 11:  /* tables_used.schema */
2858f78a528Sdrh       sqlite3_result_text(ctx, pCur->zSchema, -1, SQLITE_STATIC);
2868f78a528Sdrh       break;
2878f78a528Sdrh     case 12:  /* tables_used.name */
2888f78a528Sdrh       sqlite3_result_text(ctx, pCur->zName, -1, SQLITE_STATIC);
2898f78a528Sdrh       break;
2908f78a528Sdrh     case 13:  /* tables_used.wr */
2918f78a528Sdrh       sqlite3_result_int(ctx, pOp->opcode==OP_OpenWrite);
2928f78a528Sdrh       break;
293691b5c54Sdrh   }
294691b5c54Sdrh   return SQLITE_OK;
295691b5c54Sdrh }
296691b5c54Sdrh 
297691b5c54Sdrh /*
298691b5c54Sdrh ** Return the rowid for the current row.  In this implementation, the
299691b5c54Sdrh ** rowid is the same as the output value.
300691b5c54Sdrh */
bytecodevtabRowid(sqlite3_vtab_cursor * cur,sqlite_int64 * pRowid)301691b5c54Sdrh static int bytecodevtabRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
302691b5c54Sdrh   bytecodevtab_cursor *pCur = (bytecodevtab_cursor*)cur;
303691b5c54Sdrh   *pRowid = pCur->iRowid;
304691b5c54Sdrh   return SQLITE_OK;
305691b5c54Sdrh }
306691b5c54Sdrh 
307691b5c54Sdrh /*
30877972075Sdrh ** Initialize a cursor.
30977972075Sdrh **
31077972075Sdrh **    idxNum==0     means show all subprograms
31177972075Sdrh **    idxNum==1     means show only the main bytecode and omit subprograms.
312691b5c54Sdrh */
bytecodevtabFilter(sqlite3_vtab_cursor * pVtabCursor,int idxNum,const char * idxStr,int argc,sqlite3_value ** argv)313691b5c54Sdrh static int bytecodevtabFilter(
314691b5c54Sdrh   sqlite3_vtab_cursor *pVtabCursor,
315691b5c54Sdrh   int idxNum, const char *idxStr,
316691b5c54Sdrh   int argc, sqlite3_value **argv
317691b5c54Sdrh ){
318691b5c54Sdrh   bytecodevtab_cursor *pCur = (bytecodevtab_cursor *)pVtabCursor;
3198c5163a6Sdrh   bytecodevtab *pVTab = (bytecodevtab *)pVtabCursor->pVtab;
3208c5163a6Sdrh   int rc = SQLITE_OK;
3218c5163a6Sdrh 
3228c5163a6Sdrh   bytecodevtabCursorClear(pCur);
3238c5163a6Sdrh   pCur->iRowid = 0;
3248c5163a6Sdrh   pCur->iAddr = 0;
32577972075Sdrh   pCur->showSubprograms = idxNum==0;
3268c5163a6Sdrh   assert( argc==1 );
3278c5163a6Sdrh   if( sqlite3_value_type(argv[0])==SQLITE_TEXT ){
3288c5163a6Sdrh     const char *zSql = (const char*)sqlite3_value_text(argv[0]);
3298c5163a6Sdrh     if( zSql==0 ){
3308c5163a6Sdrh       rc = SQLITE_NOMEM;
3318c5163a6Sdrh     }else{
3328c5163a6Sdrh       rc = sqlite3_prepare_v2(pVTab->db, zSql, -1, &pCur->pStmt, 0);
3338c5163a6Sdrh       pCur->needFinalize = 1;
3348c5163a6Sdrh     }
3358c5163a6Sdrh   }else{
3368c5163a6Sdrh     pCur->pStmt = (sqlite3_stmt*)sqlite3_value_pointer(argv[0],"stmt-pointer");
3378c5163a6Sdrh   }
3388c5163a6Sdrh   if( pCur->pStmt==0 ){
3398c5163a6Sdrh     pVTab->base.zErrMsg = sqlite3_mprintf(
3408f78a528Sdrh        "argument to %s() is not a valid SQL statement",
3418f78a528Sdrh        pVTab->bTablesUsed ? "tables_used" : "bytecode"
3428c5163a6Sdrh     );
3438c5163a6Sdrh     rc = SQLITE_ERROR;
3448c5163a6Sdrh   }else{
3458c5163a6Sdrh     bytecodevtabNext(pVtabCursor);
3468c5163a6Sdrh   }
3478c5163a6Sdrh   return rc;
348691b5c54Sdrh }
349691b5c54Sdrh 
350691b5c54Sdrh /*
3518c5163a6Sdrh ** We must have a single stmt=? constraint that will be passed through
3528c5163a6Sdrh ** into the xFilter method.  If there is no valid stmt=? constraint,
3538c5163a6Sdrh ** then return an SQLITE_CONSTRAINT error.
354691b5c54Sdrh */
bytecodevtabBestIndex(sqlite3_vtab * tab,sqlite3_index_info * pIdxInfo)355691b5c54Sdrh static int bytecodevtabBestIndex(
356691b5c54Sdrh   sqlite3_vtab *tab,
357691b5c54Sdrh   sqlite3_index_info *pIdxInfo
358691b5c54Sdrh ){
3598c5163a6Sdrh   int i;
3608c5163a6Sdrh   int rc = SQLITE_CONSTRAINT;
36177972075Sdrh   struct sqlite3_index_constraint *p;
3628f78a528Sdrh   bytecodevtab *pVTab = (bytecodevtab*)tab;
3638f78a528Sdrh   int iBaseCol = pVTab->bTablesUsed ? 4 : 8;
3648c5163a6Sdrh   pIdxInfo->estimatedCost = (double)100;
3658c5163a6Sdrh   pIdxInfo->estimatedRows = 100;
36677972075Sdrh   pIdxInfo->idxNum = 0;
36777972075Sdrh   for(i=0, p=pIdxInfo->aConstraint; i<pIdxInfo->nConstraint; i++, p++){
36877972075Sdrh     if( p->usable==0 ) continue;
3698f78a528Sdrh     if( p->op==SQLITE_INDEX_CONSTRAINT_EQ && p->iColumn==iBaseCol+1 ){
3708c5163a6Sdrh       rc = SQLITE_OK;
3718c5163a6Sdrh       pIdxInfo->aConstraintUsage[i].omit = 1;
3728c5163a6Sdrh       pIdxInfo->aConstraintUsage[i].argvIndex = 1;
37377972075Sdrh     }
3748f78a528Sdrh     if( p->op==SQLITE_INDEX_CONSTRAINT_ISNULL && p->iColumn==iBaseCol ){
37577972075Sdrh       pIdxInfo->aConstraintUsage[i].omit = 1;
37677972075Sdrh       pIdxInfo->idxNum = 1;
37777972075Sdrh     }
3788c5163a6Sdrh   }
3798c5163a6Sdrh   return rc;
380691b5c54Sdrh }
381691b5c54Sdrh 
382691b5c54Sdrh /*
383691b5c54Sdrh ** This following structure defines all the methods for the
384691b5c54Sdrh ** virtual table.
385691b5c54Sdrh */
386691b5c54Sdrh static sqlite3_module bytecodevtabModule = {
387691b5c54Sdrh   /* iVersion    */ 0,
388691b5c54Sdrh   /* xCreate     */ 0,
389691b5c54Sdrh   /* xConnect    */ bytecodevtabConnect,
390691b5c54Sdrh   /* xBestIndex  */ bytecodevtabBestIndex,
391691b5c54Sdrh   /* xDisconnect */ bytecodevtabDisconnect,
392691b5c54Sdrh   /* xDestroy    */ 0,
393691b5c54Sdrh   /* xOpen       */ bytecodevtabOpen,
394691b5c54Sdrh   /* xClose      */ bytecodevtabClose,
395691b5c54Sdrh   /* xFilter     */ bytecodevtabFilter,
396691b5c54Sdrh   /* xNext       */ bytecodevtabNext,
397691b5c54Sdrh   /* xEof        */ bytecodevtabEof,
398691b5c54Sdrh   /* xColumn     */ bytecodevtabColumn,
399691b5c54Sdrh   /* xRowid      */ bytecodevtabRowid,
400691b5c54Sdrh   /* xUpdate     */ 0,
401691b5c54Sdrh   /* xBegin      */ 0,
402691b5c54Sdrh   /* xSync       */ 0,
403691b5c54Sdrh   /* xCommit     */ 0,
404691b5c54Sdrh   /* xRollback   */ 0,
405691b5c54Sdrh   /* xFindMethod */ 0,
406691b5c54Sdrh   /* xRename     */ 0,
407691b5c54Sdrh   /* xSavepoint  */ 0,
408691b5c54Sdrh   /* xRelease    */ 0,
409691b5c54Sdrh   /* xRollbackTo */ 0,
410691b5c54Sdrh   /* xShadowName */ 0
411691b5c54Sdrh };
412691b5c54Sdrh 
413691b5c54Sdrh 
sqlite3VdbeBytecodeVtabInit(sqlite3 * db)414691b5c54Sdrh int sqlite3VdbeBytecodeVtabInit(sqlite3 *db){
415691b5c54Sdrh   int rc;
4168c5163a6Sdrh   rc = sqlite3_create_module(db, "bytecode", &bytecodevtabModule, 0);
4178f78a528Sdrh   if( rc==SQLITE_OK ){
4188f78a528Sdrh     rc = sqlite3_create_module(db, "tables_used", &bytecodevtabModule, &db);
4198f78a528Sdrh   }
420691b5c54Sdrh   return rc;
421691b5c54Sdrh }
42234d15667Sdan #elif defined(SQLITE_ENABLE_BYTECODE_VTAB)
sqlite3VdbeBytecodeVtabInit(sqlite3 * db)42334d15667Sdan int sqlite3VdbeBytecodeVtabInit(sqlite3 *db){ return SQLITE_OK; }
424691b5c54Sdrh #endif /* SQLITE_ENABLE_BYTECODE_VTAB */
425