155a3490cSdrh /*
255a3490cSdrh ** 2018-04-19
355a3490cSdrh **
455a3490cSdrh ** The author disclaims copyright to this source code. In place of
555a3490cSdrh ** a legal notice, here is a blessing:
655a3490cSdrh **
755a3490cSdrh ** May you do good and not evil.
855a3490cSdrh ** May you find forgiveness for yourself and forgive others.
955a3490cSdrh ** May you share freely, never taking more than you give.
1055a3490cSdrh **
1155a3490cSdrh *************************************************************************
1255a3490cSdrh **
13ef9e3d78Sdrh ** This file implements a template virtual-table.
1455a3490cSdrh ** Developers can make a copy of this file as a baseline for writing
1555a3490cSdrh ** new virtual tables and/or table-valued functions.
1655a3490cSdrh **
1755a3490cSdrh ** Steps for writing a new virtual table implementation:
1855a3490cSdrh **
19ef9e3d78Sdrh ** (1) Make a copy of this file. Perhaps call it "mynewvtab.c"
2055a3490cSdrh **
2155a3490cSdrh ** (2) Replace this header comment with something appropriate for
2255a3490cSdrh ** the new virtual table
2355a3490cSdrh **
2455a3490cSdrh ** (3) Change every occurrence of "templatevtab" to some other string
2555a3490cSdrh ** appropriate for the new virtual table. Ideally, the new string
26ef9e3d78Sdrh ** should be the basename of the source file: "mynewvtab". Also
27ef9e3d78Sdrh ** globally change "TEMPLATEVTAB" to "MYNEWVTAB".
2855a3490cSdrh **
2955a3490cSdrh ** (4) Run a test compilation to make sure the unmodified virtual
3055a3490cSdrh ** table works.
3155a3490cSdrh **
32ef9e3d78Sdrh ** (5) Begin making incremental changes, testing as you go, to evolve
33ef9e3d78Sdrh ** the new virtual table to do what you want it to do.
3455a3490cSdrh **
3555a3490cSdrh ** This template is minimal, in the sense that it uses only the required
3655a3490cSdrh ** methods on the sqlite3_module object. As a result, templatevtab is
3755a3490cSdrh ** a read-only and eponymous-only table. Those limitation can be removed
3855a3490cSdrh ** by adding new methods.
39ef9e3d78Sdrh **
40ef9e3d78Sdrh ** This template implements an eponymous-only virtual table with a rowid and
41ef9e3d78Sdrh ** two columns named "a" and "b". The table as 10 rows with fixed integer
42ef9e3d78Sdrh ** values. Usage example:
43ef9e3d78Sdrh **
44ef9e3d78Sdrh ** SELECT rowid, a, b FROM templatevtab;
4555a3490cSdrh */
4655a3490cSdrh #if !defined(SQLITEINT_H)
4755a3490cSdrh #include "sqlite3ext.h"
4855a3490cSdrh #endif
4955a3490cSdrh SQLITE_EXTENSION_INIT1
5055a3490cSdrh #include <string.h>
51ef9e3d78Sdrh #include <assert.h>
5255a3490cSdrh
5355a3490cSdrh /* templatevtab_vtab is a subclass of sqlite3_vtab which is
5455a3490cSdrh ** underlying representation of the virtual table
5555a3490cSdrh */
5655a3490cSdrh typedef struct templatevtab_vtab templatevtab_vtab;
5755a3490cSdrh struct templatevtab_vtab {
5855a3490cSdrh sqlite3_vtab base; /* Base class - must be first */
5955a3490cSdrh /* Add new fields here, as necessary */
6055a3490cSdrh };
6155a3490cSdrh
6255a3490cSdrh /* templatevtab_cursor is a subclass of sqlite3_vtab_cursor which will
6355a3490cSdrh ** serve as the underlying representation of a cursor that scans
6455a3490cSdrh ** over rows of the result
6555a3490cSdrh */
6655a3490cSdrh typedef struct templatevtab_cursor templatevtab_cursor;
6755a3490cSdrh struct templatevtab_cursor {
6855a3490cSdrh sqlite3_vtab_cursor base; /* Base class - must be first */
6955a3490cSdrh /* Insert new fields here. For this templatevtab we only keep track
7055a3490cSdrh ** of the rowid */
7155a3490cSdrh sqlite3_int64 iRowid; /* The rowid */
7255a3490cSdrh };
7355a3490cSdrh
7455a3490cSdrh /*
7555a3490cSdrh ** The templatevtabConnect() method is invoked to create a new
7655a3490cSdrh ** template virtual table.
7755a3490cSdrh **
7855a3490cSdrh ** Think of this routine as the constructor for templatevtab_vtab objects.
7955a3490cSdrh **
8055a3490cSdrh ** All this routine needs to do is:
8155a3490cSdrh **
8255a3490cSdrh ** (1) Allocate the templatevtab_vtab object and initialize all fields.
8355a3490cSdrh **
8455a3490cSdrh ** (2) Tell SQLite (via the sqlite3_declare_vtab() interface) what the
8555a3490cSdrh ** result set of queries against the virtual table will look like.
8655a3490cSdrh */
templatevtabConnect(sqlite3 * db,void * pAux,int argc,const char * const * argv,sqlite3_vtab ** ppVtab,char ** pzErr)8755a3490cSdrh static int templatevtabConnect(
8855a3490cSdrh sqlite3 *db,
8955a3490cSdrh void *pAux,
9055a3490cSdrh int argc, const char *const*argv,
9155a3490cSdrh sqlite3_vtab **ppVtab,
9255a3490cSdrh char **pzErr
9355a3490cSdrh ){
9455a3490cSdrh templatevtab_vtab *pNew;
9555a3490cSdrh int rc;
9655a3490cSdrh
9755a3490cSdrh rc = sqlite3_declare_vtab(db,
9855a3490cSdrh "CREATE TABLE x(a,b)"
9955a3490cSdrh );
100ef9e3d78Sdrh /* For convenience, define symbolic names for the index to each column. */
101ef9e3d78Sdrh #define TEMPLATEVTAB_A 0
102ef9e3d78Sdrh #define TEMPLATEVTAB_B 1
10355a3490cSdrh if( rc==SQLITE_OK ){
10455a3490cSdrh pNew = sqlite3_malloc( sizeof(*pNew) );
10555a3490cSdrh *ppVtab = (sqlite3_vtab*)pNew;
10655a3490cSdrh if( pNew==0 ) return SQLITE_NOMEM;
10755a3490cSdrh memset(pNew, 0, sizeof(*pNew));
10855a3490cSdrh }
10955a3490cSdrh return rc;
11055a3490cSdrh }
11155a3490cSdrh
11255a3490cSdrh /*
11355a3490cSdrh ** This method is the destructor for templatevtab_vtab objects.
11455a3490cSdrh */
templatevtabDisconnect(sqlite3_vtab * pVtab)11555a3490cSdrh static int templatevtabDisconnect(sqlite3_vtab *pVtab){
11655a3490cSdrh templatevtab_vtab *p = (templatevtab_vtab*)pVtab;
11755a3490cSdrh sqlite3_free(p);
11855a3490cSdrh return SQLITE_OK;
11955a3490cSdrh }
12055a3490cSdrh
12155a3490cSdrh /*
12255a3490cSdrh ** Constructor for a new templatevtab_cursor object.
12355a3490cSdrh */
templatevtabOpen(sqlite3_vtab * p,sqlite3_vtab_cursor ** ppCursor)12455a3490cSdrh static int templatevtabOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
12555a3490cSdrh templatevtab_cursor *pCur;
12655a3490cSdrh pCur = sqlite3_malloc( sizeof(*pCur) );
12755a3490cSdrh if( pCur==0 ) return SQLITE_NOMEM;
12855a3490cSdrh memset(pCur, 0, sizeof(*pCur));
12955a3490cSdrh *ppCursor = &pCur->base;
13055a3490cSdrh return SQLITE_OK;
13155a3490cSdrh }
13255a3490cSdrh
13355a3490cSdrh /*
13455a3490cSdrh ** Destructor for a templatevtab_cursor.
13555a3490cSdrh */
templatevtabClose(sqlite3_vtab_cursor * cur)13655a3490cSdrh static int templatevtabClose(sqlite3_vtab_cursor *cur){
13755a3490cSdrh templatevtab_cursor *pCur = (templatevtab_cursor*)cur;
13855a3490cSdrh sqlite3_free(pCur);
13955a3490cSdrh return SQLITE_OK;
14055a3490cSdrh }
14155a3490cSdrh
14255a3490cSdrh
14355a3490cSdrh /*
14455a3490cSdrh ** Advance a templatevtab_cursor to its next row of output.
14555a3490cSdrh */
templatevtabNext(sqlite3_vtab_cursor * cur)14655a3490cSdrh static int templatevtabNext(sqlite3_vtab_cursor *cur){
14755a3490cSdrh templatevtab_cursor *pCur = (templatevtab_cursor*)cur;
14855a3490cSdrh pCur->iRowid++;
14955a3490cSdrh return SQLITE_OK;
15055a3490cSdrh }
15155a3490cSdrh
15255a3490cSdrh /*
15355a3490cSdrh ** Return values of columns for the row at which the templatevtab_cursor
15455a3490cSdrh ** is currently pointing.
15555a3490cSdrh */
templatevtabColumn(sqlite3_vtab_cursor * cur,sqlite3_context * ctx,int i)15655a3490cSdrh static int templatevtabColumn(
15755a3490cSdrh sqlite3_vtab_cursor *cur, /* The cursor */
15855a3490cSdrh sqlite3_context *ctx, /* First argument to sqlite3_result_...() */
15955a3490cSdrh int i /* Which column to return */
16055a3490cSdrh ){
16155a3490cSdrh templatevtab_cursor *pCur = (templatevtab_cursor*)cur;
162ef9e3d78Sdrh switch( i ){
163ef9e3d78Sdrh case TEMPLATEVTAB_A:
164ef9e3d78Sdrh sqlite3_result_int(ctx, 1000 + pCur->iRowid);
165ef9e3d78Sdrh break;
166ef9e3d78Sdrh default:
167ef9e3d78Sdrh assert( i==TEMPLATEVTAB_B );
168ef9e3d78Sdrh sqlite3_result_int(ctx, 2000 + pCur->iRowid);
169ef9e3d78Sdrh break;
170ef9e3d78Sdrh }
17155a3490cSdrh return SQLITE_OK;
17255a3490cSdrh }
17355a3490cSdrh
17455a3490cSdrh /*
17555a3490cSdrh ** Return the rowid for the current row. In this implementation, the
17655a3490cSdrh ** rowid is the same as the output value.
17755a3490cSdrh */
templatevtabRowid(sqlite3_vtab_cursor * cur,sqlite_int64 * pRowid)17855a3490cSdrh static int templatevtabRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
17955a3490cSdrh templatevtab_cursor *pCur = (templatevtab_cursor*)cur;
18055a3490cSdrh *pRowid = pCur->iRowid;
18155a3490cSdrh return SQLITE_OK;
18255a3490cSdrh }
18355a3490cSdrh
18455a3490cSdrh /*
18555a3490cSdrh ** Return TRUE if the cursor has been moved off of the last
18655a3490cSdrh ** row of output.
18755a3490cSdrh */
templatevtabEof(sqlite3_vtab_cursor * cur)18855a3490cSdrh static int templatevtabEof(sqlite3_vtab_cursor *cur){
18955a3490cSdrh templatevtab_cursor *pCur = (templatevtab_cursor*)cur;
19055a3490cSdrh return pCur->iRowid>=10;
19155a3490cSdrh }
19255a3490cSdrh
19355a3490cSdrh /*
19455a3490cSdrh ** This method is called to "rewind" the templatevtab_cursor object back
19555a3490cSdrh ** to the first row of output. This method is always called at least
19655a3490cSdrh ** once prior to any call to templatevtabColumn() or templatevtabRowid() or
19755a3490cSdrh ** templatevtabEof().
19855a3490cSdrh */
templatevtabFilter(sqlite3_vtab_cursor * pVtabCursor,int idxNum,const char * idxStr,int argc,sqlite3_value ** argv)19955a3490cSdrh static int templatevtabFilter(
20055a3490cSdrh sqlite3_vtab_cursor *pVtabCursor,
20155a3490cSdrh int idxNum, const char *idxStr,
20255a3490cSdrh int argc, sqlite3_value **argv
20355a3490cSdrh ){
20455a3490cSdrh templatevtab_cursor *pCur = (templatevtab_cursor *)pVtabCursor;
20555a3490cSdrh pCur->iRowid = 1;
20655a3490cSdrh return SQLITE_OK;
20755a3490cSdrh }
20855a3490cSdrh
20955a3490cSdrh /*
21055a3490cSdrh ** SQLite will invoke this method one or more times while planning a query
21155a3490cSdrh ** that uses the virtual table. This routine needs to create
21255a3490cSdrh ** a query plan for each invocation and compute an estimated cost for that
21355a3490cSdrh ** plan.
21455a3490cSdrh */
templatevtabBestIndex(sqlite3_vtab * tab,sqlite3_index_info * pIdxInfo)21555a3490cSdrh static int templatevtabBestIndex(
21655a3490cSdrh sqlite3_vtab *tab,
21755a3490cSdrh sqlite3_index_info *pIdxInfo
21855a3490cSdrh ){
21955a3490cSdrh pIdxInfo->estimatedCost = (double)10;
22055a3490cSdrh pIdxInfo->estimatedRows = 10;
22155a3490cSdrh return SQLITE_OK;
22255a3490cSdrh }
22355a3490cSdrh
22455a3490cSdrh /*
22555a3490cSdrh ** This following structure defines all the methods for the
22655a3490cSdrh ** virtual table.
22755a3490cSdrh */
22855a3490cSdrh static sqlite3_module templatevtabModule = {
22955a3490cSdrh /* iVersion */ 0,
23055a3490cSdrh /* xCreate */ 0,
23155a3490cSdrh /* xConnect */ templatevtabConnect,
23255a3490cSdrh /* xBestIndex */ templatevtabBestIndex,
23355a3490cSdrh /* xDisconnect */ templatevtabDisconnect,
23455a3490cSdrh /* xDestroy */ 0,
23555a3490cSdrh /* xOpen */ templatevtabOpen,
23655a3490cSdrh /* xClose */ templatevtabClose,
23755a3490cSdrh /* xFilter */ templatevtabFilter,
23855a3490cSdrh /* xNext */ templatevtabNext,
23955a3490cSdrh /* xEof */ templatevtabEof,
24055a3490cSdrh /* xColumn */ templatevtabColumn,
24155a3490cSdrh /* xRowid */ templatevtabRowid,
24255a3490cSdrh /* xUpdate */ 0,
24355a3490cSdrh /* xBegin */ 0,
24455a3490cSdrh /* xSync */ 0,
24555a3490cSdrh /* xCommit */ 0,
24655a3490cSdrh /* xRollback */ 0,
24755a3490cSdrh /* xFindMethod */ 0,
24855a3490cSdrh /* xRename */ 0,
24955a3490cSdrh /* xSavepoint */ 0,
25055a3490cSdrh /* xRelease */ 0,
251*84c501baSdrh /* xRollbackTo */ 0,
252*84c501baSdrh /* xShadowName */ 0
25355a3490cSdrh };
25455a3490cSdrh
25555a3490cSdrh
25655a3490cSdrh #ifdef _WIN32
25755a3490cSdrh __declspec(dllexport)
25855a3490cSdrh #endif
sqlite3_templatevtab_init(sqlite3 * db,char ** pzErrMsg,const sqlite3_api_routines * pApi)25955a3490cSdrh int sqlite3_templatevtab_init(
26055a3490cSdrh sqlite3 *db,
26155a3490cSdrh char **pzErrMsg,
26255a3490cSdrh const sqlite3_api_routines *pApi
26355a3490cSdrh ){
26455a3490cSdrh int rc = SQLITE_OK;
26555a3490cSdrh SQLITE_EXTENSION_INIT2(pApi);
26655a3490cSdrh rc = sqlite3_create_module(db, "templatevtab", &templatevtabModule, 0);
26755a3490cSdrh return rc;
26855a3490cSdrh }
269