File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / sqlite3 / src / test_wholenumber.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 17:04:17 2012 UTC (12 years, 7 months ago) by misho
Branches: sqlite3, MAIN
CVS tags: v3_7_10, HEAD
sqlite3

    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>