os/persistentdata/persistentstorage/sqlite3api/TEST/SRC/test_tclvar.c
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
sl@0
     1
/*
sl@0
     2
** 2006 June 13
sl@0
     3
**
sl@0
     4
** The author disclaims copyright to this source code.  In place of
sl@0
     5
** a legal notice, here is a blessing:
sl@0
     6
**
sl@0
     7
**    May you do good and not evil.
sl@0
     8
**    May you find forgiveness for yourself and forgive others.
sl@0
     9
**    May you share freely, never taking more than you give.
sl@0
    10
**
sl@0
    11
*************************************************************************
sl@0
    12
** Code for testing the virtual table interfaces.  This code
sl@0
    13
** is not included in the SQLite library.  It is used for automated
sl@0
    14
** testing of the SQLite library.
sl@0
    15
**
sl@0
    16
** The emphasis of this file is a virtual table that provides
sl@0
    17
** access to TCL variables.
sl@0
    18
**
sl@0
    19
** $Id: test_tclvar.c,v 1.17 2008/08/12 14:48:41 danielk1977 Exp $
sl@0
    20
*/
sl@0
    21
#include "sqliteInt.h"
sl@0
    22
#include "tcl.h"
sl@0
    23
#include <stdlib.h>
sl@0
    24
#include <string.h>
sl@0
    25
sl@0
    26
#ifndef SQLITE_OMIT_VIRTUALTABLE
sl@0
    27
sl@0
    28
typedef struct tclvar_vtab tclvar_vtab;
sl@0
    29
typedef struct tclvar_cursor tclvar_cursor;
sl@0
    30
sl@0
    31
/* 
sl@0
    32
** A tclvar virtual-table object 
sl@0
    33
*/
sl@0
    34
struct tclvar_vtab {
sl@0
    35
  sqlite3_vtab base;
sl@0
    36
  Tcl_Interp *interp;
sl@0
    37
};
sl@0
    38
sl@0
    39
/* A tclvar cursor object */
sl@0
    40
struct tclvar_cursor {
sl@0
    41
  sqlite3_vtab_cursor base;
sl@0
    42
sl@0
    43
  Tcl_Obj *pList1;     /* Result of [info vars ?pattern?] */
sl@0
    44
  Tcl_Obj *pList2;     /* Result of [array names [lindex $pList1 $i1]] */
sl@0
    45
  int i1;              /* Current item in pList1 */
sl@0
    46
  int i2;              /* Current item (if any) in pList2 */
sl@0
    47
};
sl@0
    48
sl@0
    49
/* Methods for the tclvar module */
sl@0
    50
static int tclvarConnect(
sl@0
    51
  sqlite3 *db,
sl@0
    52
  void *pAux,
sl@0
    53
  int argc, const char *const*argv,
sl@0
    54
  sqlite3_vtab **ppVtab,
sl@0
    55
  char **pzErr
sl@0
    56
){
sl@0
    57
  tclvar_vtab *pVtab;
sl@0
    58
  static const char zSchema[] = 
sl@0
    59
     "CREATE TABLE whatever(name TEXT, arrayname TEXT, value TEXT)";
sl@0
    60
  pVtab = sqlite3MallocZero( sizeof(*pVtab) );
sl@0
    61
  if( pVtab==0 ) return SQLITE_NOMEM;
sl@0
    62
  *ppVtab = &pVtab->base;
sl@0
    63
  pVtab->interp = (Tcl_Interp *)pAux;
sl@0
    64
  sqlite3_declare_vtab(db, zSchema);
sl@0
    65
  return SQLITE_OK;
sl@0
    66
}
sl@0
    67
/* Note that for this virtual table, the xCreate and xConnect
sl@0
    68
** methods are identical. */
sl@0
    69
sl@0
    70
static int tclvarDisconnect(sqlite3_vtab *pVtab){
sl@0
    71
  sqlite3_free(pVtab);
sl@0
    72
  return SQLITE_OK;
sl@0
    73
}
sl@0
    74
/* The xDisconnect and xDestroy methods are also the same */
sl@0
    75
sl@0
    76
/*
sl@0
    77
** Open a new tclvar cursor.
sl@0
    78
*/
sl@0
    79
static int tclvarOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
sl@0
    80
  tclvar_cursor *pCur;
sl@0
    81
  pCur = sqlite3MallocZero(sizeof(tclvar_cursor));
sl@0
    82
  *ppCursor = &pCur->base;
