19b84f035Sdrh /*
29b84f035Sdrh ** 2018-09-16
39b84f035Sdrh **
49b84f035Sdrh ** The author disclaims copyright to this source code. In place of
59b84f035Sdrh ** a legal notice, here is a blessing:
69b84f035Sdrh **
79b84f035Sdrh ** May you do good and not evil.
89b84f035Sdrh ** May you find forgiveness for yourself and forgive others.
99b84f035Sdrh ** May you share freely, never taking more than you give.
109b84f035Sdrh **
119b84f035Sdrh *************************************************************************
129b84f035Sdrh **
139b84f035Sdrh ** This file demonstrates an eponymous virtual table that returns the
149b84f035Sdrh ** EXPLAIN output from an SQL statement.
159b84f035Sdrh **
169b84f035Sdrh ** Usage example:
179b84f035Sdrh **
189b84f035Sdrh ** .load ./explain
19*067b92baSdrh ** SELECT p2 FROM explain('SELECT * FROM sqlite_schema')
209b84f035Sdrh ** WHERE opcode='OpenRead';
21d16f26a7Sdrh **
22d16f26a7Sdrh ** This module was originally written to help simplify SQLite testing,
23d16f26a7Sdrh ** by providing an easier means of verifying certain patterns in the
24d16f26a7Sdrh ** generated bytecode.
259b84f035Sdrh */
269b84f035Sdrh #if !defined(SQLITEINT_H)
279b84f035Sdrh #include "sqlite3ext.h"
289b84f035Sdrh #endif
299b84f035Sdrh SQLITE_EXTENSION_INIT1
309b84f035Sdrh #include <assert.h>
319b84f035Sdrh #include <string.h>
329b84f035Sdrh
339b84f035Sdrh #ifndef SQLITE_OMIT_VIRTUALTABLE
349b84f035Sdrh
359b84f035Sdrh /* explain_vtab is a subclass of sqlite3_vtab which will
369b84f035Sdrh ** serve as the underlying representation of a explain virtual table
379b84f035Sdrh */
389b84f035Sdrh typedef struct explain_vtab explain_vtab;
399b84f035Sdrh struct explain_vtab {
409b84f035Sdrh sqlite3_vtab base; /* Base class - must be first */
419b84f035Sdrh sqlite3 *db; /* Database connection for this explain vtab */
429b84f035Sdrh };
439b84f035Sdrh
449b84f035Sdrh /* explain_cursor is a subclass of sqlite3_vtab_cursor which will
459b84f035Sdrh ** serve as the underlying representation of a cursor that scans
469b84f035Sdrh ** over rows of the result from an EXPLAIN operation.
479b84f035Sdrh */
489b84f035Sdrh typedef struct explain_cursor explain_cursor;
499b84f035Sdrh struct explain_cursor {
509b84f035Sdrh sqlite3_vtab_cursor base; /* Base class - must be first */
519b84f035Sdrh sqlite3 *db; /* Database connection for this cursor */
529b84f035Sdrh char *zSql; /* Value for the EXPLN_COLUMN_SQL column */
539b84f035Sdrh sqlite3_stmt *pExplain; /* Statement being explained */
549b84f035Sdrh int rc; /* Result of last sqlite3_step() on pExplain */
559b84f035Sdrh };
569b84f035Sdrh
579b84f035Sdrh /*
589b84f035Sdrh ** The explainConnect() method is invoked to create a new
599b84f035Sdrh ** explain_vtab that describes the explain virtual table.
609b84f035Sdrh **
619b84f035Sdrh ** Think of this routine as the constructor for explain_vtab objects.
629b84f035Sdrh **
639b84f035Sdrh ** All this routine needs to do is:
649b84f035Sdrh **
659b84f035Sdrh ** (1) Allocate the explain_vtab object and initialize all fields.
669b84f035Sdrh **
679b84f035Sdrh ** (2) Tell SQLite (via the sqlite3_declare_vtab() interface) what the
689b84f035Sdrh ** result set of queries against explain will look like.
699b84f035Sdrh */
explainConnect(sqlite3 * db,void * pAux,int argc,const char * const * argv,sqlite3_vtab ** ppVtab,char ** pzErr)709b84f035Sdrh static int explainConnect(
719b84f035Sdrh sqlite3 *db,
729b84f035Sdrh void *pAux,
739b84f035Sdrh int argc, const char *const*argv,
749b84f035Sdrh sqlite3_vtab **ppVtab,
759b84f035Sdrh char **pzErr
769b84f035Sdrh ){
779b84f035Sdrh explain_vtab *pNew;
789b84f035Sdrh int rc;
799b84f035Sdrh
809b84f035Sdrh /* Column numbers */
819b84f035Sdrh #define EXPLN_COLUMN_ADDR 0 /* Instruction address */
829b84f035Sdrh #define EXPLN_COLUMN_OPCODE 1 /* Opcode */
839b84f035Sdrh #define EXPLN_COLUMN_P1 2 /* Operand 1 */
849b84f035Sdrh #define EXPLN_COLUMN_P2 3 /* Operand 2 */
859b84f035Sdrh #define EXPLN_COLUMN_P3 4 /* Operand 3 */
869b84f035Sdrh #define EXPLN_COLUMN_P4 5 /* Operand 4 */
879b84f035Sdrh #define EXPLN_COLUMN_P5 6 /* Operand 5 */
889b84f035Sdrh #define EXPLN_COLUMN_COMMENT 7 /* Comment */
899b84f035Sdrh #define EXPLN_COLUMN_SQL 8 /* SQL that is being explained */
909b84f035Sdrh
919b84f035Sdrh
929b84f035Sdrh rc = sqlite3_declare_vtab(db,
939b84f035Sdrh "CREATE TABLE x(addr,opcode,p1,p2,p3,p4,p5,comment,sql HIDDEN)");
949b84f035Sdrh if( rc==SQLITE_OK ){
959b84f035Sdrh pNew = sqlite3_malloc( sizeof(*pNew) );
969b84f035Sdrh *ppVtab = (sqlite3_vtab*)pNew;
979b84f035Sdrh if( pNew==0 ) return SQLITE_NOMEM;
989b84f035Sdrh memset(pNew, 0, sizeof(*pNew));
999b84f035Sdrh pNew->db = db;
1009b84f035Sdrh }
1019b84f035Sdrh return rc;
1029b84f035Sdrh }
1039b84f035Sdrh
1049b84f035Sdrh /*
1059b84f035Sdrh ** This method is the destructor for explain_cursor objects.
1069b84f035Sdrh */
explainDisconnect(sqlite3_vtab * pVtab)1079b84f035Sdrh static int explainDisconnect(sqlite3_vtab *pVtab){
1089b84f035Sdrh sqlite3_free(pVtab);
1099b84f035Sdrh return SQLITE_OK;
1109b84f035Sdrh }
1119b84f035Sdrh
1129b84f035Sdrh /*
1139b84f035Sdrh ** Constructor for a new explain_cursor object.
1149b84f035Sdrh */
explainOpen(sqlite3_vtab * p,sqlite3_vtab_cursor ** ppCursor)1159b84f035Sdrh static int explainOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
1169b84f035Sdrh explain_cursor *pCur;
1179b84f035Sdrh pCur = sqlite3_malloc( sizeof(*pCur) );
1189b84f035Sdrh if( pCur==0 ) return SQLITE_NOMEM;
1199b84f035Sdrh memset(pCur, 0, sizeof(*pCur));
1209b84f035Sdrh pCur->db = ((explain_vtab*)p)->db;
1219b84f035Sdrh *ppCursor = &pCur->base;
1229b84f035Sdrh return SQLITE_OK;
1239b84f035Sdrh }
1249b84f035Sdrh
1259b84f035Sdrh /*
1269b84f035Sdrh ** Destructor for a explain_cursor.
1279b84f035Sdrh */
explainClose(sqlite3_vtab_cursor * cur)1289b84f035Sdrh static int explainClose(sqlite3_vtab_cursor *cur){
1299b84f035Sdrh explain_cursor *pCur = (explain_cursor*)cur;
1309b84f035Sdrh sqlite3_finalize(pCur->pExplain);
1319b84f035Sdrh sqlite3_free(pCur->zSql);
1329b84f035Sdrh sqlite3_free(pCur);
1339b84f035Sdrh return SQLITE_OK;
1349b84f035Sdrh }
1359b84f035Sdrh
1369b84f035Sdrh
1379b84f035Sdrh /*
1389b84f035Sdrh ** Advance a explain_cursor to its next row of output.
1399b84f035Sdrh */
explainNext(sqlite3_vtab_cursor * cur)1409b84f035Sdrh static int explainNext(sqlite3_vtab_cursor *cur){
1419b84f035Sdrh explain_cursor *pCur = (explain_cursor*)cur;
1429b84f035Sdrh pCur->rc = sqlite3_step(pCur->pExplain);
1439b84f035Sdrh if( pCur->rc!=SQLITE_DONE && pCur->rc!=SQLITE_ROW ) return pCur->rc;
1449b84f035Sdrh return SQLITE_OK;
1459b84f035Sdrh }
1469b84f035Sdrh
1479b84f035Sdrh /*
1489b84f035Sdrh ** Return values of columns for the row at which the explain_cursor
1499b84f035Sdrh ** is currently pointing.
1509b84f035Sdrh */
explainColumn(sqlite3_vtab_cursor * cur,sqlite3_context * ctx,int i)1519b84f035Sdrh static int explainColumn(
1529b84f035Sdrh sqlite3_vtab_cursor *cur, /* The cursor */
1539b84f035Sdrh sqlite3_context *ctx, /* First argument to sqlite3_result_...() */
1549b84f035Sdrh int i /* Which column to return */
1559b84f035Sdrh ){
1569b84f035Sdrh explain_cursor *pCur = (explain_cursor*)cur;
1579b84f035Sdrh if( i==EXPLN_COLUMN_SQL ){
1589b84f035Sdrh sqlite3_result_text(ctx, pCur->zSql, -1, SQLITE_TRANSIENT);
1599b84f035Sdrh }else{
1609b84f035Sdrh sqlite3_result_value(ctx, sqlite3_column_value(pCur->pExplain, i));
1619b84f035Sdrh }
1629b84f035Sdrh return SQLITE_OK;
1639b84f035Sdrh }
1649b84f035Sdrh
1659b84f035Sdrh /*
1669b84f035Sdrh ** Return the rowid for the current row. In this implementation, the
1679b84f035Sdrh ** rowid is the same as the output value.
1689b84f035Sdrh */
explainRowid(sqlite3_vtab_cursor * cur,sqlite_int64 * pRowid)1699b84f035Sdrh static int explainRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
1709b84f035Sdrh explain_cursor *pCur = (explain_cursor*)cur;
1719b84f035Sdrh *pRowid = sqlite3_column_int64(pCur->pExplain, 0);
1729b84f035Sdrh return SQLITE_OK;
1739b84f035Sdrh }
1749b84f035Sdrh
1759b84f035Sdrh /*
1769b84f035Sdrh ** Return TRUE if the cursor has been moved off of the last
1779b84f035Sdrh ** row of output.
1789b84f035Sdrh */
explainEof(sqlite3_vtab_cursor * cur)1799b84f035Sdrh static int explainEof(sqlite3_vtab_cursor *cur){
1809b84f035Sdrh explain_cursor *pCur = (explain_cursor*)cur;
1819b84f035Sdrh return pCur->rc!=SQLITE_ROW;
1829b84f035Sdrh }
1839b84f035Sdrh
1849b84f035Sdrh /*
1859b84f035Sdrh ** This method is called to "rewind" the explain_cursor object back
1869b84f035Sdrh ** to the first row of output. This method is always called at least
1879b84f035Sdrh ** once prior to any call to explainColumn() or explainRowid() or
1889b84f035Sdrh ** explainEof().
1899b84f035Sdrh **
1909b84f035Sdrh ** The argv[0] is the SQL statement that is to be explained.
1919b84f035Sdrh */
explainFilter(sqlite3_vtab_cursor * pVtabCursor,int idxNum,const char * idxStr,int argc,sqlite3_value ** argv)1929b84f035Sdrh static int explainFilter(
1939b84f035Sdrh sqlite3_vtab_cursor *pVtabCursor,
1949b84f035Sdrh int idxNum, const char *idxStr,
1959b84f035Sdrh int argc, sqlite3_value **argv
1969b84f035Sdrh ){
1979b84f035Sdrh explain_cursor *pCur = (explain_cursor *)pVtabCursor;
1989b84f035Sdrh char *zSql = 0;
1999b84f035Sdrh int rc;
2009b84f035Sdrh sqlite3_finalize(pCur->pExplain);
2019b84f035Sdrh pCur->pExplain = 0;
2029b84f035Sdrh if( sqlite3_value_type(argv[0])!=SQLITE_TEXT ){
2039b84f035Sdrh pCur->rc = SQLITE_DONE;
2049b84f035Sdrh return SQLITE_OK;
2059b84f035Sdrh }
2069b84f035Sdrh sqlite3_free(pCur->zSql);
2079b84f035Sdrh pCur->zSql = sqlite3_mprintf("%s", sqlite3_value_text(argv[0]));
2089b84f035Sdrh if( pCur->zSql ){
2099b84f035Sdrh zSql = sqlite3_mprintf("EXPLAIN %s", pCur->zSql);
2109b84f035Sdrh }
2119b84f035Sdrh if( zSql==0 ){
2129b84f035Sdrh rc = SQLITE_NOMEM;
2139b84f035Sdrh }else{
2149b84f035Sdrh rc = sqlite3_prepare_v2(pCur->db, zSql, -1, &pCur->pExplain, 0);
2156557a07cSdrh sqlite3_free(zSql);
2169b84f035Sdrh }
2179b84f035Sdrh if( rc ){
2189b84f035Sdrh sqlite3_finalize(pCur->pExplain);
2199b84f035Sdrh pCur->pExplain = 0;
2209b84f035Sdrh sqlite3_free(pCur->zSql);
2219b84f035Sdrh pCur->zSql = 0;
2229b84f035Sdrh }else{
2239b84f035Sdrh pCur->rc = sqlite3_step(pCur->pExplain);
2249b84f035Sdrh rc = (pCur->rc==SQLITE_DONE || pCur->rc==SQLITE_ROW) ? SQLITE_OK : pCur->rc;
2259b84f035Sdrh }
2269b84f035Sdrh return rc;
2279b84f035Sdrh }
2289b84f035Sdrh
2299b84f035Sdrh /*
2309b84f035Sdrh ** SQLite will invoke this method one or more times while planning a query
2319b84f035Sdrh ** that uses the explain virtual table. This routine needs to create
2329b84f035Sdrh ** a query plan for each invocation and compute an estimated cost for that
2339b84f035Sdrh ** plan.
2349b84f035Sdrh */
explainBestIndex(sqlite3_vtab * tab,sqlite3_index_info * pIdxInfo)2359b84f035Sdrh static int explainBestIndex(
2369b84f035Sdrh sqlite3_vtab *tab,
2379b84f035Sdrh sqlite3_index_info *pIdxInfo
2389b84f035Sdrh ){
239d16f26a7Sdrh int i; /* Loop counter */
240d16f26a7Sdrh int idx = -1; /* Index of a usable == constraint against SQL */
241d16f26a7Sdrh int unusable = 0; /* True if there are unusable constraints on SQL */
2429b84f035Sdrh
2439b84f035Sdrh pIdxInfo->estimatedRows = 500;
2449b84f035Sdrh for(i=0; i<pIdxInfo->nConstraint; i++){
2459b84f035Sdrh struct sqlite3_index_constraint *p = &pIdxInfo->aConstraint[i];
246d16f26a7Sdrh if( p->iColumn!=EXPLN_COLUMN_SQL ) continue;
247d16f26a7Sdrh if( !p->usable ){
248d16f26a7Sdrh unusable = 1;
249d16f26a7Sdrh }else if( p->op==SQLITE_INDEX_CONSTRAINT_EQ ){
250d16f26a7Sdrh idx = i;
251d16f26a7Sdrh }
252d16f26a7Sdrh }
253d16f26a7Sdrh if( idx>=0 ){
254d16f26a7Sdrh /* There exists a usable == constraint against the SQL column */
2559b84f035Sdrh pIdxInfo->estimatedCost = 10.0;
2569b84f035Sdrh pIdxInfo->idxNum = 1;
257d16f26a7Sdrh pIdxInfo->aConstraintUsage[idx].argvIndex = 1;
258d16f26a7Sdrh pIdxInfo->aConstraintUsage[idx].omit = 1;
259d16f26a7Sdrh }else if( unusable ){
260d16f26a7Sdrh /* There are unusable constraints against the SQL column. Do not allow
261d16f26a7Sdrh ** this plan to continue forward. */
262d16f26a7Sdrh return SQLITE_CONSTRAINT;
2639b84f035Sdrh }
2649b84f035Sdrh return SQLITE_OK;
2659b84f035Sdrh }
2669b84f035Sdrh
2679b84f035Sdrh /*
2689b84f035Sdrh ** This following structure defines all the methods for the
2699b84f035Sdrh ** explain virtual table.
2709b84f035Sdrh */
2719b84f035Sdrh static sqlite3_module explainModule = {
2729b84f035Sdrh 0, /* iVersion */
2739b84f035Sdrh 0, /* xCreate */
2749b84f035Sdrh explainConnect, /* xConnect */
2759b84f035Sdrh explainBestIndex, /* xBestIndex */
2769b84f035Sdrh explainDisconnect, /* xDisconnect */
2779b84f035Sdrh 0, /* xDestroy */
2789b84f035Sdrh explainOpen, /* xOpen - open a cursor */
2799b84f035Sdrh explainClose, /* xClose - close a cursor */
2809b84f035Sdrh explainFilter, /* xFilter - configure scan constraints */
2819b84f035Sdrh explainNext, /* xNext - advance a cursor */
2829b84f035Sdrh explainEof, /* xEof - check for end of scan */
2839b84f035Sdrh explainColumn, /* xColumn - read data */
2849b84f035Sdrh explainRowid, /* xRowid - read data */
2859b84f035Sdrh 0, /* xUpdate */
2869b84f035Sdrh 0, /* xBegin */
2879b84f035Sdrh 0, /* xSync */
2889b84f035Sdrh 0, /* xCommit */
2899b84f035Sdrh 0, /* xRollback */
2909b84f035Sdrh 0, /* xFindMethod */
2919b84f035Sdrh 0, /* xRename */
2929b84f035Sdrh 0, /* xSavepoint */
2939b84f035Sdrh 0, /* xRelease */
2949b84f035Sdrh 0, /* xRollbackTo */
29584c501baSdrh 0, /* xShadowName */
2969b84f035Sdrh };
2979b84f035Sdrh
2989b84f035Sdrh #endif /* SQLITE_OMIT_VIRTUALTABLE */
2999b84f035Sdrh
sqlite3ExplainVtabInit(sqlite3 * db)3009b84f035Sdrh int sqlite3ExplainVtabInit(sqlite3 *db){
3019b84f035Sdrh int rc = SQLITE_OK;
3029b84f035Sdrh #ifndef SQLITE_OMIT_VIRTUALTABLE
3039b84f035Sdrh rc = sqlite3_create_module(db, "explain", &explainModule, 0);
3049b84f035Sdrh #endif
3059b84f035Sdrh return rc;
3069b84f035Sdrh }
3079b84f035Sdrh
3089b84f035Sdrh #ifdef _WIN32
3099b84f035Sdrh __declspec(dllexport)
3109b84f035Sdrh #endif
sqlite3_explain_init(sqlite3 * db,char ** pzErrMsg,const sqlite3_api_routines * pApi)3119b84f035Sdrh int sqlite3_explain_init(
3129b84f035Sdrh sqlite3 *db,
3139b84f035Sdrh char **pzErrMsg,
3149b84f035Sdrh const sqlite3_api_routines *pApi
3159b84f035Sdrh ){
3169b84f035Sdrh int rc = SQLITE_OK;
3179b84f035Sdrh SQLITE_EXTENSION_INIT2(pApi);
3189b84f035Sdrh #ifndef SQLITE_OMIT_VIRTUALTABLE
3199b84f035Sdrh rc = sqlite3ExplainVtabInit(db);
3209b84f035Sdrh #endif
3219b84f035Sdrh return rc;
3229b84f035Sdrh }
323