1 /* 2 ** 2017-05-31 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 information 14 ** about all prepared statements for the database connection. 15 ** 16 ** Usage example: 17 ** 18 ** .load ./stmt 19 ** .mode line 20 ** .header on 21 ** SELECT * FROM stmt; 22 */ 23 #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_STMTVTAB) 24 #if !defined(SQLITEINT_H) 25 #include "sqlite3ext.h" 26 #endif 27 SQLITE_EXTENSION_INIT1 28 #include <assert.h> 29 #include <string.h> 30 31 #ifndef SQLITE_OMIT_VIRTUALTABLE 32 33 /* stmt_vtab is a subclass of sqlite3_vtab which will 34 ** serve as the underlying representation of a stmt virtual table 35 */ 36 typedef struct stmt_vtab stmt_vtab; 37 struct stmt_vtab { 38 sqlite3_vtab base; /* Base class - must be first */ 39 sqlite3 *db; /* Database connection for this stmt vtab */ 40 }; 41 42 /* stmt_cursor is a subclass of sqlite3_vtab_cursor which will 43 ** serve as the underlying representation of a cursor that scans 44 ** over rows of the result 45 */ 46 typedef struct stmt_cursor stmt_cursor; 47 struct stmt_cursor { 48 sqlite3_vtab_cursor base; /* Base class - must be first */ 49 sqlite3 *db; /* Database connection for this cursor */ 50 sqlite3_stmt *pStmt; /* Statement cursor is currently pointing at */ 51 sqlite3_int64 iRowid; /* The rowid */ 52 }; 53 54 /* 55 ** The stmtConnect() method is invoked to create a new 56 ** stmt_vtab that describes the stmt virtual table. 57 ** 58 ** Think of this routine as the constructor for stmt_vtab objects. 59 ** 60 ** All this routine needs to do is: 61 ** 62 ** (1) Allocate the stmt_vtab object and initialize all fields. 63 ** 64 ** (2) Tell SQLite (via the sqlite3_declare_vtab() interface) what the 65 ** result set of queries against stmt will look like. 66 */ 67 static int stmtConnect( 68 sqlite3 *db, 69 void *pAux, 70 int argc, const char *const*argv, 71 sqlite3_vtab **ppVtab, 72 char **pzErr 73 ){ 74 stmt_vtab *pNew; 75 int rc; 76 77 /* Column numbers */ 78 #define STMT_COLUMN_SQL 0 /* SQL for the statement */ 79 #define STMT_COLUMN_NCOL 1 /* Number of result columns */ 80 #define STMT_COLUMN_RO 2 /* True if read-only */ 81 #define STMT_COLUMN_BUSY 3 /* True if currently busy */ 82 #define STMT_COLUMN_NSCAN 4 /* SQLITE_STMTSTATUS_FULLSCAN_STEP */ 83 #define STMT_COLUMN_NSORT 5 /* SQLITE_STMTSTATUS_SORT */ 84 #define STMT_COLUMN_NAIDX 6 /* SQLITE_STMTSTATUS_AUTOINDEX */ 85 #define STMT_COLUMN_NSTEP 7 /* SQLITE_STMTSTATUS_VM_STEP */ 86 #define STMT_COLUMN_REPREP 8 /* SQLITE_STMTSTATUS_REPREPARE */ 87 #define STMT_COLUMN_RUN 9 /* SQLITE_STMTSTATUS_RUN */ 88 #define STMT_COLUMN_MEM 10 /* SQLITE_STMTSTATUS_MEMUSED */ 89 90 91 rc = sqlite3_declare_vtab(db, 92 "CREATE TABLE x(sql,ncol,ro,busy,nscan,nsort,naidx,nstep," 93 "reprep,run,mem)"); 94 if( rc==SQLITE_OK ){ 95 pNew = sqlite3_malloc( sizeof(*pNew) ); 96 *ppVtab = (sqlite3_vtab*)pNew; 97 if( pNew==0 ) return SQLITE_NOMEM; 98 memset(pNew, 0, sizeof(*pNew)); 99 pNew->db = db; 100 } 101 return rc; 102 } 103 104 /* 105 ** This method is the destructor for stmt_cursor objects. 106 */ 107 static int stmtDisconnect(sqlite3_vtab *pVtab){ 108 sqlite3_free(pVtab); 109 return SQLITE_OK; 110 } 111 112 /* 113 ** Constructor for a new stmt_cursor object. 114 */ 115 static int stmtOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){ 116 stmt_cursor *pCur; 117 pCur = sqlite3_malloc( sizeof(*pCur) ); 118 if( pCur==0 ) return SQLITE_NOMEM; 119 memset(pCur, 0, sizeof(*pCur)); 120 pCur->db = ((stmt_vtab*)p)->db; 121 *ppCursor = &pCur->base; 122 return SQLITE_OK; 123 } 124 125 /* 126 ** Destructor for a stmt_cursor. 127 */ 128 static int stmtClose(sqlite3_vtab_cursor *cur){ 129 sqlite3_free(cur); 130 return SQLITE_OK; 131 } 132 133 134 /* 135 ** Advance a stmt_cursor to its next row of output. 136 */ 137 static int stmtNext(sqlite3_vtab_cursor *cur){ 138 stmt_cursor *pCur = (stmt_cursor*)cur; 139 pCur->iRowid++; 140 pCur->pStmt = sqlite3_next_stmt(pCur->db, pCur->pStmt); 141 return SQLITE_OK; 142 } 143 144 /* 145 ** Return values of columns for the row at which the stmt_cursor 146 ** is currently pointing. 147 */ 148 static int stmtColumn( 149 sqlite3_vtab_cursor *cur, /* The cursor */ 150 sqlite3_context *ctx, /* First argument to sqlite3_result_...() */ 151 int i /* Which column to return */ 152 ){ 153 stmt_cursor *pCur = (stmt_cursor*)cur; 154 switch( i ){ 155 case STMT_COLUMN_SQL: { 156 sqlite3_result_text(ctx, sqlite3_sql(pCur->pStmt), -1, SQLITE_TRANSIENT); 157 break; 158 } 159 case STMT_COLUMN_NCOL: { 160 sqlite3_result_int(ctx, sqlite3_column_count(pCur->pStmt)); 161 break; 162 } 163 case STMT_COLUMN_RO: { 164 sqlite3_result_int(ctx, sqlite3_stmt_readonly(pCur->pStmt)); 165 break; 166 } 167 case STMT_COLUMN_BUSY: { 168 sqlite3_result_int(ctx, sqlite3_stmt_busy(pCur->pStmt)); 169 break; 170 } 171 default: { 172 assert( i==STMT_COLUMN_MEM ); 173 i = SQLITE_STMTSTATUS_MEMUSED + 174 STMT_COLUMN_NSCAN - SQLITE_STMTSTATUS_FULLSCAN_STEP; 175 /* Fall thru */ 176 } 177 case STMT_COLUMN_NSCAN: 178 case STMT_COLUMN_NSORT: 179 case STMT_COLUMN_NAIDX: 180 case STMT_COLUMN_NSTEP: 181 case STMT_COLUMN_REPREP: 182 case STMT_COLUMN_RUN: { 183 sqlite3_result_int(ctx, sqlite3_stmt_status(pCur->pStmt, 184 i-STMT_COLUMN_NSCAN+SQLITE_STMTSTATUS_FULLSCAN_STEP, 0)); 185 break; 186 } 187 } 188 return SQLITE_OK; 189 } 190 191 /* 192 ** Return the rowid for the current row. In this implementation, the 193 ** rowid is the same as the output value. 194 */ 195 static int stmtRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){ 196 stmt_cursor *pCur = (stmt_cursor*)cur; 197 *pRowid = pCur->iRowid; 198 return SQLITE_OK; 199 } 200 201 /* 202 ** Return TRUE if the cursor has been moved off of the last 203 ** row of output. 204 */ 205 static int stmtEof(sqlite3_vtab_cursor *cur){ 206 stmt_cursor *pCur = (stmt_cursor*)cur; 207 return pCur->pStmt==0; 208 } 209 210 /* 211 ** This method is called to "rewind" the stmt_cursor object back 212 ** to the first row of output. This method is always called at least 213 ** once prior to any call to stmtColumn() or stmtRowid() or 214 ** stmtEof(). 215 */ 216 static int stmtFilter( 217 sqlite3_vtab_cursor *pVtabCursor, 218 int idxNum, const char *idxStr, 219 int argc, sqlite3_value **argv 220 ){ 221 stmt_cursor *pCur = (stmt_cursor *)pVtabCursor; 222 pCur->pStmt = 0; 223 pCur->iRowid = 0; 224 return stmtNext(pVtabCursor); 225 } 226 227 /* 228 ** SQLite will invoke this method one or more times while planning a query 229 ** that uses the stmt virtual table. This routine needs to create 230 ** a query plan for each invocation and compute an estimated cost for that 231 ** plan. 232 */ 233 static int stmtBestIndex( 234 sqlite3_vtab *tab, 235 sqlite3_index_info *pIdxInfo 236 ){ 237 pIdxInfo->estimatedCost = (double)500; 238 pIdxInfo->estimatedRows = 500; 239 return SQLITE_OK; 240 } 241 242 /* 243 ** This following structure defines all the methods for the 244 ** stmt virtual table. 245 */ 246 static sqlite3_module stmtModule = { 247 0, /* iVersion */ 248 0, /* xCreate */ 249 stmtConnect, /* xConnect */ 250 stmtBestIndex, /* xBestIndex */ 251 stmtDisconnect, /* xDisconnect */ 252 0, /* xDestroy */ 253 stmtOpen, /* xOpen - open a cursor */ 254 stmtClose, /* xClose - close a cursor */ 255 stmtFilter, /* xFilter - configure scan constraints */ 256 stmtNext, /* xNext - advance a cursor */ 257 stmtEof, /* xEof - check for end of scan */ 258 stmtColumn, /* xColumn - read data */ 259 stmtRowid, /* xRowid - read data */ 260 0, /* xUpdate */ 261 0, /* xBegin */ 262 0, /* xSync */ 263 0, /* xCommit */ 264 0, /* xRollback */ 265 0, /* xFindMethod */ 266 0, /* xRename */ 267 0, /* xSavepoint */ 268 0, /* xRelease */ 269 0, /* xRollbackTo */ 270 0, /* xShadowName */ 271 }; 272 273 #endif /* SQLITE_OMIT_VIRTUALTABLE */ 274 275 int sqlite3StmtVtabInit(sqlite3 *db){ 276 int rc = SQLITE_OK; 277 #ifndef SQLITE_OMIT_VIRTUALTABLE 278 rc = sqlite3_create_module(db, "sqlite_stmt", &stmtModule, 0); 279 #endif 280 return rc; 281 } 282 283 #ifndef SQLITE_CORE 284 #ifdef _WIN32 285 __declspec(dllexport) 286 #endif 287 int sqlite3_stmt_init( 288 sqlite3 *db, 289 char **pzErrMsg, 290 const sqlite3_api_routines *pApi 291 ){ 292 int rc = SQLITE_OK; 293 SQLITE_EXTENSION_INIT2(pApi); 294 #ifndef SQLITE_OMIT_VIRTUALTABLE 295 rc = sqlite3StmtVtabInit(db); 296 #endif 297 return rc; 298 } 299 #endif /* SQLITE_CORE */ 300 #endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_STMTVTAB) */ 301