4 ** The author disclaims copyright to this source code. In place of
5 ** a legal notice, here is a blessing:
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.
11 *************************************************************************
13 ** This file implements a virtual table that returns the whole numbers
14 ** between 1 and 4294967295, inclusive.
18 ** CREATE VIRTUAL TABLE nums USING wholenumber;
19 ** SELECT value FROM nums WHERE value<10;
29 #ifndef SQLITE_OMIT_VIRTUALTABLE
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 */
40 /* Methods for the wholenumber module */
41 static int wholenumberConnect(
44 int argc
, const char *const*argv
,
45 sqlite3_vtab
**ppVtab
,
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
));
55 /* Note that for this virtual table, the xCreate and xConnect
56 ** methods are identical. */
58 static int wholenumberDisconnect(sqlite3_vtab
*pVtab
){
62 /* The xDisconnect and xDestroy methods are also the same */
66 ** Open a new wholenumber cursor.
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
;
78 ** Close a wholenumber cursor.
80 static int wholenumberClose(sqlite3_vtab_cursor
*cur
){
87 ** Advance a cursor to its next row of output
89 static int wholenumberNext(sqlite3_vtab_cursor
*cur
){
90 wholenumber_cursor
*pCur
= (wholenumber_cursor
*)cur
;
96 ** Return the value associated with a wholenumber.
98 static int wholenumberColumn(
99 sqlite3_vtab_cursor
*cur
,
100 sqlite3_context
*ctx
,
103 wholenumber_cursor
*pCur
= (wholenumber_cursor
*)cur
;
104 sqlite3_result_int64(ctx
, pCur
->iValue
);
111 static int wholenumberRowid(sqlite3_vtab_cursor
*cur
, sqlite_int64
*pRowid
){
112 wholenumber_cursor
*pCur
= (wholenumber_cursor
*)cur
;
113 *pRowid
= pCur
->iValue
;
118 ** When the wholenumber_cursor.rLimit value is 0 or less, that is a signal
119 ** that the cursor has nothing more to output.
121 static int wholenumberEof(sqlite3_vtab_cursor
*cur
){
122 wholenumber_cursor
*pCur
= (wholenumber_cursor
*)cur
;
123 return pCur
->iValue
>pCur
->mxValue
|| pCur
->iValue
==0;
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.
131 ** idxNum Constraints
132 ** ------ ---------------------
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
144 static int wholenumberFilter(
145 sqlite3_vtab_cursor
*pVtabCursor
,
146 int idxNum
, const char *idxStr
,
147 int argc
, sqlite3_value
**argv
149 wholenumber_cursor
*pCur
= (wholenumber_cursor
*)pVtabCursor
;
153 pCur
->mxValue
= 0xffffffff; /* 4294967295 */
155 v
= sqlite3_value_int64(argv
[0]) + (idxNum
&1);
156 if( v
>pCur
->iValue
&& v
<=pCur
->mxValue
) pCur
->iValue
= v
;
160 v
= sqlite3_value_int64(argv
[i
]) - ((idxNum
>>2)&1);
161 if( v
>=pCur
->iValue
&& v
<pCur
->mxValue
) pCur
->mxValue
= v
;
167 ** Search for terms of these forms:
169 ** (1) value > $value
170 ** (2) value >= $value
171 ** (4) value < $value
172 ** (8) value <= $value
174 ** idxNum is an ORed combination of 1 or 2 with 4 or 8.
176 static int wholenumberBestIndex(
178 sqlite3_index_info
*pIdxInfo
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
){
193 if( (idxNum
& 3)==0 && pConstraint
->op
==SQLITE_INDEX_CONSTRAINT_GE
){
197 if( (idxNum
& 12)==0 && pConstraint
->op
==SQLITE_INDEX_CONSTRAINT_LT
){
201 if( (idxNum
& 12)==0 && pConstraint
->op
==SQLITE_INDEX_CONSTRAINT_LE
){
206 pIdxInfo
->idxNum
= idxNum
;
208 pIdxInfo
->aConstraintUsage
[ltIdx
].argvIndex
= argvIdx
++;
209 pIdxInfo
->aConstraintUsage
[ltIdx
].omit
= 1;
212 pIdxInfo
->aConstraintUsage
[gtIdx
].argvIndex
= argvIdx
;
213 pIdxInfo
->aConstraintUsage
[gtIdx
].omit
= 1;
215 if( pIdxInfo
->nOrderBy
==1
216 && pIdxInfo
->aOrderBy
[0].desc
==0
218 pIdxInfo
->orderByConsumed
= 1;
220 pIdxInfo
->estimatedCost
= (double)1;
225 ** A virtual table module that provides read-only access to a
226 ** Tcl global variable namespace.
228 static sqlite3_module wholenumberModule
= {
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 */
251 #endif /* SQLITE_OMIT_VIRTUALTABLE */
255 ** Register the wholenumber virtual table
257 int wholenumber_register(sqlite3
*db
){
259 #ifndef SQLITE_OMIT_VIRTUALTABLE
260 rc
= sqlite3_create_module(db
, "wholenumber", &wholenumberModule
, 0);
268 ** Decode a pointer to an sqlite3 object.
270 extern int getDbPointer(Tcl_Interp
*interp
, const char *zA
, sqlite3
**ppDb
);
273 ** Register the echo virtual table module.
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 */
283 Tcl_WrongNumArgs(interp
, 1, objv
, "DB");
286 if( getDbPointer(interp
, Tcl_GetString(objv
[1]), &db
) ) return TCL_ERROR
;
287 wholenumber_register(db
);
293 ** Register commands with the TCL interpreter.
295 int Sqlitetestwholenumber_Init(Tcl_Interp
*interp
){
298 Tcl_ObjCmdProc
*xProc
;
301 { "register_wholenumber_module", register_wholenumber_module
, 0 },
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);
311 #endif /* SQLITE_TEST */