xref: /sqlite-3.40.0/ext/misc/memstat.c (revision 2d77d80a)
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