1 /*
2 ** 2018-04-19
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 implements a template virtual-table.
14 ** Developers can make a copy of this file as a baseline for writing
15 ** new virtual tables and/or table-valued functions.
16 **
17 ** Steps for writing a new virtual table implementation:
18 **
19 ** (1) Make a copy of this file. Perhaps call it "mynewvtab.c"
20 **
21 ** (2) Replace this header comment with something appropriate for
22 ** the new virtual table
23 **
24 ** (3) Change every occurrence of "templatevtab" to some other string
25 ** appropriate for the new virtual table. Ideally, the new string
26 ** should be the basename of the source file: "mynewvtab". Also
27 ** globally change "TEMPLATEVTAB" to "MYNEWVTAB".
28 **
29 ** (4) Run a test compilation to make sure the unmodified virtual
30 ** table works.
31 **
32 ** (5) Begin making incremental changes, testing as you go, to evolve
33 ** the new virtual table to do what you want it to do.
34 **
35 ** This template is minimal, in the sense that it uses only the required
36 ** methods on the sqlite3_module object. As a result, templatevtab is
37 ** a read-only and eponymous-only table. Those limitation can be removed
38 ** by adding new methods.
39 **
40 ** This template implements an eponymous-only virtual table with a rowid and
41 ** two columns named "a" and "b". The table as 10 rows with fixed integer
42 ** values. Usage example:
43 **
44 ** SELECT rowid, a, b FROM templatevtab;
45 */
46 #if !defined(SQLITEINT_H)
47 #include "sqlite3ext.h"
48 #endif
49 SQLITE_EXTENSION_INIT1
50 #include <string.h>
51 #include <assert.h>
52
53 /* templatevtab_vtab is a subclass of sqlite3_vtab which is
54 ** underlying representation of the virtual table
55 */
56 typedef struct templatevtab_vtab templatevtab_vtab;
57 struct templatevtab_vtab {
58 sqlite3_vtab base; /* Base class - must be first */
59 /* Add new fields here, as necessary */
60 };
61
62 /* templatevtab_cursor is a subclass of sqlite3_vtab_cursor which will
63 ** serve as the underlying representation of a cursor that scans
64 ** over rows of the result
65 */
66 typedef struct templatevtab_cursor templatevtab_cursor;
67 struct templatevtab_cursor {
68 sqlite3_vtab_cursor base; /* Base class - must be first */
69 /* Insert new fields here. For this templatevtab we only keep track
70 ** of the rowid */
71 sqlite3_int64 iRowid; /* The rowid */
72 };
73
74 /*
75 ** The templatevtabConnect() method is invoked to create a new
76 ** template virtual table.
77 **
78 ** Think of this routine as the constructor for templatevtab_vtab objects.
79 **
80 ** All this routine needs to do is:
81 **
82 ** (1) Allocate the templatevtab_vtab object and initialize all fields.
83 **
84 ** (2) Tell SQLite (via the sqlite3_declare_vtab() interface) what the
85 ** result set of queries against the virtual table will look like.
86 */
templatevtabConnect(sqlite3 * db,void * pAux,int argc,const char * const * argv,sqlite3_vtab ** ppVtab,char ** pzErr)87 static int templatevtabConnect(
88 sqlite3 *db,
89 void *pAux,
90 int argc, const char *const*argv,
91 sqlite3_vtab **ppVtab,
92 char **pzErr
93 ){
94 templatevtab_vtab *pNew;
95 int rc;
96
97 rc = sqlite3_declare_vtab(db,
98 "CREATE TABLE x(a,b)"
99 );
100 /* For convenience, define symbolic names for the index to each column. */
101 #define TEMPLATEVTAB_A 0
102 #define TEMPLATEVTAB_B 1
103 if( rc==SQLITE_OK ){
104 pNew = sqlite3_malloc( sizeof(*pNew) );
105 *ppVtab = (sqlite3_vtab*)pNew;
106 if( pNew==0 ) return SQLITE_NOMEM;
107 memset(pNew, 0, sizeof(*pNew));
108 }
109 return rc;
110 }
111
112 /*
113 ** This method is the destructor for templatevtab_vtab objects.
114 */
templatevtabDisconnect(sqlite3_vtab * pVtab)115 static int templatevtabDisconnect(sqlite3_vtab *pVtab){
116 templatevtab_vtab *p = (templatevtab_vtab*)pVtab;
117 sqlite3_free(p);
118 return SQLITE_OK;
119 }
120
121 /*
122 ** Constructor for a new templatevtab_cursor object.
123 */
templatevtabOpen(sqlite3_vtab * p,sqlite3_vtab_cursor ** ppCursor)124 static int templatevtabOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
125 templatevtab_cursor *pCur;
126 pCur = sqlite3_malloc( sizeof(*pCur) );
127 if( pCur==0 ) return SQLITE_NOMEM;
128 memset(pCur, 0, sizeof(*pCur));
129 *ppCursor = &pCur->base;
130 return SQLITE_OK;
131 }
132
133 /*
134 ** Destructor for a templatevtab_cursor.
135 */
templatevtabClose(sqlite3_vtab_cursor * cur)136 static int templatevtabClose(sqlite3_vtab_cursor *cur){
137 templatevtab_cursor *pCur = (templatevtab_cursor*)cur;
138 sqlite3_free(pCur);
139 return SQLITE_OK;
140 }
141
142
143 /*
144 ** Advance a templatevtab_cursor to its next row of output.
145 */
templatevtabNext(sqlite3_vtab_cursor * cur)146 static int templatevtabNext(sqlite3_vtab_cursor *cur){
147 templatevtab_cursor *pCur = (templatevtab_cursor*)cur;
148 pCur->iRowid++;
149 return SQLITE_OK;
150 }
151
152 /*
153 ** Return values of columns for the row at which the templatevtab_cursor
154 ** is currently pointing.
155 */
templatevtabColumn(sqlite3_vtab_cursor * cur,sqlite3_context * ctx,int i)156 static int templatevtabColumn(
157 sqlite3_vtab_cursor *cur, /* The cursor */
158 sqlite3_context *ctx, /* First argument to sqlite3_result_...() */
159 int i /* Which column to return */
160 ){
161 templatevtab_cursor *pCur = (templatevtab_cursor*)cur;
162 switch( i ){
163 case TEMPLATEVTAB_A:
164 sqlite3_result_int(ctx, 1000 + pCur->iRowid);
165 break;
166 default:
167 assert( i==TEMPLATEVTAB_B );
168 sqlite3_result_int(ctx, 2000 + pCur->iRowid);
169 break;
170 }
171 return SQLITE_OK;
172 }
173
174 /*
175 ** Return the rowid for the current row. In this implementation, the
176 ** rowid is the same as the output value.
177 */
templatevtabRowid(sqlite3_vtab_cursor * cur,sqlite_int64 * pRowid)178 static int templatevtabRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
179 templatevtab_cursor *pCur = (templatevtab_cursor*)cur;
180 *pRowid = pCur->iRowid;
181 return SQLITE_OK;
182 }
183
184 /*
185 ** Return TRUE if the cursor has been moved off of the last
186 ** row of output.
187 */
templatevtabEof(sqlite3_vtab_cursor * cur)188 static int templatevtabEof(sqlite3_vtab_cursor *cur){
189 templatevtab_cursor *pCur = (templatevtab_cursor*)cur;
190 return pCur->iRowid>=10;
191 }
192
193 /*
194 ** This method is called to "rewind" the templatevtab_cursor object back
195 ** to the first row of output. This method is always called at least
196 ** once prior to any call to templatevtabColumn() or templatevtabRowid() or
197 ** templatevtabEof().
198 */
templatevtabFilter(sqlite3_vtab_cursor * pVtabCursor,int idxNum,const char * idxStr,int argc,sqlite3_value ** argv)199 static int templatevtabFilter(
200 sqlite3_vtab_cursor *pVtabCursor,
201 int idxNum, const char *idxStr,
202 int argc, sqlite3_value **argv
203 ){
204 templatevtab_cursor *pCur = (templatevtab_cursor *)pVtabCursor;
205 pCur->iRowid = 1;
206 return SQLITE_OK;
207 }
208
209 /*
210 ** SQLite will invoke this method one or more times while planning a query
211 ** that uses the virtual table. This routine needs to create
212 ** a query plan for each invocation and compute an estimated cost for that
213 ** plan.
214 */
templatevtabBestIndex(sqlite3_vtab * tab,sqlite3_index_info * pIdxInfo)215 static int templatevtabBestIndex(
216 sqlite3_vtab *tab,
217 sqlite3_index_info *pIdxInfo
218 ){
219 pIdxInfo->estimatedCost = (double)10;
220 pIdxInfo->estimatedRows = 10;
221 return SQLITE_OK;
222 }
223
224 /*
225 ** This following structure defines all the methods for the
226 ** virtual table.
227 */
228 static sqlite3_module templatevtabModule = {
229 /* iVersion */ 0,
230 /* xCreate */ 0,
231 /* xConnect */ templatevtabConnect,
232 /* xBestIndex */ templatevtabBestIndex,
233 /* xDisconnect */ templatevtabDisconnect,
234 /* xDestroy */ 0,
235 /* xOpen */ templatevtabOpen,
236 /* xClose */ templatevtabClose,
237 /* xFilter */ templatevtabFilter,
238 /* xNext */ templatevtabNext,
239 /* xEof */ templatevtabEof,
240 /* xColumn */ templatevtabColumn,
241 /* xRowid */ templatevtabRowid,
242 /* xUpdate */ 0,
243 /* xBegin */ 0,
244 /* xSync */ 0,
245 /* xCommit */ 0,
246 /* xRollback */ 0,
247 /* xFindMethod */ 0,
248 /* xRename */ 0,
249 /* xSavepoint */ 0,
250 /* xRelease */ 0,
251 /* xRollbackTo */ 0,
252 /* xShadowName */ 0
253 };
254
255
256 #ifdef _WIN32
257 __declspec(dllexport)
258 #endif
sqlite3_templatevtab_init(sqlite3 * db,char ** pzErrMsg,const sqlite3_api_routines * pApi)259 int sqlite3_templatevtab_init(
260 sqlite3 *db,
261 char **pzErrMsg,
262 const sqlite3_api_routines *pApi
263 ){
264 int rc = SQLITE_OK;
265 SQLITE_EXTENSION_INIT2(pApi);
266 rc = sqlite3_create_module(db, "templatevtab", &templatevtabModule, 0);
267 return rc;
268 }
269