Annotation of embedaddon/sqlite3/src/test_wholenumber.c, revision 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>