Annotation of embedaddon/sqlite3/src/test_wholenumber.c, revision 1.1.1.1
1.1 misho 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 */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>