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

     1  /*
     2  ** 2016-06-29
     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 demonstrates how to create a table-valued-function that
    14  ** returns the values in a C-language array.
    15  ** Examples:
    16  **
    17  **      SELECT * FROM carray($ptr,5)
    18  **
    19  ** The query above returns 5 integers contained in a C-language array
    20  ** at the address $ptr.  $ptr is a pointer to the array of integers.
    21  ** The pointer value must be assigned to $ptr using the
    22  ** sqlite3_bind_pointer() interface with a pointer type of "carray".
    23  ** For example:
    24  **
    25  **    static int aX[] = { 53, 9, 17, 2231, 4, 99 };
    26  **    int i = sqlite3_bind_parameter_index(pStmt, "$ptr");
    27  **    sqlite3_bind_value(pStmt, i, aX, "carray", 0);
    28  **
    29  ** There is an optional third parameter to determine the datatype of
    30  ** the C-language array.  Allowed values of the third parameter are
    31  ** 'int32', 'int64', 'double', 'char*'.  Example:
    32  **
    33  **      SELECT * FROM carray($ptr,10,'char*');
    34  **
    35  ** The default value of the third parameter is 'int32'.
    36  **
    37  ** HOW IT WORKS
    38  **
    39  ** The carray "function" is really a virtual table with the
    40  ** following schema:
    41  **
    42  **     CREATE TABLE carray(
    43  **       value,
    44  **       pointer HIDDEN,
    45  **       count HIDDEN,
    46  **       ctype TEXT HIDDEN
    47  **     );
    48  **
    49  ** If the hidden columns "pointer" and "count" are unconstrained, then 
    50  ** the virtual table has no rows.  Otherwise, the virtual table interprets
    51  ** the integer value of "pointer" as a pointer to the array and "count"
    52  ** as the number of elements in the array.  The virtual table steps through
    53  ** the array, element by element.
    54  */
    55  #include "sqlite3ext.h"
    56  SQLITE_EXTENSION_INIT1
    57  #include <assert.h>
    58  #include <string.h>
    59  
    60  #ifndef SQLITE_OMIT_VIRTUALTABLE
    61  
    62  /*
    63  ** Allowed datatypes
    64  */
    65  #define CARRAY_INT32    0
    66  #define CARRAY_INT64    1
    67  #define CARRAY_DOUBLE   2
    68  #define CARRAY_TEXT     3
    69  
    70  /*
    71  ** Names of types
    72  */
    73  static const char *azType[] = { "int32", "int64", "double", "char*" };
    74  
    75  
    76  /* carray_cursor is a subclass of sqlite3_vtab_cursor which will
    77  ** serve as the underlying representation of a cursor that scans
    78  ** over rows of the result
    79  */
    80  typedef struct carray_cursor carray_cursor;
    81  struct carray_cursor {
    82    sqlite3_vtab_cursor base;  /* Base class - must be first */
    83    sqlite3_int64 iRowid;      /* The rowid */
    84    void *pPtr;                /* Pointer to the array of values */
    85    sqlite3_int64 iCnt;        /* Number of integers in the array */
    86    unsigned char eType;       /* One of the CARRAY_type values */
    87  };
    88  
    89  /*
    90  ** The carrayConnect() method is invoked to create a new
    91  ** carray_vtab that describes the carray virtual table.
    92  **
    93  ** Think of this routine as the constructor for carray_vtab objects.
    94  **
    95  ** All this routine needs to do is:
    96  **
    97  **    (1) Allocate the carray_vtab object and initialize all fields.
    98  **
    99  **    (2) Tell SQLite (via the sqlite3_declare_vtab() interface) what the
   100  **        result set of queries against carray will look like.
   101  */
   102  static int carrayConnect(
   103    sqlite3 *db,
   104    void *pAux,
   105    int argc, const char *const*argv,
   106    sqlite3_vtab **ppVtab,
   107    char **pzErr
   108  ){
   109    sqlite3_vtab *pNew;
   110    int rc;
   111  
   112  /* Column numbers */
   113  #define CARRAY_COLUMN_VALUE   0
   114  #define CARRAY_COLUMN_POINTER 1
   115  #define CARRAY_COLUMN_COUNT   2
   116  #define CARRAY_COLUMN_CTYPE   3
   117  
   118    rc = sqlite3_declare_vtab(db,
   119       "CREATE TABLE x(value,pointer hidden,count hidden,ctype hidden)");
   120    if( rc==SQLITE_OK ){
   121      pNew = *ppVtab = sqlite3_malloc( sizeof(*pNew) );
   122      if( pNew==0 ) return SQLITE_NOMEM;
   123      memset(pNew, 0, sizeof(*pNew));
   124    }
   125    return rc;
   126  }
   127  
   128  /*
   129  ** This method is the destructor for carray_cursor objects.
   130  */
   131  static int carrayDisconnect(sqlite3_vtab *pVtab){
   132    sqlite3_free(pVtab);
   133    return SQLITE_OK;
   134  }
   135  
   136  /*
   137  ** Constructor for a new carray_cursor object.
   138  */
   139  static int carrayOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
   140    carray_cursor *pCur;
   141    pCur = sqlite3_malloc( sizeof(*pCur) );
   142    if( pCur==0 ) return SQLITE_NOMEM;
   143    memset(pCur, 0, sizeof(*pCur));
   144    *ppCursor = &pCur->base;
   145    return SQLITE_OK;
   146  }
   147  
   148  /*
   149  ** Destructor for a carray_cursor.
   150  */
   151  static int carrayClose(sqlite3_vtab_cursor *cur){
   152    sqlite3_free(cur);
   153    return SQLITE_OK;
   154  }
   155  
   156  
   157  /*
   158  ** Advance a carray_cursor to its next row of output.
   159  */
   160  static int carrayNext(sqlite3_vtab_cursor *cur){
   161    carray_cursor *pCur = (carray_cursor*)cur;
   162    pCur->iRowid++;
   163    return SQLITE_OK;
   164  }
   165  
   166  /*
   167  ** Return values of columns for the row at which the carray_cursor
   168  ** is currently pointing.
   169  */
   170  static int carrayColumn(
   171    sqlite3_vtab_cursor *cur,   /* The cursor */
   172    sqlite3_context *ctx,       /* First argument to sqlite3_result_...() */
   173    int i                       /* Which column to return */
   174  ){
   175    carray_cursor *pCur = (carray_cursor*)cur;
   176    sqlite3_int64 x = 0;
   177    switch( i ){
   178      case CARRAY_COLUMN_POINTER:   return SQLITE_OK;
   179      case CARRAY_COLUMN_COUNT:     x = pCur->iCnt;   break;
   180      case CARRAY_COLUMN_CTYPE: {
   181        sqlite3_result_text(ctx, azType[pCur->eType], -1, SQLITE_STATIC);
   182        return SQLITE_OK;
   183      }
   184      default: {
   185        switch( pCur->eType ){
   186          case CARRAY_INT32: {
   187            int *p = (int*)pCur->pPtr;
   188            sqlite3_result_int(ctx, p[pCur->iRowid-1]);
   189            return SQLITE_OK;
   190          }
   191          case CARRAY_INT64: {
   192            sqlite3_int64 *p = (sqlite3_int64*)pCur->pPtr;
   193            sqlite3_result_int64(ctx, p[pCur->iRowid-1]);
   194            return SQLITE_OK;
   195          }
   196          case CARRAY_DOUBLE: {
   197            double *p = (double*)pCur->pPtr;
   198            sqlite3_result_double(ctx, p[pCur->iRowid-1]);
   199            return SQLITE_OK;
   200          }
   201          case CARRAY_TEXT: {
   202            const char **p = (const char**)pCur->pPtr;
   203            sqlite3_result_text(ctx, p[pCur->iRowid-1], -1, SQLITE_TRANSIENT);
   204            return SQLITE_OK;
   205          }
   206        }
   207      }
   208    }
   209    sqlite3_result_int64(ctx, x);
   210    return SQLITE_OK;
   211  }
   212  
   213  /*
   214  ** Return the rowid for the current row.  In this implementation, the
   215  ** rowid is the same as the output value.
   216  */
   217  static int carrayRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
   218    carray_cursor *pCur = (carray_cursor*)cur;
   219    *pRowid = pCur->iRowid;
   220    return SQLITE_OK;
   221  }
   222  
   223  /*
   224  ** Return TRUE if the cursor has been moved off of the last
   225  ** row of output.
   226  */
   227  static int carrayEof(sqlite3_vtab_cursor *cur){
   228    carray_cursor *pCur = (carray_cursor*)cur;
   229    return pCur->iRowid>pCur->iCnt;
   230  }
   231  
   232  /*
   233  ** This method is called to "rewind" the carray_cursor object back
   234  ** to the first row of output.
   235  */
   236  static int carrayFilter(
   237    sqlite3_vtab_cursor *pVtabCursor, 
   238    int idxNum, const char *idxStr,
   239    int argc, sqlite3_value **argv
   240  ){
   241    carray_cursor *pCur = (carray_cursor *)pVtabCursor;
   242    if( idxNum ){
   243      pCur->pPtr = sqlite3_value_pointer(argv[0], "carray");
   244      pCur->iCnt = pCur->pPtr ? sqlite3_value_int64(argv[1]) : 0;
   245      if( idxNum<3 ){
   246        pCur->eType = CARRAY_INT32;
   247      }else{
   248        unsigned char i;
   249        const char *zType = (const char*)sqlite3_value_text(argv[2]);
   250        for(i=0; i<sizeof(azType)/sizeof(azType[0]); i++){
   251          if( sqlite3_stricmp(zType, azType[i])==0 ) break;
   252        }
   253        if( i>=sizeof(azType)/sizeof(azType[0]) ){
   254          pVtabCursor->pVtab->zErrMsg = sqlite3_mprintf(
   255            "unknown datatype: %Q", zType);
   256          return SQLITE_ERROR;
   257        }else{
   258          pCur->eType = i;
   259        }
   260      }
   261    }else{
   262      pCur->pPtr = 0;
   263      pCur->iCnt = 0;
   264    }
   265    pCur->iRowid = 1;
   266    return SQLITE_OK;
   267  }
   268  
   269  /*
   270  ** SQLite will invoke this method one or more times while planning a query
   271  ** that uses the carray virtual table.  This routine needs to create
   272  ** a query plan for each invocation and compute an estimated cost for that
   273  ** plan.
   274  **
   275  ** In this implementation idxNum is used to represent the
   276  ** query plan.  idxStr is unused.
   277  **
   278  ** idxNum is 2 if the pointer= and count= constraints exist,
   279  ** 3 if the ctype= constraint also exists, and is 0 otherwise.
   280  ** If idxNum is 0, then carray becomes an empty table.
   281  */
   282  static int carrayBestIndex(
   283    sqlite3_vtab *tab,
   284    sqlite3_index_info *pIdxInfo
   285  ){
   286    int i;                 /* Loop over constraints */
   287    int ptrIdx = -1;       /* Index of the pointer= constraint, or -1 if none */
   288    int cntIdx = -1;       /* Index of the count= constraint, or -1 if none */
   289    int ctypeIdx = -1;     /* Index of the ctype= constraint, or -1 if none */
   290  
   291    const struct sqlite3_index_constraint *pConstraint;
   292    pConstraint = pIdxInfo->aConstraint;
   293    for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){
   294      if( pConstraint->usable==0 ) continue;
   295      if( pConstraint->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue;
   296      switch( pConstraint->iColumn ){
   297        case CARRAY_COLUMN_POINTER:
   298          ptrIdx = i;
   299          break;
   300        case CARRAY_COLUMN_COUNT:
   301          cntIdx = i;
   302          break;
   303        case CARRAY_COLUMN_CTYPE:
   304          ctypeIdx = i;
   305          break;
   306      }
   307    }
   308    if( ptrIdx>=0 && cntIdx>=0 ){
   309      pIdxInfo->aConstraintUsage[ptrIdx].argvIndex = 1;
   310      pIdxInfo->aConstraintUsage[ptrIdx].omit = 1;
   311      pIdxInfo->aConstraintUsage[cntIdx].argvIndex = 2;
   312      pIdxInfo->aConstraintUsage[cntIdx].omit = 1;
   313      pIdxInfo->estimatedCost = (double)1;
   314      pIdxInfo->estimatedRows = 100;
   315      pIdxInfo->idxNum = 2;
   316      if( ctypeIdx>=0 ){
   317        pIdxInfo->aConstraintUsage[ctypeIdx].argvIndex = 3;
   318        pIdxInfo->aConstraintUsage[ctypeIdx].omit = 1;
   319        pIdxInfo->idxNum = 3;
   320      }
   321    }else{
   322      pIdxInfo->estimatedCost = (double)2147483647;
   323      pIdxInfo->estimatedRows = 2147483647;
   324      pIdxInfo->idxNum = 0;
   325    }
   326    return SQLITE_OK;
   327  }
   328  
   329  /*
   330  ** This following structure defines all the methods for the 
   331  ** carray virtual table.
   332  */
   333  static sqlite3_module carrayModule = {
   334    0,                         /* iVersion */
   335    0,                         /* xCreate */
   336    carrayConnect,             /* xConnect */
   337    carrayBestIndex,           /* xBestIndex */
   338    carrayDisconnect,          /* xDisconnect */
   339    0,                         /* xDestroy */
   340    carrayOpen,                /* xOpen - open a cursor */
   341    carrayClose,               /* xClose - close a cursor */
   342    carrayFilter,              /* xFilter - configure scan constraints */
   343    carrayNext,                /* xNext - advance a cursor */
   344    carrayEof,                 /* xEof - check for end of scan */
   345    carrayColumn,              /* xColumn - read data */
   346    carrayRowid,               /* xRowid - read data */
   347    0,                         /* xUpdate */
   348    0,                         /* xBegin */
   349    0,                         /* xSync */
   350    0,                         /* xCommit */
   351    0,                         /* xRollback */
   352    0,                         /* xFindMethod */
   353    0,                         /* xRename */
   354  };
   355  
   356  /*
   357  ** For testing purpose in the TCL test harness, we need a method for
   358  ** setting the pointer value.  The inttoptr(X) SQL function accomplishes
   359  ** this.  Tcl script will bind an integer to X and the inttoptr() SQL
   360  ** function will use sqlite3_result_pointer() to convert that integer into
   361  ** a pointer.
   362  **
   363  ** This is for testing on TCL only.
   364  */
   365  #ifdef SQLITE_TEST
   366  static void inttoptrFunc(
   367    sqlite3_context *context,
   368    int argc,
   369    sqlite3_value **argv
   370  ){
   371    void *p;
   372    sqlite3_int64 i64;
   373    i64 = sqlite3_value_int64(argv[0]);
   374    if( sizeof(i64)==sizeof(p) ){
   375      memcpy(&p, &i64, sizeof(p));
   376    }else{
   377      int i32 = i64 & 0xffffffff;
   378      memcpy(&p, &i32, sizeof(p));
   379    }
   380    sqlite3_result_pointer(context, p, "carray", 0);
   381  }
   382  #endif /* SQLITE_TEST */
   383  
   384  #endif /* SQLITE_OMIT_VIRTUALTABLE */
   385  
   386  #ifdef _WIN32
   387  __declspec(dllexport)
   388  #endif
   389  int sqlite3_carray_init(
   390    sqlite3 *db, 
   391    char **pzErrMsg, 
   392    const sqlite3_api_routines *pApi
   393  ){
   394    int rc = SQLITE_OK;
   395    SQLITE_EXTENSION_INIT2(pApi);
   396  #ifndef SQLITE_OMIT_VIRTUALTABLE
   397    rc = sqlite3_create_module(db, "carray", &carrayModule, 0);
   398  #ifdef SQLITE_TEST
   399    if( rc==SQLITE_OK ){
   400      rc = sqlite3_create_function(db, "inttoptr", 1, SQLITE_UTF8, 0,
   401                                   inttoptrFunc, 0, 0);
   402    }
   403  #endif /* SQLITE_TEST */
   404  #endif /* SQLITE_OMIT_VIRTUALTABLE */
   405    return rc;
   406  }