modernc.org/cc@v1.0.1/v2/testdata/_sqlite/ext/misc/wholenumber.c (about) 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 "sqlite3ext.h" 26 SQLITE_EXTENSION_INIT1 27 #include <assert.h> 28 #include <string.h> 29 30 #ifndef SQLITE_OMIT_VIRTUALTABLE 31 32 33 /* A wholenumber cursor object */ 34 typedef struct wholenumber_cursor wholenumber_cursor; 35 struct wholenumber_cursor { 36 sqlite3_vtab_cursor base; /* Base class - must be first */ 37 sqlite3_int64 iValue; /* Current value */ 38 sqlite3_int64 mxValue; /* Maximum value */ 39 }; 40 41 /* Methods for the wholenumber module */ 42 static int wholenumberConnect( 43 sqlite3 *db, 44 void *pAux, 45 int argc, const char *const*argv, 46 sqlite3_vtab **ppVtab, 47 char **pzErr 48 ){ 49 sqlite3_vtab *pNew; 50 pNew = *ppVtab = sqlite3_malloc( sizeof(*pNew) ); 51 if( pNew==0 ) return SQLITE_NOMEM; 52 sqlite3_declare_vtab(db, "CREATE TABLE x(value)"); 53 memset(pNew, 0, sizeof(*pNew)); 54 return SQLITE_OK; 55 } 56 /* Note that for this virtual table, the xCreate and xConnect 57 ** methods are identical. */ 58 59 static int wholenumberDisconnect(sqlite3_vtab *pVtab){ 60 sqlite3_free(pVtab); 61 return SQLITE_OK; 62 } 63 /* The xDisconnect and xDestroy methods are also the same */ 64 65 66 /* 67 ** Open a new wholenumber cursor. 68 */ 69 static int wholenumberOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){ 70 wholenumber_cursor *pCur; 71 pCur = sqlite3_malloc( sizeof(*pCur) ); 72 if( pCur==0 ) return SQLITE_NOMEM; 73 memset(pCur, 0, sizeof(*pCur)); 74 *ppCursor = &pCur->base; 75 return SQLITE_OK; 76 } 77 78 /* 79 ** Close a wholenumber cursor. 80 */ 81 static int wholenumberClose(sqlite3_vtab_cursor *cur){ 82 sqlite3_free(cur); 83 return SQLITE_OK; 84 } 85 86 87 /* 88 ** Advance a cursor to its next row of output 89 */ 90 static int wholenumberNext(sqlite3_vtab_cursor *cur){ 91 wholenumber_cursor *pCur = (wholenumber_cursor*)cur; 92 pCur->iValue++; 93 return SQLITE_OK; 94 } 95 96 /* 97 ** Return the value associated with a wholenumber. 98 */ 99 static int wholenumberColumn( 100 sqlite3_vtab_cursor *cur, 101 sqlite3_context *ctx, 102 int i 103 ){ 104 wholenumber_cursor *pCur = (wholenumber_cursor*)cur; 105 sqlite3_result_int64(ctx, pCur->iValue); 106 return SQLITE_OK; 107 } 108 109 /* 110 ** The rowid. 111 */ 112 static int wholenumberRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){ 113 wholenumber_cursor *pCur = (wholenumber_cursor*)cur; 114 *pRowid = pCur->iValue; 115 return SQLITE_OK; 116 } 117 118 /* 119 ** When the wholenumber_cursor.rLimit value is 0 or less, that is a signal 120 ** that the cursor has nothing more to output. 121 */ 122 static int wholenumberEof(sqlite3_vtab_cursor *cur){ 123 wholenumber_cursor *pCur = (wholenumber_cursor*)cur; 124 return pCur->iValue>pCur->mxValue || pCur->iValue==0; 125 } 126 127 /* 128 ** Called to "rewind" a cursor back to the beginning so that 129 ** it starts its output over again. Always called at least once 130 ** prior to any wholenumberColumn, wholenumberRowid, or wholenumberEof call. 131 ** 132 ** idxNum Constraints 133 ** ------ --------------------- 134 ** 0 (none) 135 ** 1 value > $argv0 136 ** 2 value >= $argv0 137 ** 4 value < $argv0 138 ** 8 value <= $argv0 139 ** 140 ** 5 value > $argv0 AND value < $argv1 141 ** 6 value >= $argv0 AND value < $argv1 142 ** 9 value > $argv0 AND value <= $argv1 143 ** 10 value >= $argv0 AND value <= $argv1 144 */ 145 static int wholenumberFilter( 146 sqlite3_vtab_cursor *pVtabCursor, 147 int idxNum, const char *idxStr, 148 int argc, sqlite3_value **argv 149 ){ 150 wholenumber_cursor *pCur = (wholenumber_cursor *)pVtabCursor; 151 sqlite3_int64 v; 152 int i = 0; 153 pCur->iValue = 1; 154 pCur->mxValue = 0xffffffff; /* 4294967295 */ 155 if( idxNum & 3 ){ 156 v = sqlite3_value_int64(argv[0]) + (idxNum&1); 157 if( v>pCur->iValue && v<=pCur->mxValue ) pCur->iValue = v; 158 i++; 159 } 160 if( idxNum & 12 ){ 161 v = sqlite3_value_int64(argv[i]) - ((idxNum>>2)&1); 162 if( v>=pCur->iValue && v<pCur->mxValue ) pCur->mxValue = v; 163 } 164 return SQLITE_OK; 165 } 166 167 /* 168 ** Search for terms of these forms: 169 ** 170 ** (1) value > $value 171 ** (2) value >= $value 172 ** (4) value < $value 173 ** (8) value <= $value 174 ** 175 ** idxNum is an ORed combination of 1 or 2 with 4 or 8. 176 */ 177 static int wholenumberBestIndex( 178 sqlite3_vtab *tab, 179 sqlite3_index_info *pIdxInfo 180 ){ 181 int i; 182 int idxNum = 0; 183 int argvIdx = 1; 184 int ltIdx = -1; 185 int gtIdx = -1; 186 const struct sqlite3_index_constraint *pConstraint; 187 pConstraint = pIdxInfo->aConstraint; 188 for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){ 189 if( pConstraint->usable==0 ) continue; 190 if( (idxNum & 3)==0 && pConstraint->op==SQLITE_INDEX_CONSTRAINT_GT ){ 191 idxNum |= 1; 192 ltIdx = i; 193 } 194 if( (idxNum & 3)==0 && pConstraint->op==SQLITE_INDEX_CONSTRAINT_GE ){ 195 idxNum |= 2; 196 ltIdx = i; 197 } 198 if( (idxNum & 12)==0 && pConstraint->op==SQLITE_INDEX_CONSTRAINT_LT ){ 199 idxNum |= 4; 200 gtIdx = i; 201 } 202 if( (idxNum & 12)==0 && pConstraint->op==SQLITE_INDEX_CONSTRAINT_LE ){ 203 idxNum |= 8; 204 gtIdx = i; 205 } 206 } 207 pIdxInfo->idxNum = idxNum; 208 if( ltIdx>=0 ){ 209 pIdxInfo->aConstraintUsage[ltIdx].argvIndex = argvIdx++; 210 pIdxInfo->aConstraintUsage[ltIdx].omit = 1; 211 } 212 if( gtIdx>=0 ){ 213 pIdxInfo->aConstraintUsage[gtIdx].argvIndex = argvIdx; 214 pIdxInfo->aConstraintUsage[gtIdx].omit = 1; 215 } 216 if( pIdxInfo->nOrderBy==1 217 && pIdxInfo->aOrderBy[0].desc==0 218 ){ 219 pIdxInfo->orderByConsumed = 1; 220 } 221 if( (idxNum & 12)==0 ){ 222 pIdxInfo->estimatedCost = (double)100000000; 223 }else if( (idxNum & 3)==0 ){ 224 pIdxInfo->estimatedCost = (double)5; 225 }else{ 226 pIdxInfo->estimatedCost = (double)1; 227 } 228 return SQLITE_OK; 229 } 230 231 /* 232 ** A virtual table module that provides read-only access to a 233 ** Tcl global variable namespace. 234 */ 235 static sqlite3_module wholenumberModule = { 236 0, /* iVersion */ 237 wholenumberConnect, 238 wholenumberConnect, 239 wholenumberBestIndex, 240 wholenumberDisconnect, 241 wholenumberDisconnect, 242 wholenumberOpen, /* xOpen - open a cursor */ 243 wholenumberClose, /* xClose - close a cursor */ 244 wholenumberFilter, /* xFilter - configure scan constraints */ 245 wholenumberNext, /* xNext - advance a cursor */ 246 wholenumberEof, /* xEof - check for end of scan */ 247 wholenumberColumn, /* xColumn - read data */ 248 wholenumberRowid, /* xRowid - read data */ 249 0, /* xUpdate */ 250 0, /* xBegin */ 251 0, /* xSync */ 252 0, /* xCommit */ 253 0, /* xRollback */ 254 0, /* xFindMethod */ 255 0, /* xRename */ 256 }; 257 258 #endif /* SQLITE_OMIT_VIRTUALTABLE */ 259 260 #ifdef _WIN32 261 __declspec(dllexport) 262 #endif 263 int sqlite3_wholenumber_init( 264 sqlite3 *db, 265 char **pzErrMsg, 266 const sqlite3_api_routines *pApi 267 ){ 268 int rc = SQLITE_OK; 269 SQLITE_EXTENSION_INIT2(pApi); 270 #ifndef SQLITE_OMIT_VIRTUALTABLE 271 rc = sqlite3_create_module(db, "wholenumber", &wholenumberModule, 0); 272 #endif 273 return rc; 274 }