sl@0
    83
  return SQLITE_OK;
sl@0
    84
}
sl@0
    85
sl@0
    86
/*
sl@0
    87
** Close a tclvar cursor.
sl@0
    88
*/
sl@0
    89
static int tclvarClose(sqlite3_vtab_cursor *cur){
sl@0
    90
  tclvar_cursor *pCur = (tclvar_cursor *)cur;
sl@0
    91
  if( pCur->pList1 ){
sl@0
    92
    Tcl_DecrRefCount(pCur->pList1);
sl@0
    93
  }
sl@0
    94
  if( pCur->pList2 ){
sl@0
    95
    Tcl_DecrRefCount(pCur->pList2);
sl@0
    96
  }
sl@0
    97
  sqlite3_free(pCur);
sl@0
    98
  return SQLITE_OK;
sl@0
    99
}
sl@0
   100
sl@0
   101
/*
sl@0
   102
** Returns 1 if data is ready, or 0 if not.
sl@0
   103
*/
sl@0
   104
static int next2(Tcl_Interp *interp, tclvar_cursor *pCur, Tcl_Obj *pObj){
sl@0
   105
  Tcl_Obj *p;
sl@0
   106
sl@0
   107
  if( pObj ){
sl@0
   108
    if( !pCur->pList2 ){
sl@0
   109
      p = Tcl_NewStringObj("array names", -1);
sl@0
   110
      Tcl_IncrRefCount(p);
sl@0
   111
      Tcl_ListObjAppendElement(0, p, pObj);
sl@0
   112
      Tcl_EvalObjEx(interp, p, TCL_EVAL_GLOBAL);
sl@0
   113
      Tcl_DecrRefCount(p);
sl@0
   114
      pCur->pList2 = Tcl_GetObjResult(interp);
sl@0
   115
      Tcl_IncrRefCount(pCur->pList2);
sl@0
   116
      assert( pCur->i2==0 );
sl@0
   117
    }else{
sl@0
   118
      int n = 0;
sl@0
   119
      pCur->i2++;
sl@0
   120
      Tcl_ListObjLength(0, pCur->pList2, &n);
sl@0
   121
      if( pCur->i2>=n ){
sl@0
   122
        Tcl_DecrRefCount(pCur->pList2);
sl@0
   123
        pCur->pList2 = 0;
sl@0
   124
        pCur->i2 = 0;
sl@0
   125
        return 0;
sl@0
   126
      }
sl@0
   127
    }
sl@0
   128
  }
sl@0
   129
sl@0
   130
  return 1;
sl@0
   131
}
sl@0
   132
sl@0
   133
static int tclvarNext(sqlite3_vtab_cursor *cur){
sl@0
   134
  Tcl_Obj *pObj;
sl@0
   135
  int n = 0;
sl@0
   136
  int ok = 0;
sl@0
   137
sl@0
   138
  tclvar_cursor *pCur = (tclvar_cursor *)cur;
sl@0
   139
  Tcl_Interp *interp = ((tclvar_vtab *)(cur->pVtab))->interp;
sl@0
   140
sl@0
   141
  Tcl_ListObjLength(0, pCur->pList1, &n);
sl@0
   142
  while( !ok && pCur->i1<n ){
sl@0
   143
    Tcl_ListObjIndex(0, pCur->pList1, pCur->i1, &pObj);
sl@0
   144
    ok = next2(interp, pCur, pObj);
sl@0
   145
    if( !ok ){
sl@0
   146
      pCur->i1++;
sl@0
   147
    }
sl@0
   148
  }
sl@0
   149
sl@0
   150
  return 0;
sl@0
   151
}
sl@0
   152
sl@0
   153
