1 /* 2 ** 2011 April 02 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 virtual table that returns the whole numbers 14 ** between 1 and 4294967295, inclusive. 15 ** 16 ** Example: 17 ** 18 ** CREATE VIRTUAL TABLE nums USING wholenumber; 19 ** SELECT value FROM nums WHERE value<10; 20 ** 21 ** Results in: 22 ** 23 ** 1 2 3 4 5 6 7 8 9 24 */ 25 #include "sqlite3.h" 26 #include <assert.h> 27 #include <string.h> 28 29 #ifndef SQLITE_OMIT_VIRTUALTABLE 30 31 32 /* A wholenumber cursor object */ 33 typedef struct wholenumber_cursor wholenumber_cursor; 34 struct wholenumber_cursor { 35 sqlite3_vtab_cursor base; /* Base class - must be first */ 36 unsigned iValue; /* Current value */ 37 unsigned mxValue; /* Maximum value */ 38 }; 39 40 /* Methods for the wholenumber module */ 41 static int wholenumberConnect( 42 sqlite3 *db, 43 void *pAux, 44 int argc, const char *const*argv, 45 sqlite3_vtab **ppVtab, 46 char **pzErr 47 ){ 48 sqlite3_vtab *pNew; 49 pNew = *ppVtab = sqlite3_malloc( sizeof(*pNew) ); 50 if( pNew==0 ) return SQLITE_NOMEM; 51 sqlite3_declare_vtab(db, "CREATE TABLE x(value)"); 52 memset(pNew, 0, sizeof(*pNew)); 53 return SQLITE_OK; 54 } 55 /* Note that for this virtual table, the xCreate and xConnect 56 ** methods are identical. */ 57 58 static int wholenumberDisconnect(sqlite3_vtab *pVtab){ 59 sqlite3_free(pVtab); 60 return SQLITE_OK; 61 } 62 /* The xDisconnect and xDestroy methods are also the same */ 63 64 65 /* 66 ** Open a new wholenumber cursor. 67 */ 68 static int wholenumberOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){ 69 wholenumber_cursor *pCur; 70 pCur = sqlite3_malloc( sizeof(*pCur) ); 71 if( pCur==0 ) return SQLITE_NOMEM; 72 memset(pCur, 0, sizeof(*pCur)); 73 *ppCursor = &pCur->base; 74 return SQLITE_OK; 75 } 76 77 /* 78 ** Close a wholenumber cursor. 79 */ 80 static int wholenumberClose(sqlite3_vtab_cursor *cur){ 81 sqlite3_free(cur); 82 return SQLITE_OK; 83 } 84 85 86 /* 87 ** Advance a cursor to its next row of output 88 */ 89 static int wholenumberNext(sqlite3_vtab_cursor *cur){ 90 wholenumber_cursor *pCur = (wholenumber_cursor*)cur; 91 pCur->iValue++; 92 return SQLITE_OK; 93 } 94 95 /* 96 ** Return the value associated with a wholenumber. 97 */ 98 static int wholenumberColumn( 99 sqlite3_vtab_cursor *cur, 100 sqlite3_context *ctx, 101 int i 102 ){ 103 wholenumber_cursor *pCur = (wholenumber_cursor*)cur; 104 sqlite3_result_int64(ctx, pCur->iValue); 105 return SQLITE_OK; 106 } 107 108 /* 109 ** The rowid. 110 */ 111 static int wholenumberRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){ 112 wholenumber_cursor *pCur = (wholenumber_cursor*)cur; 113 *pRowid = pCur->iValue; 114 return SQLITE_OK; 115 } 116 117 /* 118 ** When the wholenumber_cursor.rLimit value is 0 or less, that is a signal 119 ** that the cursor has nothing more to output. 120 */ 121 static int wholenumberEof(sqlite3_vtab_cursor *cur){ 122 wholenumber_cursor *pCur = (wholenumber_cursor*)cur; 123 return pCur->iValue>pCur->mxValue || pCur->iValue==0; 124 } 125 126 /* 127 ** Called to "rewind" a cursor back to the beginning so that 128 ** it starts its output over again. Always called at least once 129 ** prior to any wholenumberColumn, wholenumberRowid, or wholenumberEof call. 130 ** 131 ** idxNum Constraints 132 ** ------ --------------------- 133 ** 0 (none) 134 ** 1 value > $argv0 135 ** 2 value >= $argv0 136 ** 4 value < $argv0 137 ** 8 value <= $argv0 138 ** 139 ** 5 value > $argv0 AND value < $argv1 140 ** 6 value >= $argv0 AND value < $argv1 141 ** 9 value > $argv0 AND value <= $argv1 142 ** 10 value >= $argv0 AND value <= $argv1 143 */ 144 static int wholenumberFilter( 145 sqlite3_vtab_cursor *pVtabCursor, 146 int idxNum, const char *idxStr, 147 int argc, sqlite3_value **argv 148 ){ 149 wholenumber_cursor *pCur = (wholenumber_cursor *)pVtabCursor; 150 sqlite3_int64 v; 151 int i = 0; 152 pCur->iValue = 1; 153 pCur->mxValue = 0xffffffff; /* 4294967295 */ 154 if( idxNum & 3 ){ 155 v = sqlite3_value_int64(argv[0]) + (idxNum&1); 156 if( v>pCur->iValue && v<=pCur->mxValue ) pCur->iValue = v; 157 i++; 158 } 159 if( idxNum & 12 ){ 160 v = sqlite3_value_int64(argv[i]) - ((idxNum>>2)&1); 161 if( v>=pCur->iValue && v<pCur->mxValue ) pCur->mxValue = v; 162 } 163 return SQLITE_OK; 164 } 165 166 /* 167 ** Search for terms of these forms: 168 ** 169 ** (1) value > $value 170 ** (2) value >= $value 171 ** (4) value < $value 172 ** (8) value <= $value 173 ** 174 ** idxNum is an ORed combination of 1 or 2 with 4 or 8. 175 */ 176 static int wholenumberBestIndex( 177 sqlite3_vtab *tab, 178 sqlite3_index_info *pIdxInfo 179 ){ 180 int i; 181 int idxNum = 0; 182 int argvIdx = 1; 183 int ltIdx = -1; 184 int gtIdx = -1; 185 const struct sqlite3_index_constraint *pConstraint; 186 pConstraint = pIdxInfo->aConstraint; 187 for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){ 188 if( pConstraint->usable==0 ) continue; 189 if( (idxNum & 3)==0 && pConstraint->op==SQLITE_INDEX_CONSTRAINT_GT ){ 190 idxNum |= 1; 191 ltIdx = i; 192 } 193 if( (idxNum & 3)==0 && pConstraint->op==SQLITE_INDEX_CONSTRAINT_GE ){ 194 idxNum |= 2; 195 ltIdx = i; 196 } 197 if( (idxNum & 12)==0 && pConstraint->op==SQLITE_INDEX_CONSTRAINT_LT ){ 198 idxNum |= 4; 199 gtIdx = i; 200 } 201 if( (idxNum & 12)==0 && pConstraint->op==SQLITE_INDEX_CONSTRAINT_LE ){ 202 idxNum |= 8; 203 gtIdx = i; 204 } 205 } 206 pIdxInfo->idxNum = idxNum; 207 if( ltIdx>=0 ){ 208 pIdxInfo->aConstraintUsage[ltIdx].argvIndex = argvIdx++; 209 pIdxInfo->aConstraintUsage[ltIdx].omit = 1; 210 } 211 if( gtIdx>=0 ){ 212 pIdxInfo->aConstraintUsage[gtIdx].argvIndex = argvIdx; 213 pIdxInfo->aConstraintUsage[gtIdx].omit = 1; 214 } 215 if( pIdxInfo->nOrderBy==1 216 && pIdxInfo->aOrderBy[0].desc==0 217 ){ 218 pIdxInfo->orderByConsumed = 1; 219 } 220 pIdxInfo->estimatedCost = (double)1; 221 return SQLITE_OK; 222 } 223 224 /* 225 ** A virtual table module that provides read-only access to a 226 ** Tcl global variable namespace. 227 */ 228 static sqlite3_module wholenumberModule = { 229 0, /* iVersion */ 230 wholenumberConnect, 231 wholenumberConnect, 232 wholenumberBestIndex, 233 wholenumberDisconnect, 234 wholenumberDisconnect, 235 wholenumberOpen, /* xOpen - open a cursor */ 236 wholenumberClose, /* xClose - close a cursor */ 237 wholenumberFilter, /* xFilter - configure scan constraints */ 238 wholenumberNext, /* xNext - advance a cursor */ 239 wholenumberEof, /* xEof - check for end of scan */ 240 wholenumberColumn, /* xColumn - read data */ 241 wholenumberRowid, /* xRowid - read data */ 242 0, /* xUpdate */ 243 0, /* xBegin */ 244 0, /* xSync */ 245 0, /* xCommit */ 246 0, /* xRollback */ 247 0, /* xFindMethod */ 248 0, /* xRename */ 249 }; 250 251 #endif /* SQLITE_OMIT_VIRTUALTABLE */ 252 253 254 /* 255 ** Register the wholenumber virtual table 256 */ 257 int wholenumber_register(sqlite3 *db){ 258 int rc = SQLITE_OK; 259 #ifndef SQLITE_OMIT_VIRTUALTABLE 260 rc = sqlite3_create_module(db, "wholenumber", &wholenumberModule, 0); 261 #endif 262 return rc; 263 } 264 265 #ifdef SQLITE_TEST 266 #include <tcl.h> 267 /* 268 ** Decode a pointer to an sqlite3 object. 269 */ 270 extern int getDbPointer(Tcl_Interp *interp, const char *zA, sqlite3 **ppDb); 271 272 /* 273 ** Register the echo virtual table module. 274 */ 275 static int register_wholenumber_module( 276 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ 277 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ 278 int objc, /* Number of arguments */ 279 Tcl_Obj *CONST objv[] /* Command arguments */ 280 ){ 281 sqlite3 *db; 282 if( objc!=2 ){ 283 Tcl_WrongNumArgs(interp, 1, objv, "DB"); 284 return TCL_ERROR; 285 } 286 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; 287 wholenumber_register(db); 288 return TCL_OK; 289 } 290 291 292 /* 293 ** Register commands with the TCL interpreter. 294 */ 295 int Sqlitetestwholenumber_Init(Tcl_Interp *interp){ 296 static struct { 297 char *zName; 298 Tcl_ObjCmdProc *xProc; 299 void *clientData; 300 } aObjCmd[] = { 301 { "register_wholenumber_module", register_wholenumber_module, 0 }, 302 }; 303 int i; 304 for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){ 305 Tcl_CreateObjCommand(interp, aObjCmd[i].zName, 306 aObjCmd[i].xProc, aObjCmd[i].clientData, 0); 307 } 308 return TCL_OK; 309 } 310 311 #endif /* SQLITE_TEST */ 312