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>