static int tclvarFilter(
sl@0
   154
  sqlite3_vtab_cursor *pVtabCursor, 
sl@0
   155
  int idxNum, const char *idxStr,
sl@0
   156
  int argc, sqlite3_value **argv
sl@0
   157
){
sl@0
   158
  tclvar_cursor *pCur = (tclvar_cursor *)pVtabCursor;
sl@0
   159
  Tcl_Interp *interp = ((tclvar_vtab *)(pVtabCursor->pVtab))->interp;
sl@0
   160
sl@0
   161
  Tcl_Obj *p = Tcl_NewStringObj("info vars", -1);
sl@0
   162
  Tcl_IncrRefCount(p);
sl@0
   163
sl@0
   164
  assert( argc==0 || argc==1 );
sl@0
   165
  if( argc==1 ){
sl@0
   166
    Tcl_Obj *pArg = Tcl_NewStringObj((char*)sqlite3_value_text(argv[0]), -1);
sl@0
   167
    Tcl_ListObjAppendElement(0, p, pArg);
sl@0
   168
  }
sl@0
   169
  Tcl_EvalObjEx(interp, p, TCL_EVAL_GLOBAL);
sl@0
   170
  pCur->pList1 = Tcl_GetObjResult(interp);
sl@0
   171
  Tcl_IncrRefCount(pCur->pList1);
sl@0
   172
  assert( pCur->i1==0 && pCur->i2==0 && pCur->pList2==0 );
sl@0
   173
sl@0
   174
  Tcl_DecrRefCount(p);
sl@0
   175
  return tclvarNext(pVtabCursor);
sl@0
   176
}
sl@0
   177
sl@0
   178
static int tclvarColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){
sl@0
   179
  Tcl_Obj *p1;
sl@0
   180
  Tcl_Obj *p2;
sl@0
   181
  const char *z1; 
sl@0
   182
  const char *z2 = "";
sl@0
   183
  tclvar_cursor *pCur = (tclvar_cursor*)cur;
sl@0
   184
  Tcl_Interp *interp = ((tclvar_vtab *)cur->pVtab)->interp;
sl@0
   185
sl@0
   186
  Tcl_ListObjIndex(interp, pCur->pList1, pCur->i1, &p1);
sl@0
   187
  Tcl_ListObjIndex(interp, pCur->pList2, pCur->i2, &p2);
sl@0
   188
  z1 = Tcl_GetString(p1);
sl@0
   189
  if( p2 ){
sl@0
   190
    z2 = Tcl_GetString(p2);
sl@0
   191
  }
sl@0
   192
  switch (i) {
sl@0
   193
    case 0: {
sl@0
   194
      sqlite3_result_text(ctx, z1, -1, SQLITE_TRANSIENT);
sl@0
   195
      break;
sl@0
   196
    }
sl@0
   197
    case 1: {
sl@0
   198
      sqlite3_result_text(ctx, z2, -1, SQLITE_TRANSIENT);
sl@0
   199
      break;
sl@0
   200
    }
sl@0
   201
    case 2: {
sl@0
   202
      Tcl_Obj *pVal = Tcl_GetVar2Ex(interp, z1, *z2?z2:0, TCL_GLOBAL_ONLY);
sl@0
   203
      sqlite3_result_text(ctx, Tcl_GetString(pVal), -1, SQLITE_TRANSIENT);
sl@0
   204
      break;
sl@0
   205
    }
sl@0
   206
  }
sl@0
   207
  return SQLITE_OK;
sl@0
   208
}
sl@0
   209
sl@0
   210
static int tclvarRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
sl@0
   211
  *pRowid = 0;
sl@0
   212
  return SQLITE_OK;
sl@0
   213
}
sl@0
   214
sl@0
   215
static int tclvarEof(sqlite3_vtab_cursor *cur){
sl@0
   216
  tclvar_cursor *pCur = (tclvar_cursor*)cur;
sl@0
   217
  return (pCur->pList2?0:1);
sl@0
   218
}
sl@0
   219
sl@0
   220
static int tclvarBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
sl@0
   221
  int ii;
sl@0
   222
sl@0
   223
  for(ii=0; ii<pIdxInfo->nConstraint; ii++){
sl@0
   224
    struct sqlite3_index_constraint const *pCons = &pIdxInfo->aConstraint[ii];
sl@0
   225
    if( pCons->iColumn==0 && pCons->usable
sl@0
   226
           && pCons->op==SQLITE_INDEX_CONSTRAINT_EQ ){
sl@0
   227
      struct sqlite3_index_constraint_usage *pUsage;
sl@0
   228
      pUsage = &pIdxInfo->aConstraintUsage[ii];
sl@0
   229
      pUsage->omit = 0;
sl@0
   230
      pUsage->argvIndex = 1;
sl@0
   231
      return SQLITE_OK;
sl@0
   232
    }
sl@0
   233
  }
sl@0
   234
