modernc.org/cc@v1.0.1/v2/testdata/_sqlite/ext/misc/wholenumber.c (about)

     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 "sqlite3ext.h"
    26  SQLITE_EXTENSION_INIT1
    27  #include <assert.h>
    28  #include <string.h>
    29  
    30  #ifndef SQLITE_OMIT_VIRTUALTABLE
    31  
    32  
    33  /* A wholenumber cursor object */
    34  typedef struct wholenumber_cursor wholenumber_cursor;
    35  struct wholenumber_cursor {
    36    sqlite3_vtab_cursor base;  /* Base class - must be first */
    37    sqlite3_int64 iValue;      /* Current value */
    38    sqlite3_int64 mxValue;     /* Maximum value */
    39  };
    40  
    41  /* Methods for the wholenumber module */
    42  static int wholenumberConnect(
    43    sqlite3 *db,
    44    void *pAux,
    45    int argc, const char *const*argv,
    46    sqlite3_vtab **ppVtab,
    47    char **pzErr
    48  ){
    49    sqlite3_vtab *pNew;
    50    pNew = *ppVtab = sqlite3_malloc( sizeof(*pNew) );
    51    if( pNew==0 ) return SQLITE_NOMEM;
    52    sqlite3_declare_vtab(db, "CREATE TABLE x(value)");
    53    memset(pNew, 0, sizeof(*pNew));
    54    return SQLITE_OK;
    55  }
    56  /* Note that for this virtual table, the xCreate and xConnect
    57  ** methods are identical. */
    58  
    59  static int wholenumberDisconnect(sqlite3_vtab *pVtab){
    60    sqlite3_free(pVtab);
    61    return SQLITE_OK;
    62  }
    63  /* The xDisconnect and xDestroy methods are also the same */
    64  
    65  
    66  /*
    67  ** Open a new wholenumber cursor.
    68  */
    69  static int wholenumberOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
    70    wholenumber_cursor *pCur;
    71    pCur = sqlite3_malloc( sizeof(*pCur) );
    72    if( pCur==0 ) return SQLITE_NOMEM;
    73    memset(pCur, 0, sizeof(*pCur));
    74    *ppCursor = &pCur->base;
    75    return SQLITE_OK;
    76  }
    77  
    78  /*
    79  ** Close a wholenumber cursor.
    80  */
    81  static int wholenumberClose(sqlite3_vtab_cursor *cur){
    82    sqlite3_free(cur);
    83    return SQLITE_OK;
    84  }
    85  
    86  
    87  /*
    88  ** Advance a cursor to its next row of output
    89  */
    90  static int wholenumberNext(sqlite3_vtab_cursor *cur){
    91    wholenumber_cursor *pCur = (wholenumber_cursor*)cur;
    92    pCur->iValue++;
    93    return SQLITE_OK;
    94  }
    95  
    96  /*
    97  ** Return the value associated with a wholenumber.
    98  */
    99  static int wholenumberColumn(
   100    sqlite3_vtab_cursor *cur,
   101    sqlite3_context *ctx,
   102    int i
   103  ){
   104    wholenumber_cursor *pCur = (wholenumber_cursor*)cur;
   105    sqlite3_result_int64(ctx, pCur->iValue);
   106    return SQLITE_OK;
   107  }
   108  
   109  /*
   110  ** The rowid.
   111  */
   112  static int wholenumberRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
   113    wholenumber_cursor *pCur = (wholenumber_cursor*)cur;
   114    *pRowid = pCur->iValue;
   115    return SQLITE_OK;
   116  }
   117  
   118  /*
   119  ** When the wholenumber_cursor.rLimit value is 0 or less, that is a signal
   120  ** that the cursor has nothing more to output.
   121  */
   122  static int wholenumberEof(sqlite3_vtab_cursor *cur){
   123    wholenumber_cursor *pCur = (wholenumber_cursor*)cur;
   124    return pCur->iValue>pCur->mxValue || pCur->iValue==0;
   125  }
   126  
   127  /*
   128  ** Called to "rewind" a cursor back to the beginning so that
   129  ** it starts its output over again.  Always called at least once
   130  ** prior to any wholenumberColumn, wholenumberRowid, or wholenumberEof call.
   131  **
   132  **    idxNum   Constraints
   133  **    ------   ---------------------
   134  **      0      (none)
   135  **      1      value > $argv0
   136  **      2      value >= $argv0
   137  **      4      value < $argv0
   138  **      8      value <= $argv0
   139  **
   140  **      5      value > $argv0 AND value < $argv1
   141  **      6      value >= $argv0 AND value < $argv1
   142  **      9      value > $argv0 AND value <= $argv1
   143  **     10      value >= $argv0 AND value <= $argv1
   144  */
   145  static int wholenumberFilter(
   146    sqlite3_vtab_cursor *pVtabCursor, 
   147    int idxNum, const char *idxStr,
   148    int argc, sqlite3_value **argv
   149  ){
   150    wholenumber_cursor *pCur = (wholenumber_cursor *)pVtabCursor;
   151    sqlite3_int64 v;
   152    int i = 0;
   153    pCur->iValue = 1;
   154    pCur->mxValue = 0xffffffff;  /* 4294967295 */
   155    if( idxNum & 3 ){
   156      v = sqlite3_value_int64(argv[0]) + (idxNum&1);
   157      if( v>pCur->iValue && v<=pCur->mxValue ) pCur->iValue = v;
   158      i++;
   159    }
   160    if( idxNum & 12 ){
   161      v = sqlite3_value_int64(argv[i]) - ((idxNum>>2)&1);
   162      if( v>=pCur->iValue && v<pCur->mxValue ) pCur->mxValue = v;
   163    }
   164    return SQLITE_OK;
   165  }
   166  
   167  /*
   168  ** Search for terms of these forms:
   169  **
   170  **  (1)  value > $value
   171  **  (2)  value >= $value
   172  **  (4)  value < $value
   173  **  (8)  value <= $value
   174  **
   175  ** idxNum is an ORed combination of 1 or 2 with 4 or 8.
   176  */
   177  static int wholenumberBestIndex(
   178    sqlite3_vtab *tab,
   179    sqlite3_index_info *pIdxInfo
   180  ){
   181    int i;
   182    int idxNum = 0;
   183    int argvIdx = 1;
   184    int ltIdx = -1;
   185    int gtIdx = -1;
   186    const struct sqlite3_index_constraint *pConstraint;
   187    pConstraint = pIdxInfo->aConstraint;
   188    for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){
   189      if( pConstraint->usable==0 ) continue;
   190      if( (idxNum & 3)==0 && pConstraint->op==SQLITE_INDEX_CONSTRAINT_GT ){
   191        idxNum |= 1;
   192        ltIdx = i;
   193      }
   194      if( (idxNum & 3)==0 && pConstraint->op==SQLITE_INDEX_CONSTRAINT_GE ){
   195        idxNum |= 2;
   196        ltIdx = i;
   197      }
   198      if( (idxNum & 12)==0 && pConstraint->op==SQLITE_INDEX_CONSTRAINT_LT ){
   199        idxNum |= 4;
   200        gtIdx = i;
   201      }
   202      if( (idxNum & 12)==0 && pConstraint->op==SQLITE_INDEX_CONSTRAINT_LE ){
   203        idxNum |= 8;
   204        gtIdx = i;
   205      }
   206    }
   207    pIdxInfo->idxNum = idxNum;
   208    if( ltIdx>=0 ){
   209      pIdxInfo->aConstraintUsage[ltIdx].argvIndex = argvIdx++;
   210      pIdxInfo->aConstraintUsage[ltIdx].omit = 1;
   211    }
   212    if( gtIdx>=0 ){
   213      pIdxInfo->aConstraintUsage[gtIdx].argvIndex = argvIdx;
   214      pIdxInfo->aConstraintUsage[gtIdx].omit = 1;
   215    }
   216    if( pIdxInfo->nOrderBy==1
   217     && pIdxInfo->aOrderBy[0].desc==0
   218    ){
   219      pIdxInfo->orderByConsumed = 1;
   220    }
   221    if( (idxNum & 12)==0 ){
   222      pIdxInfo->estimatedCost = (double)100000000;
   223    }else if( (idxNum & 3)==0 ){
   224      pIdxInfo->estimatedCost = (double)5;
   225    }else{
   226      pIdxInfo->estimatedCost = (double)1;
   227    }
   228    return SQLITE_OK;
   229  }
   230  
   231  /*
   232  ** A virtual table module that provides read-only access to a
   233  ** Tcl global variable namespace.
   234  */
   235  static sqlite3_module wholenumberModule = {
   236    0,                         /* iVersion */
   237    wholenumberConnect,
   238    wholenumberConnect,
   239    wholenumberBestIndex,
   240    wholenumberDisconnect, 
   241    wholenumberDisconnect,
   242    wholenumberOpen,           /* xOpen - open a cursor */
   243    wholenumberClose,          /* xClose - close a cursor */
   244    wholenumberFilter,         /* xFilter - configure scan constraints */
   245    wholenumberNext,           /* xNext - advance a cursor */
   246    wholenumberEof,            /* xEof - check for end of scan */
   247    wholenumberColumn,         /* xColumn - read data */
   248    wholenumberRowid,          /* xRowid - read data */
   249    0,                         /* xUpdate */
   250    0,                         /* xBegin */
   251    0,                         /* xSync */
   252    0,                         /* xCommit */
   253    0,                         /* xRollback */
   254    0,                         /* xFindMethod */
   255    0,                         /* xRename */
   256  };
   257  
   258  #endif /* SQLITE_OMIT_VIRTUALTABLE */
   259  
   260  #ifdef _WIN32
   261  __declspec(dllexport)
   262  #endif
   263  int sqlite3_wholenumber_init(
   264    sqlite3 *db, 
   265    char **pzErrMsg, 
   266    const sqlite3_api_routines *pApi
   267  ){
   268    int rc = SQLITE_OK;
   269    SQLITE_EXTENSION_INIT2(pApi);
   270  #ifndef SQLITE_OMIT_VIRTUALTABLE
   271    rc = sqlite3_create_module(db, "wholenumber", &wholenumberModule, 0);
   272  #endif
   273    return rc;
   274  }