Annotation of embedaddon/sqlite3/src/test_tclvar.c, revision 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>