sl@0
   235
  for(ii=0; ii<pIdxInfo->nConstraint; ii++){
sl@0
   236
    struct sqlite3_index_constraint const *pCons = &pIdxInfo->aConstraint[ii];
sl@0
   237
    if( pCons->iColumn==0 && pCons->usable
sl@0
   238
           && pCons->op==SQLITE_INDEX_CONSTRAINT_MATCH ){
sl@0
   239
      struct sqlite3_index_constraint_usage *pUsage;
sl@0
   240
      pUsage = &pIdxInfo->aConstraintUsage[ii];
sl@0
   241
      pUsage->omit = 1;
sl@0
   242
      pUsage->argvIndex = 1;
sl@0
   243
      return SQLITE_OK;
sl@0
   244
    }
sl@0
   245
  }
sl@0
   246
sl@0
   247
  return SQLITE_OK;
sl@0
   248
}
sl@0
   249
sl@0
   250
/*
sl@0
   251
** A virtual table module that provides read-only access to a
sl@0
   252
** Tcl global variable namespace.
sl@0
   253
*/
sl@0
   254
static sqlite3_module tclvarModule = {
sl@0
   255
  0,                         /* iVersion */
sl@0
   256
  tclvarConnect,
sl@0
   257
  tclvarConnect,
sl@0
   258
  tclvarBestIndex,
sl@0
   259
  tclvarDisconnect, 
sl@0
   260
  tclvarDisconnect,
sl@0
   261
  tclvarOpen,                  /* xOpen - open a cursor */
sl@0
   262
  tclvarClose,                 /* xClose - close a cursor */
sl@0
   263
  tclvarFilter,                /* xFilter - configure scan constraints */
sl@0
   264
  tclvarNext,                  /* xNext - advance a cursor */
sl@0
   265
  tclvarEof,                   /* xEof - check for end of scan */
sl@0
   266
  tclvarColumn,                /* xColumn - read data */
sl@0
   267
  tclvarRowid,                 /* xRowid - read data */
sl@0
   268
  0,                           /* xUpdate */
sl@0
   269
  0,                           /* xBegin */
sl@0
   270
  0,                           /* xSync */
sl@0
   271
  0,                           /* xCommit */
sl@0
   272
  0,                           /* xRollback */
sl@0
   273
  0,                           /* xFindMethod */
sl@0
   274
  0,                           /* xRename */
sl@0
   275
};
sl@0
   276
sl@0
   277
/*
sl@0
   278
** Decode a pointer to an sqlite3 object.
sl@0
   279
*/
sl@0
   280
extern int getDbPointer(Tcl_Interp *interp, const char *zA, sqlite3 **ppDb);
sl@0
   281
sl@0
   282
/*
sl@0
   283
** Register the echo virtual table module.
sl@0
   284
*/
sl@0
   285
static int register_tclvar_module(
sl@0
   286
  ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
sl@0
   287
  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
sl@0
   288
  int objc,              /* Number of arguments */
sl@0
   289
  Tcl_Obj *CONST objv[]  /* Command arguments */
sl@0
   290
){
sl@0
   291
  sqlite3 *db;
sl@0
   292
  if( objc!=2 ){
sl@0
   293
    Tcl_WrongNumArgs(interp, 1, objv, "DB");
sl@0
   294
    return TCL_ERROR;
sl@0
   295
  }
sl@0
   296
  if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
sl@0
   297
#ifndef SQLITE_OMIT_VIRTUALTABLE
sl@0
   298
  sqlite3_create_module(db, "tclvar", &tclvarModule, (void *)interp);
sl@0
   299
#endif
sl@0
   300
  return TCL_OK;
sl@0
   301
}
sl@0
   302
sl@0
   303
#endif
sl@0
   304
sl@0
   305
sl@0
   306
/*
sl@0
   307
** Register commands with the TCL interpreter.
sl@0
   308
*/
sl@0
   309
int Sqlitetesttclvar_Init(Tcl_Interp *interp){
sl@0
   310
#ifndef SQLITE_OMIT_VIRTUALTABLE
sl@0
   311
  static struct {
sl@0
   312
     char *zName;
sl@0
   313
     Tcl_ObjCmdProc *xProc;
sl@0
   314
     void *clientData;
sl@0
   315
  } aObjCmd[] = {
sl@0
   316
     { "register_tclvar_module",   register_tclvar_module, 0 },
sl@0
   317
  };
sl@0
   318
  int i;
sl@0
   319
  for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){
sl@0
   320
    Tcl_CreateObjCommand(interp, aObjCmd[i].zName, 
sl@0
   321
        aObjCmd[i].xProc, aObjCmd[i].clientData, 0);
sl@0
   322
  }
sl@0
   323
#endif
sl@0
   324
  return TCL_OK;
sl@0
   325
}