1d7fda6cfSdrh /*
2d7fda6cfSdrh ** 2018-09-27
3d7fda6cfSdrh **
4d7fda6cfSdrh ** The author disclaims copyright to this source code. In place of
5d7fda6cfSdrh ** a legal notice, here is a blessing:
6d7fda6cfSdrh **
7d7fda6cfSdrh ** May you do good and not evil.
8d7fda6cfSdrh ** May you find forgiveness for yourself and forgive others.
9d7fda6cfSdrh ** May you share freely, never taking more than you give.
10d7fda6cfSdrh **
11d7fda6cfSdrh *************************************************************************
12d7fda6cfSdrh **
13d7fda6cfSdrh ** This file demonstrates an eponymous virtual table that returns information
14d7fda6cfSdrh ** from sqlite3_status64() and sqlite3_db_status().
15d7fda6cfSdrh **
16d7fda6cfSdrh ** Usage example:
17d7fda6cfSdrh **
18d7fda6cfSdrh ** .load ./memstat
19d7fda6cfSdrh ** .mode quote
20d7fda6cfSdrh ** .header on
21d7fda6cfSdrh ** SELECT * FROM memstat;
22d7fda6cfSdrh */
23d7134fe0Sdrh #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_MEMSTATVTAB)
24d7fda6cfSdrh #if !defined(SQLITEINT_H)
25d7fda6cfSdrh #include "sqlite3ext.h"
26d7fda6cfSdrh #endif
27d7fda6cfSdrh SQLITE_EXTENSION_INIT1
28d7fda6cfSdrh #include <assert.h>
29d7fda6cfSdrh #include <string.h>
30d7fda6cfSdrh
31d7fda6cfSdrh #ifndef SQLITE_OMIT_VIRTUALTABLE
32d7fda6cfSdrh
33d7fda6cfSdrh /* memstat_vtab is a subclass of sqlite3_vtab which will
34d7fda6cfSdrh ** serve as the underlying representation of a memstat virtual table
35d7fda6cfSdrh */
36d7fda6cfSdrh typedef struct memstat_vtab memstat_vtab;
37d7fda6cfSdrh struct memstat_vtab {
38d7fda6cfSdrh sqlite3_vtab base; /* Base class - must be first */
39d7fda6cfSdrh sqlite3 *db; /* Database connection for this memstat vtab */
40d7fda6cfSdrh };
41d7fda6cfSdrh
42d7fda6cfSdrh /* memstat_cursor is a subclass of sqlite3_vtab_cursor which will
43d7fda6cfSdrh ** serve as the underlying representation of a cursor that scans
44d7fda6cfSdrh ** over rows of the result
45d7fda6cfSdrh */
46d7fda6cfSdrh typedef struct memstat_cursor memstat_cursor;
47d7fda6cfSdrh struct memstat_cursor {
48d7fda6cfSdrh sqlite3_vtab_cursor base; /* Base class - must be first */
49d7fda6cfSdrh sqlite3 *db; /* Database connection for this cursor */
50d7134fe0Sdrh int iRowid; /* Current row in aMemstatColumn[] */
51d7134fe0Sdrh int iDb; /* Which schema we are looking at */
52d7134fe0Sdrh int nDb; /* Number of schemas */
53d7134fe0Sdrh char **azDb; /* Names of all schemas */
54d7134fe0Sdrh sqlite3_int64 aVal[2]; /* Result values */
55d7fda6cfSdrh };
56d7fda6cfSdrh
57d7fda6cfSdrh /*
58d7fda6cfSdrh ** The memstatConnect() method is invoked to create a new
59d7fda6cfSdrh ** memstat_vtab that describes the memstat virtual table.
60d7fda6cfSdrh **
61d7fda6cfSdrh ** Think of this routine as the constructor for memstat_vtab objects.
62d7fda6cfSdrh **
63d7fda6cfSdrh ** All this routine needs to do is:
64d7fda6cfSdrh **
65d7fda6cfSdrh ** (1) Allocate the memstat_vtab object and initialize all fields.
66d7fda6cfSdrh **
67d7fda6cfSdrh ** (2) Tell SQLite (via the sqlite3_declare_vtab() interface) what the
68d7fda6cfSdrh ** result set of queries against memstat will look like.
69d7fda6cfSdrh */
memstatConnect(sqlite3 * db,void * pAux,int argc,const char * const * argv,sqlite3_vtab ** ppVtab,char ** pzErr)70d7fda6cfSdrh static int memstatConnect(
71d7fda6cfSdrh sqlite3 *db,
72d7fda6cfSdrh void *pAux,
73d7fda6cfSdrh int argc, const char *const*argv,
74d7fda6cfSdrh sqlite3_vtab **ppVtab,
75d7fda6cfSdrh char **pzErr
76d7fda6cfSdrh ){
77d7fda6cfSdrh memstat_vtab *pNew;
78d7fda6cfSdrh int rc;
79d7fda6cfSdrh
80d7fda6cfSdrh /* Column numbers */
81d7fda6cfSdrh #define MSV_COLUMN_NAME 0 /* Name of quantity being measured */
82d7134fe0Sdrh #define MSV_COLUMN_SCHEMA 1 /* schema name */
83d7134fe0Sdrh #define MSV_COLUMN_VALUE 2 /* Current value */
84d7134fe0Sdrh #define MSV_COLUMN_HIWTR 3 /* Highwater mark */
85d7fda6cfSdrh
86d7134fe0Sdrh rc = sqlite3_declare_vtab(db,"CREATE TABLE x(name,schema,value,hiwtr)");
87d7fda6cfSdrh if( rc==SQLITE_OK ){
88d7fda6cfSdrh pNew = sqlite3_malloc( sizeof(*pNew) );
89d7fda6cfSdrh *ppVtab = (sqlite3_vtab*)pNew;
90d7fda6cfSdrh if( pNew==0 ) return SQLITE_NOMEM;
91d7fda6cfSdrh memset(pNew, 0, sizeof(*pNew));
92d7fda6cfSdrh pNew->db = db;
93d7fda6cfSdrh }
94d7fda6cfSdrh return rc;
95d7fda6cfSdrh }
96d7fda6cfSdrh
97d7fda6cfSdrh /*
98d7fda6cfSdrh ** This method is the destructor for memstat_cursor objects.
99d7fda6cfSdrh */
memstatDisconnect(sqlite3_vtab * pVtab)100d7fda6cfSdrh static int memstatDisconnect(sqlite3_vtab *pVtab){
101d7fda6cfSdrh sqlite3_free(pVtab);
102d7fda6cfSdrh return SQLITE_OK;
103d7fda6cfSdrh }
104d7fda6cfSdrh
105d7fda6cfSdrh /*
106d7fda6cfSdrh ** Constructor for a new memstat_cursor object.
107d7fda6cfSdrh */
memstatOpen(sqlite3_vtab * p,sqlite3_vtab_cursor ** ppCursor)108d7fda6cfSdrh static int memstatOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
109d7fda6cfSdrh memstat_cursor *pCur;
110d7fda6cfSdrh pCur = sqlite3_malloc( sizeof(*pCur) );
111d7fda6cfSdrh if( pCur==0 ) return SQLITE_NOMEM;
112d7fda6cfSdrh memset(pCur, 0, sizeof(*pCur));
113d7fda6cfSdrh pCur->db = ((memstat_vtab*)p)->db;
114d7fda6cfSdrh *ppCursor = &pCur->base;
115d7fda6cfSdrh return SQLITE_OK;
116d7fda6cfSdrh }
117d7fda6cfSdrh
118d7fda6cfSdrh /*
119d7134fe0Sdrh ** Clear all the schema names from a cursor
120d7134fe0Sdrh */
memstatClearSchema(memstat_cursor * pCur)121d7134fe0Sdrh static void memstatClearSchema(memstat_cursor *pCur){
122d7134fe0Sdrh int i;
123d7134fe0Sdrh if( pCur->azDb==0 ) return;
124d7134fe0Sdrh for(i=0; i<pCur->nDb; i++){
125d7134fe0Sdrh sqlite3_free(pCur->azDb[i]);
126d7134fe0Sdrh }
127d7134fe0Sdrh sqlite3_free(pCur->azDb);
128d7134fe0Sdrh pCur->azDb = 0;
129d7134fe0Sdrh pCur->nDb = 0;
130d7134fe0Sdrh }
131d7134fe0Sdrh
132d7134fe0Sdrh /*
133d7134fe0Sdrh ** Fill in the azDb[] array for the cursor.
134d7134fe0Sdrh */
memstatFindSchemas(memstat_cursor * pCur)135d7134fe0Sdrh static int memstatFindSchemas(memstat_cursor *pCur){
136d7134fe0Sdrh sqlite3_stmt *pStmt = 0;
137d7134fe0Sdrh int rc;
138d7134fe0Sdrh if( pCur->nDb ) return SQLITE_OK;
139d7134fe0Sdrh rc = sqlite3_prepare_v2(pCur->db, "PRAGMA database_list", -1, &pStmt, 0);
140d7134fe0Sdrh if( rc ){
141d7134fe0Sdrh sqlite3_finalize(pStmt);
142d7134fe0Sdrh return rc;
143d7134fe0Sdrh }
144d7134fe0Sdrh while( sqlite3_step(pStmt)==SQLITE_ROW ){
145d7134fe0Sdrh char **az, *z;
146*2d77d80aSdrh az = sqlite3_realloc64(pCur->azDb, sizeof(char*)*(pCur->nDb+1));
147d7134fe0Sdrh if( az==0 ){
148d7134fe0Sdrh memstatClearSchema(pCur);
149d7134fe0Sdrh return SQLITE_NOMEM;
150d7134fe0Sdrh }
151d7134fe0Sdrh pCur->azDb = az;
152d7134fe0Sdrh z = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 1));
153d7134fe0Sdrh if( z==0 ){
154d7134fe0Sdrh memstatClearSchema(pCur);
155d7134fe0Sdrh return SQLITE_NOMEM;
156d7134fe0Sdrh }
157d7134fe0Sdrh pCur->azDb[pCur->nDb] = z;
158d7134fe0Sdrh pCur->nDb++;
159d7134fe0Sdrh }
160d7134fe0Sdrh sqlite3_finalize(pStmt);
161d7134fe0Sdrh return SQLITE_OK;
162d7134fe0Sdrh }
163d7134fe0Sdrh
164d7134fe0Sdrh
165d7134fe0Sdrh /*
166d7fda6cfSdrh ** Destructor for a memstat_cursor.
167d7fda6cfSdrh */
memstatClose(sqlite3_vtab_cursor * cur)168d7fda6cfSdrh static int memstatClose(sqlite3_vtab_cursor *cur){
169d7134fe0Sdrh memstat_cursor *pCur = (memstat_cursor*)cur;
170d7134fe0Sdrh memstatClearSchema(pCur);
171d7fda6cfSdrh sqlite3_free(cur);
172d7fda6cfSdrh return SQLITE_OK;
173d7fda6cfSdrh }
174d7fda6cfSdrh
175d7fda6cfSdrh
176d7fda6cfSdrh /*
177d7fda6cfSdrh ** Allowed values for aMemstatColumn[].eType
178d7fda6cfSdrh */
179d7fda6cfSdrh #define MSV_GSTAT 0 /* sqlite3_status64() information */
180d7134fe0Sdrh #define MSV_DB 1 /* sqlite3_db_status() information */
1817c5577acSdrh #define MSV_ZIPVFS 2 /* ZIPVFS file-control with 64-bit return */
182d7fda6cfSdrh
183d7fda6cfSdrh /*
184d7fda6cfSdrh ** An array of quantities that can be measured and reported by
185d7fda6cfSdrh ** this virtual table
186d7fda6cfSdrh */
187d7fda6cfSdrh static const struct MemstatColumns {
188d7fda6cfSdrh const char *zName; /* Symbolic name */
189d7134fe0Sdrh unsigned char eType; /* Type of interface */
190d7134fe0Sdrh unsigned char mNull; /* Bitmask of which columns are NULL */
191d7134fe0Sdrh /* 2: dbname, 4: current, 8: hiwtr */
192d7fda6cfSdrh int eOp; /* Opcode */
193d7fda6cfSdrh } aMemstatColumn[] = {
194d7134fe0Sdrh {"MEMORY_USED", MSV_GSTAT, 2, SQLITE_STATUS_MEMORY_USED },
195d7134fe0Sdrh {"MALLOC_SIZE", MSV_GSTAT, 6, SQLITE_STATUS_MALLOC_SIZE },
196d7134fe0Sdrh {"MALLOC_COUNT", MSV_GSTAT, 2, SQLITE_STATUS_MALLOC_COUNT },
197d7134fe0Sdrh {"PAGECACHE_USED", MSV_GSTAT, 2, SQLITE_STATUS_PAGECACHE_USED },
198d7134fe0Sdrh {"PAGECACHE_OVERFLOW", MSV_GSTAT, 2, SQLITE_STATUS_PAGECACHE_OVERFLOW },
199d7134fe0Sdrh {"PAGECACHE_SIZE", MSV_GSTAT, 6, SQLITE_STATUS_PAGECACHE_SIZE },
200d7134fe0Sdrh {"PARSER_STACK", MSV_GSTAT, 6, SQLITE_STATUS_PARSER_STACK },
201d7134fe0Sdrh {"DB_LOOKASIDE_USED", MSV_DB, 2, SQLITE_DBSTATUS_LOOKASIDE_USED },
202d7134fe0Sdrh {"DB_LOOKASIDE_HIT", MSV_DB, 6, SQLITE_DBSTATUS_LOOKASIDE_HIT },
203d7134fe0Sdrh {"DB_LOOKASIDE_MISS_SIZE", MSV_DB, 6, SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE},
204d7134fe0Sdrh {"DB_LOOKASIDE_MISS_FULL", MSV_DB, 6, SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL},
205d7134fe0Sdrh {"DB_CACHE_USED", MSV_DB, 10, SQLITE_DBSTATUS_CACHE_USED },
2060efb6f51Sdan #if SQLITE_VERSION_NUMBER >= 3140000
207d7134fe0Sdrh {"DB_CACHE_USED_SHARED", MSV_DB, 10, SQLITE_DBSTATUS_CACHE_USED_SHARED },
2080efb6f51Sdan #endif
209d7134fe0Sdrh {"DB_SCHEMA_USED", MSV_DB, 10, SQLITE_DBSTATUS_SCHEMA_USED },
210d7134fe0Sdrh {"DB_STMT_USED", MSV_DB, 10, SQLITE_DBSTATUS_STMT_USED },
211d7134fe0Sdrh {"DB_CACHE_HIT", MSV_DB, 10, SQLITE_DBSTATUS_CACHE_HIT },
212d7134fe0Sdrh {"DB_CACHE_MISS", MSV_DB, 10, SQLITE_DBSTATUS_CACHE_MISS },
213d7134fe0Sdrh {"DB_CACHE_WRITE", MSV_DB, 10, SQLITE_DBSTATUS_CACHE_WRITE },
2140efb6f51Sdan #if SQLITE_VERSION_NUMBER >= 3230000
215d7134fe0Sdrh {"DB_CACHE_SPILL", MSV_DB, 10, SQLITE_DBSTATUS_CACHE_SPILL },
2160efb6f51Sdan #endif
217d7134fe0Sdrh {"DB_DEFERRED_FKS", MSV_DB, 10, SQLITE_DBSTATUS_DEFERRED_FKS },
2187c5577acSdrh #ifdef SQLITE_ENABLE_ZIPVFS
219d7134fe0Sdrh {"ZIPVFS_CACHE_USED", MSV_ZIPVFS, 8, 231454 },
220d7134fe0Sdrh {"ZIPVFS_CACHE_HIT", MSV_ZIPVFS, 8, 231455 },
221d7134fe0Sdrh {"ZIPVFS_CACHE_MISS", MSV_ZIPVFS, 8, 231456 },
222d7134fe0Sdrh {"ZIPVFS_CACHE_WRITE", MSV_ZIPVFS, 8, 231457 },
223d7134fe0Sdrh {"ZIPVFS_DIRECT_READ", MSV_ZIPVFS, 8, 231458 },
224d7134fe0Sdrh {"ZIPVFS_DIRECT_BYTES", MSV_ZIPVFS, 8, 231459 },
2257c5577acSdrh #endif /* SQLITE_ENABLE_ZIPVFS */
226d7fda6cfSdrh };
227d7fda6cfSdrh #define MSV_NROW (sizeof(aMemstatColumn)/sizeof(aMemstatColumn[0]))
228d7fda6cfSdrh
229d7fda6cfSdrh /*
230d7fda6cfSdrh ** Advance a memstat_cursor to its next row of output.
231d7fda6cfSdrh */
memstatNext(sqlite3_vtab_cursor * cur)232d7fda6cfSdrh static int memstatNext(sqlite3_vtab_cursor *cur){
233d7fda6cfSdrh memstat_cursor *pCur = (memstat_cursor*)cur;
234d7134fe0Sdrh int i;
235d7134fe0Sdrh assert( pCur->iRowid<=MSV_NROW );
236d7134fe0Sdrh while(1){
237d7134fe0Sdrh i = (int)pCur->iRowid - 1;
2387dd630a8Sdrh if( i<0 || (aMemstatColumn[i].mNull & 2)!=0 || (++pCur->iDb)>=pCur->nDb ){
239d7fda6cfSdrh pCur->iRowid++;
240d7134fe0Sdrh if( pCur->iRowid>MSV_NROW ) return SQLITE_OK; /* End of the table */
241d7134fe0Sdrh pCur->iDb = 0;
242d7134fe0Sdrh i++;
243d7134fe0Sdrh }
244d7134fe0Sdrh pCur->aVal[0] = 0;
245d7134fe0Sdrh pCur->aVal[1] = 0;
246d7134fe0Sdrh switch( aMemstatColumn[i].eType ){
247d7134fe0Sdrh case MSV_GSTAT: {
2486dd5f07dSdrh if( sqlite3_libversion_number()>=3010000 ){
249d7134fe0Sdrh sqlite3_status64(aMemstatColumn[i].eOp,
250d7134fe0Sdrh &pCur->aVal[0], &pCur->aVal[1],0);
2516dd5f07dSdrh }else{
2526dd5f07dSdrh int xCur, xHiwtr;
2536dd5f07dSdrh sqlite3_status(aMemstatColumn[i].eOp, &xCur, &xHiwtr, 0);
2546dd5f07dSdrh pCur->aVal[0] = xCur;
2556dd5f07dSdrh pCur->aVal[1] = xHiwtr;
2566dd5f07dSdrh }
257d7134fe0Sdrh break;
258d7134fe0Sdrh }
259d7134fe0Sdrh case MSV_DB: {
260d7134fe0Sdrh int xCur, xHiwtr;
261d7134fe0Sdrh sqlite3_db_status(pCur->db, aMemstatColumn[i].eOp, &xCur, &xHiwtr, 0);
262d7134fe0Sdrh pCur->aVal[0] = xCur;
263d7134fe0Sdrh pCur->aVal[1] = xHiwtr;
264d7134fe0Sdrh break;
265d7134fe0Sdrh }
266d7134fe0Sdrh case MSV_ZIPVFS: {
267d7134fe0Sdrh int rc;
268d7134fe0Sdrh rc = sqlite3_file_control(pCur->db, pCur->azDb[pCur->iDb],
269d7134fe0Sdrh aMemstatColumn[i].eOp, (void*)&pCur->aVal[0]);
270d7134fe0Sdrh if( rc!=SQLITE_OK ) continue;
271d7134fe0Sdrh break;
272d7134fe0Sdrh }
273d7134fe0Sdrh }
274d7134fe0Sdrh break;
275d7134fe0Sdrh }
276d7fda6cfSdrh return SQLITE_OK;
277d7fda6cfSdrh }
278d7fda6cfSdrh
279d7fda6cfSdrh
280d7fda6cfSdrh /*
281d7fda6cfSdrh ** Return values of columns for the row at which the memstat_cursor
282d7fda6cfSdrh ** is currently pointing.
283d7fda6cfSdrh */
memstatColumn(sqlite3_vtab_cursor * cur,sqlite3_context * ctx,int iCol)284d7fda6cfSdrh static int memstatColumn(
285d7fda6cfSdrh sqlite3_vtab_cursor *cur, /* The cursor */
286d7fda6cfSdrh sqlite3_context *ctx, /* First argument to sqlite3_result_...() */
287d7fda6cfSdrh int iCol /* Which column to return */
288d7fda6cfSdrh ){
289d7fda6cfSdrh memstat_cursor *pCur = (memstat_cursor*)cur;
290d7fda6cfSdrh int i;
291d7fda6cfSdrh assert( pCur->iRowid>0 && pCur->iRowid<=MSV_NROW );
292d7fda6cfSdrh i = (int)pCur->iRowid - 1;
293d7134fe0Sdrh if( (aMemstatColumn[i].mNull & (1<<iCol))!=0 ){
294d7fda6cfSdrh return SQLITE_OK;
295d7fda6cfSdrh }
296d7134fe0Sdrh switch( iCol ){
297d7134fe0Sdrh case MSV_COLUMN_NAME: {
298d7134fe0Sdrh sqlite3_result_text(ctx, aMemstatColumn[i].zName, -1, SQLITE_STATIC);
299d7fda6cfSdrh break;
300d7fda6cfSdrh }
301d7134fe0Sdrh case MSV_COLUMN_SCHEMA: {
302d7134fe0Sdrh sqlite3_result_text(ctx, pCur->azDb[pCur->iDb], -1, 0);
303d7fda6cfSdrh break;
304d7fda6cfSdrh }
305d7134fe0Sdrh case MSV_COLUMN_VALUE: {
306d7134fe0Sdrh sqlite3_result_int64(ctx, pCur->aVal[0]);
307d7134fe0Sdrh break;
308d7134fe0Sdrh }
309d7134fe0Sdrh case MSV_COLUMN_HIWTR: {
310d7134fe0Sdrh sqlite3_result_int64(ctx, pCur->aVal[1]);
3117c5577acSdrh break;
3127c5577acSdrh }
313d7fda6cfSdrh }
314d7fda6cfSdrh return SQLITE_OK;
315d7fda6cfSdrh }
316d7fda6cfSdrh
317d7fda6cfSdrh /*
318d7fda6cfSdrh ** Return the rowid for the current row. In this implementation, the
319d7fda6cfSdrh ** rowid is the same as the output value.
320d7fda6cfSdrh */
memstatRowid(sqlite3_vtab_cursor * cur,sqlite_int64 * pRowid)321d7fda6cfSdrh static int memstatRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
322d7fda6cfSdrh memstat_cursor *pCur = (memstat_cursor*)cur;
323d7134fe0Sdrh *pRowid = pCur->iRowid*1000 + pCur->iDb;
324d7fda6cfSdrh return SQLITE_OK;
325d7fda6cfSdrh }
326d7fda6cfSdrh
327d7fda6cfSdrh /*
328d7fda6cfSdrh ** Return TRUE if the cursor has been moved off of the last
329d7fda6cfSdrh ** row of output.
330d7fda6cfSdrh */
memstatEof(sqlite3_vtab_cursor * cur)331d7fda6cfSdrh static int memstatEof(sqlite3_vtab_cursor *cur){
332d7fda6cfSdrh memstat_cursor *pCur = (memstat_cursor*)cur;
3337c5577acSdrh return pCur->iRowid>MSV_NROW;
334d7fda6cfSdrh }
335d7fda6cfSdrh
336d7fda6cfSdrh /*
337d7fda6cfSdrh ** This method is called to "rewind" the memstat_cursor object back
338d7fda6cfSdrh ** to the first row of output. This method is always called at least
339d7fda6cfSdrh ** once prior to any call to memstatColumn() or memstatRowid() or
340d7fda6cfSdrh ** memstatEof().
341d7fda6cfSdrh */
memstatFilter(sqlite3_vtab_cursor * pVtabCursor,int idxNum,const char * idxStr,int argc,sqlite3_value ** argv)342d7fda6cfSdrh static int memstatFilter(
343d7fda6cfSdrh sqlite3_vtab_cursor *pVtabCursor,
344d7fda6cfSdrh int idxNum, const char *idxStr,
345d7fda6cfSdrh int argc, sqlite3_value **argv
346d7fda6cfSdrh ){
347d7fda6cfSdrh memstat_cursor *pCur = (memstat_cursor *)pVtabCursor;
34809b523c9Sdrh int rc = memstatFindSchemas(pCur);
34909b523c9Sdrh if( rc ) return rc;
35009b523c9Sdrh pCur->iRowid = 0;
351d7134fe0Sdrh pCur->iDb = 0;
35209b523c9Sdrh return memstatNext(pVtabCursor);
353d7fda6cfSdrh }
354d7fda6cfSdrh
355d7fda6cfSdrh /*
356d7fda6cfSdrh ** SQLite will invoke this method one or more times while planning a query
357d7fda6cfSdrh ** that uses the memstat virtual table. This routine needs to create
358d7fda6cfSdrh ** a query plan for each invocation and compute an estimated cost for that
359d7fda6cfSdrh ** plan.
360d7fda6cfSdrh */
memstatBestIndex(sqlite3_vtab * tab,sqlite3_index_info * pIdxInfo)361d7fda6cfSdrh static int memstatBestIndex(
362d7fda6cfSdrh sqlite3_vtab *tab,
363d7fda6cfSdrh sqlite3_index_info *pIdxInfo
364d7fda6cfSdrh ){
365d7fda6cfSdrh pIdxInfo->estimatedCost = (double)500;
366d7fda6cfSdrh pIdxInfo->estimatedRows = 500;
367d7fda6cfSdrh return SQLITE_OK;
368d7fda6cfSdrh }
369d7fda6cfSdrh
370d7fda6cfSdrh /*
371d7fda6cfSdrh ** This following structure defines all the methods for the
372d7fda6cfSdrh ** memstat virtual table.
373d7fda6cfSdrh */
374d7fda6cfSdrh static sqlite3_module memstatModule = {
375d7fda6cfSdrh 0, /* iVersion */
376d7fda6cfSdrh 0, /* xCreate */
377d7fda6cfSdrh memstatConnect, /* xConnect */
378d7fda6cfSdrh memstatBestIndex, /* xBestIndex */
379d7fda6cfSdrh memstatDisconnect, /* xDisconnect */
380d7fda6cfSdrh 0, /* xDestroy */
381d7fda6cfSdrh memstatOpen, /* xOpen - open a cursor */
382d7fda6cfSdrh memstatClose, /* xClose - close a cursor */
383d7fda6cfSdrh memstatFilter, /* xFilter - configure scan constraints */
384d7fda6cfSdrh memstatNext, /* xNext - advance a cursor */
385d7fda6cfSdrh memstatEof, /* xEof - check for end of scan */
386d7fda6cfSdrh memstatColumn, /* xColumn - read data */
387d7fda6cfSdrh memstatRowid, /* xRowid - read data */
388d7fda6cfSdrh 0, /* xUpdate */
389d7fda6cfSdrh 0, /* xBegin */
390d7fda6cfSdrh 0, /* xSync */
391d7fda6cfSdrh 0, /* xCommit */
392d7fda6cfSdrh 0, /* xRollback */
393d7fda6cfSdrh 0, /* xFindMethod */
394d7fda6cfSdrh 0, /* xRename */
395d7fda6cfSdrh 0, /* xSavepoint */
396d7fda6cfSdrh 0, /* xRelease */
397d7fda6cfSdrh 0, /* xRollbackTo */
39884c501baSdrh 0, /* xShadowName */
399d7fda6cfSdrh };
400d7fda6cfSdrh
401d7fda6cfSdrh #endif /* SQLITE_OMIT_VIRTUALTABLE */
402d7fda6cfSdrh
sqlite3MemstatVtabInit(sqlite3 * db)403d7fda6cfSdrh int sqlite3MemstatVtabInit(sqlite3 *db){
404d7fda6cfSdrh int rc = SQLITE_OK;
405d7fda6cfSdrh #ifndef SQLITE_OMIT_VIRTUALTABLE
406d7fda6cfSdrh rc = sqlite3_create_module(db, "sqlite_memstat", &memstatModule, 0);
407d7fda6cfSdrh #endif
408d7fda6cfSdrh return rc;
409d7fda6cfSdrh }
410d7fda6cfSdrh
411d7fda6cfSdrh #ifndef SQLITE_CORE
412d7fda6cfSdrh #ifdef _WIN32
413d7fda6cfSdrh __declspec(dllexport)
414d7fda6cfSdrh #endif
sqlite3_memstat_init(sqlite3 * db,char ** pzErrMsg,const sqlite3_api_routines * pApi)415d7fda6cfSdrh int sqlite3_memstat_init(
416d7fda6cfSdrh sqlite3 *db,
417d7fda6cfSdrh char **pzErrMsg,
418d7fda6cfSdrh const sqlite3_api_routines *pApi
419d7fda6cfSdrh ){
420d7fda6cfSdrh int rc = SQLITE_OK;
421d7fda6cfSdrh SQLITE_EXTENSION_INIT2(pApi);
422d7fda6cfSdrh #ifndef SQLITE_OMIT_VIRTUALTABLE
423d7fda6cfSdrh rc = sqlite3MemstatVtabInit(db);
424d7fda6cfSdrh #endif
425d7fda6cfSdrh return rc;
426d7fda6cfSdrh }
427d7fda6cfSdrh #endif /* SQLITE_CORE */
428d7134fe0Sdrh #endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_MEMSTATVTAB) */
429