add pragma cipher_default_use_hmac to toggle global HMAC setting
[sqlcipher.git] / src / test_wholenumber.c
blob150dc95ac49ee64d859950df0cbc229644a57a87
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.
11 *************************************************************************
13 ** This file implements a virtual table that returns the whole numbers
14 ** between 1 and 4294967295, inclusive.
16 ** Example:
18 ** CREATE VIRTUAL TABLE nums USING wholenumber;
19 ** SELECT value FROM nums WHERE value<10;
21 ** Results in:
23 ** 1 2 3 4 5 6 7 8 9
25 #include "sqlite3.h"
26 #include <assert.h>
27 #include <string.h>
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(
42 sqlite3 *db,
43 void *pAux,
44 int argc, const char *const*argv,
45 sqlite3_vtab **ppVtab,
46 char **pzErr
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;
55 /* Note that for this virtual table, the xCreate and xConnect
56 ** methods are identical. */
58 static int wholenumberDisconnect(sqlite3_vtab *pVtab){
59 sqlite3_free(pVtab);
60 return SQLITE_OK;
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;
74 return SQLITE_OK;
78 ** Close a wholenumber cursor.
80 static int wholenumberClose(sqlite3_vtab_cursor *cur){
81 sqlite3_free(cur);
82 return SQLITE_OK;
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;
91 pCur->iValue++;
92 return SQLITE_OK;
96 ** Return the value associated with a wholenumber.
98 static int wholenumberColumn(
99 sqlite3_vtab_cursor *cur,
100 sqlite3_context *ctx,
101 int i
103 wholenumber_cursor *pCur = (wholenumber_cursor*)cur;
104 sqlite3_result_int64(ctx, pCur->iValue);
105 return SQLITE_OK;
109 ** The rowid.
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;
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 ** ------ ---------------------
133 ** 0 (none)
134 ** 1 value > $argv0
135 ** 2 value >= $argv0
136 ** 4 value < $argv0
137 ** 8 value <= $argv0
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;
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++;
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;
163 return SQLITE_OK;
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(
177 sqlite3_vtab *tab,
178 sqlite3_index_info *pIdxInfo
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;
193 if( (idxNum & 3)==0 && pConstraint->op==SQLITE_INDEX_CONSTRAINT_GE ){
194 idxNum |= 2;
195 ltIdx = i;
197 if( (idxNum & 12)==0 && pConstraint->op==SQLITE_INDEX_CONSTRAINT_LT ){
198 idxNum |= 4;
199 gtIdx = i;
201 if( (idxNum & 12)==0 && pConstraint->op==SQLITE_INDEX_CONSTRAINT_LE ){
202 idxNum |= 8;
203 gtIdx = i;
206 pIdxInfo->idxNum = idxNum;
207 if( ltIdx>=0 ){
208 pIdxInfo->aConstraintUsage[ltIdx].argvIndex = argvIdx++;
209 pIdxInfo->aConstraintUsage[ltIdx].omit = 1;
211 if( gtIdx>=0 ){
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;
221 return SQLITE_OK;
225 ** A virtual table module that provides read-only access to a
226 ** Tcl global variable namespace.
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 */
251 #endif /* SQLITE_OMIT_VIRTUALTABLE */
255 ** Register the wholenumber virtual table
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;
265 #ifdef SQLITE_TEST
266 #include <tcl.h>
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 */
281 sqlite3 *db;
282 if( objc!=2 ){
283 Tcl_WrongNumArgs(interp, 1, objv, "DB");
284 return TCL_ERROR;
286 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
287 wholenumber_register(db);
288 return TCL_OK;
293 ** Register commands with the TCL interpreter.
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 },
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);
308 return TCL_OK;
311 #endif /* SQLITE_TEST */