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