Annotation of embedaddon/sqlite3/src/test_tclvar.c, revision 1.1.1.1

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>