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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 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