Annotation of embedaddon/sqlite3/src/test3.c, revision 1.1

1.1     ! misho       1: /*
        !             2: ** 2001 September 15
        !             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 btree.c module in SQLite.  This code
        !            13: ** is not included in the SQLite library.  It is used for automated
        !            14: ** testing of the SQLite library.
        !            15: */
        !            16: #include "sqliteInt.h"
        !            17: #include "btreeInt.h"
        !            18: #include "tcl.h"
        !            19: #include <stdlib.h>
        !            20: #include <string.h>
        !            21: 
        !            22: /*
        !            23: ** Interpret an SQLite error number
        !            24: */
        !            25: static char *errorName(int rc){
        !            26:   char *zName;
        !            27:   switch( rc ){
        !            28:     case SQLITE_OK:         zName = "SQLITE_OK";          break;
        !            29:     case SQLITE_ERROR:      zName = "SQLITE_ERROR";       break;
        !            30:     case SQLITE_PERM:       zName = "SQLITE_PERM";        break;
        !            31:     case SQLITE_ABORT:      zName = "SQLITE_ABORT";       break;
        !            32:     case SQLITE_BUSY:       zName = "SQLITE_BUSY";        break;
        !            33:     case SQLITE_NOMEM:      zName = "SQLITE_NOMEM";       break;
        !            34:     case SQLITE_READONLY:   zName = "SQLITE_READONLY";    break;
        !            35:     case SQLITE_INTERRUPT:  zName = "SQLITE_INTERRUPT";   break;
        !            36:     case SQLITE_IOERR:      zName = "SQLITE_IOERR";       break;
        !            37:     case SQLITE_CORRUPT:    zName = "SQLITE_CORRUPT";     break;
        !            38:     case SQLITE_FULL:       zName = "SQLITE_FULL";        break;
        !            39:     case SQLITE_CANTOPEN:   zName = "SQLITE_CANTOPEN";    break;
        !            40:     case SQLITE_PROTOCOL:   zName = "SQLITE_PROTOCOL";    break;
        !            41:     case SQLITE_EMPTY:      zName = "SQLITE_EMPTY";       break;
        !            42:     case SQLITE_LOCKED:     zName = "SQLITE_LOCKED";      break;
        !            43:     default:                zName = "SQLITE_Unknown";     break;
        !            44:   }
        !            45:   return zName;
        !            46: }
        !            47: 
        !            48: /*
        !            49: ** A bogus sqlite3 connection structure for use in the btree
        !            50: ** tests.
        !            51: */
        !            52: static sqlite3 sDb;
        !            53: static int nRefSqlite3 = 0;
        !            54: 
        !            55: /*
        !            56: ** Usage:   btree_open FILENAME NCACHE
        !            57: **
        !            58: ** Open a new database
        !            59: */
        !            60: static int btree_open(
        !            61:   void *NotUsed,
        !            62:   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
        !            63:   int argc,              /* Number of arguments */
        !            64:   const char **argv      /* Text of each argument */
        !            65: ){
        !            66:   Btree *pBt;
        !            67:   int rc, nCache;
        !            68:   char zBuf[100];
        !            69:   int n;
        !            70:   char *zFilename;
        !            71:   if( argc!=3 ){
        !            72:     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
        !            73:        " FILENAME NCACHE FLAGS\"", 0);
        !            74:     return TCL_ERROR;
        !            75:   }
        !            76:   if( Tcl_GetInt(interp, argv[2], &nCache) ) return TCL_ERROR;
        !            77:   nRefSqlite3++;
        !            78:   if( nRefSqlite3==1 ){
        !            79:     sDb.pVfs = sqlite3_vfs_find(0);
        !            80:     sDb.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_RECURSIVE);
        !            81:     sqlite3_mutex_enter(sDb.mutex);
        !            82:   }
        !            83:   n = strlen(argv[1]);
        !            84:   zFilename = sqlite3_malloc( n+2 );
        !            85:   if( zFilename==0 ) return TCL_ERROR;
        !            86:   memcpy(zFilename, argv[1], n+1);
        !            87:   zFilename[n+1] = 0;
        !            88:   rc = sqlite3BtreeOpen(sDb.pVfs, zFilename, &sDb, &pBt, 0, 
        !            89:      SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_MAIN_DB);
        !            90:   sqlite3_free(zFilename);
        !            91:   if( rc!=SQLITE_OK ){
        !            92:     Tcl_AppendResult(interp, errorName(rc), 0);
        !            93:     return TCL_ERROR;
        !            94:   }
        !            95:   sqlite3BtreeSetCacheSize(pBt, nCache);
        !            96:   sqlite3_snprintf(sizeof(zBuf), zBuf,"%p", pBt);
        !            97:   Tcl_AppendResult(interp, zBuf, 0);
        !            98:   return TCL_OK;
        !            99: }
        !           100: 
        !           101: /*
        !           102: ** Usage:   btree_close ID
        !           103: **
        !           104: ** Close the given database.
        !           105: */
        !           106: static int btree_close(
        !           107:   void *NotUsed,
        !           108:   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
        !           109:   int argc,              /* Number of arguments */
        !           110:   const char **argv      /* Text of each argument */
        !           111: ){
        !           112:   Btree *pBt;
        !           113:   int rc;
        !           114:   if( argc!=2 ){
        !           115:     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
        !           116:        " ID\"", 0);
        !           117:     return TCL_ERROR;
        !           118:   }
        !           119:   pBt = sqlite3TestTextToPtr(argv[1]);
        !           120:   rc = sqlite3BtreeClose(pBt);
        !           121:   if( rc!=SQLITE_OK ){
        !           122:     Tcl_AppendResult(interp, errorName(rc), 0);
        !           123:     return TCL_ERROR;
        !           124:   }
        !           125:   nRefSqlite3--;
        !           126:   if( nRefSqlite3==0 ){
        !           127:     sqlite3_mutex_leave(sDb.mutex);
        !           128:     sqlite3_mutex_free(sDb.mutex);
        !           129:     sDb.mutex = 0;
        !           130:     sDb.pVfs = 0;
        !           131:   }
        !           132:   return TCL_OK;
        !           133: }
        !           134: 
        !           135: 
        !           136: /*
        !           137: ** Usage:   btree_begin_transaction ID
        !           138: **
        !           139: ** Start a new transaction
        !           140: */
        !           141: static int btree_begin_transaction(
        !           142:   void *NotUsed,
        !           143:   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
        !           144:   int argc,              /* Number of arguments */
        !           145:   const char **argv      /* Text of each argument */
        !           146: ){
        !           147:   Btree *pBt;
        !           148:   int rc;
        !           149:   if( argc!=2 ){
        !           150:     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
        !           151:        " ID\"", 0);
        !           152:     return TCL_ERROR;
        !           153:   }
        !           154:   pBt = sqlite3TestTextToPtr(argv[1]);
        !           155:   sqlite3BtreeEnter(pBt);
        !           156:   rc = sqlite3BtreeBeginTrans(pBt, 1);
        !           157:   sqlite3BtreeLeave(pBt);
        !           158:   if( rc!=SQLITE_OK ){
        !           159:     Tcl_AppendResult(interp, errorName(rc), 0);
        !           160:     return TCL_ERROR;
        !           161:   }
        !           162:   return TCL_OK;
        !           163: }
        !           164: 
        !           165: /*
        !           166: ** Usage:   btree_pager_stats ID
        !           167: **
        !           168: ** Returns pager statistics
        !           169: */
        !           170: static int btree_pager_stats(
        !           171:   void *NotUsed,
        !           172:   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
        !           173:   int argc,              /* Number of arguments */
        !           174:   const char **argv      /* Text of each argument */
        !           175: ){
        !           176:   Btree *pBt;
        !           177:   int i;
        !           178:   int *a;
        !           179: 
        !           180:   if( argc!=2 ){
        !           181:     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
        !           182:        " ID\"", 0);
        !           183:     return TCL_ERROR;
        !           184:   }
        !           185:   pBt = sqlite3TestTextToPtr(argv[1]);
        !           186:  
        !           187:   /* Normally in this file, with a b-tree handle opened using the 
        !           188:   ** [btree_open] command it is safe to call sqlite3BtreeEnter() directly.
        !           189:   ** But this function is sometimes called with a btree handle obtained
        !           190:   ** from an open SQLite connection (using [btree_from_db]). In this case
        !           191:   ** we need to obtain the mutex for the controlling SQLite handle before
        !           192:   ** it is safe to call sqlite3BtreeEnter().
        !           193:   */
        !           194:   sqlite3_mutex_enter(pBt->db->mutex);
        !           195: 
        !           196:   sqlite3BtreeEnter(pBt);
        !           197:   a = sqlite3PagerStats(sqlite3BtreePager(pBt));
        !           198:   for(i=0; i<11; i++){
        !           199:     static char *zName[] = {
        !           200:       "ref", "page", "max", "size", "state", "err",
        !           201:       "hit", "miss", "ovfl", "read", "write"
        !           202:     };
        !           203:     char zBuf[100];
        !           204:     Tcl_AppendElement(interp, zName[i]);
        !           205:     sqlite3_snprintf(sizeof(zBuf), zBuf,"%d",a[i]);
        !           206:     Tcl_AppendElement(interp, zBuf);
        !           207:   }
        !           208:   sqlite3BtreeLeave(pBt);
        !           209: 
        !           210:   /* Release the mutex on the SQLite handle that controls this b-tree */
        !           211:   sqlite3_mutex_leave(pBt->db->mutex);
        !           212:   return TCL_OK;
        !           213: }
        !           214: 
        !           215: /*
        !           216: ** Usage:   btree_cursor ID TABLENUM WRITEABLE
        !           217: **
        !           218: ** Create a new cursor.  Return the ID for the cursor.
        !           219: */
        !           220: static int btree_cursor(
        !           221:   void *NotUsed,
        !           222:   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
        !           223:   int argc,              /* Number of arguments */
        !           224:   const char **argv      /* Text of each argument */
        !           225: ){
        !           226:   Btree *pBt;
        !           227:   int iTable;
        !           228:   BtCursor *pCur;
        !           229:   int rc = SQLITE_OK;
        !           230:   int wrFlag;
        !           231:   char zBuf[30];
        !           232: 
        !           233:   if( argc!=4 ){
        !           234:     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
        !           235:        " ID TABLENUM WRITEABLE\"", 0);
        !           236:     return TCL_ERROR;
        !           237:   }
        !           238:   pBt = sqlite3TestTextToPtr(argv[1]);
        !           239:   if( Tcl_GetInt(interp, argv[2], &iTable) ) return TCL_ERROR;
        !           240:   if( Tcl_GetBoolean(interp, argv[3], &wrFlag) ) return TCL_ERROR;
        !           241:   pCur = (BtCursor *)ckalloc(sqlite3BtreeCursorSize());
        !           242:   memset(pCur, 0, sqlite3BtreeCursorSize());
        !           243:   sqlite3BtreeEnter(pBt);
        !           244: #ifndef SQLITE_OMIT_SHARED_CACHE
        !           245:   rc = sqlite3BtreeLockTable(pBt, iTable, wrFlag);
        !           246: #endif
        !           247:   if( rc==SQLITE_OK ){
        !           248:     rc = sqlite3BtreeCursor(pBt, iTable, wrFlag, 0, pCur);
        !           249:   }
        !           250:   sqlite3BtreeLeave(pBt);
        !           251:   if( rc ){
        !           252:     ckfree((char *)pCur);
        !           253:     Tcl_AppendResult(interp, errorName(rc), 0);
        !           254:     return TCL_ERROR;
        !           255:   }
        !           256:   sqlite3_snprintf(sizeof(zBuf), zBuf,"%p", pCur);
        !           257:   Tcl_AppendResult(interp, zBuf, 0);
        !           258:   return SQLITE_OK;
        !           259: }
        !           260: 
        !           261: /*
        !           262: ** Usage:   btree_close_cursor ID
        !           263: **
        !           264: ** Close a cursor opened using btree_cursor.
        !           265: */
        !           266: static int btree_close_cursor(
        !           267:   void *NotUsed,
        !           268:   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
        !           269:   int argc,              /* Number of arguments */
        !           270:   const char **argv      /* Text of each argument */
        !           271: ){
        !           272:   BtCursor *pCur;
        !           273:   Btree *pBt;
        !           274:   int rc;
        !           275: 
        !           276:   if( argc!=2 ){
        !           277:     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
        !           278:        " ID\"", 0);
        !           279:     return TCL_ERROR;
        !           280:   }
        !           281:   pCur = sqlite3TestTextToPtr(argv[1]);
        !           282:   pBt = pCur->pBtree;
        !           283:   sqlite3BtreeEnter(pBt);
        !           284:   rc = sqlite3BtreeCloseCursor(pCur);
        !           285:   sqlite3BtreeLeave(pBt);
        !           286:   ckfree((char *)pCur);
        !           287:   if( rc ){
        !           288:     Tcl_AppendResult(interp, errorName(rc), 0);
        !           289:     return TCL_ERROR;
        !           290:   }
        !           291:   return SQLITE_OK;
        !           292: }
        !           293: 
        !           294: /*
        !           295: ** Usage:   btree_next ID
        !           296: **
        !           297: ** Move the cursor to the next entry in the table.  Return 0 on success
        !           298: ** or 1 if the cursor was already on the last entry in the table or if
        !           299: ** the table is empty.
        !           300: */
        !           301: static int btree_next(
        !           302:   void *NotUsed,
        !           303:   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
        !           304:   int argc,              /* Number of arguments */
        !           305:   const char **argv      /* Text of each argument */
        !           306: ){
        !           307:   BtCursor *pCur;
        !           308:   int rc;
        !           309:   int res = 0;
        !           310:   char zBuf[100];
        !           311: 
        !           312:   if( argc!=2 ){
        !           313:     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
        !           314:        " ID\"", 0);
        !           315:     return TCL_ERROR;
        !           316:   }
        !           317:   pCur = sqlite3TestTextToPtr(argv[1]);
        !           318:   sqlite3BtreeEnter(pCur->pBtree);
        !           319:   rc = sqlite3BtreeNext(pCur, &res);
        !           320:   sqlite3BtreeLeave(pCur->pBtree);
        !           321:   if( rc ){
        !           322:     Tcl_AppendResult(interp, errorName(rc), 0);
        !           323:     return TCL_ERROR;
        !           324:   }
        !           325:   sqlite3_snprintf(sizeof(zBuf),zBuf,"%d",res);
        !           326:   Tcl_AppendResult(interp, zBuf, 0);
        !           327:   return SQLITE_OK;
        !           328: }
        !           329: 
        !           330: /*
        !           331: ** Usage:   btree_first ID
        !           332: **
        !           333: ** Move the cursor to the first entry in the table.  Return 0 if the
        !           334: ** cursor was left point to something and 1 if the table is empty.
        !           335: */
        !           336: static int btree_first(
        !           337:   void *NotUsed,
        !           338:   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
        !           339:   int argc,              /* Number of arguments */
        !           340:   const char **argv      /* Text of each argument */
        !           341: ){
        !           342:   BtCursor *pCur;
        !           343:   int rc;
        !           344:   int res = 0;
        !           345:   char zBuf[100];
        !           346: 
        !           347:   if( argc!=2 ){
        !           348:     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
        !           349:        " ID\"", 0);
        !           350:     return TCL_ERROR;
        !           351:   }
        !           352:   pCur = sqlite3TestTextToPtr(argv[1]);
        !           353:   sqlite3BtreeEnter(pCur->pBtree);
        !           354:   rc = sqlite3BtreeFirst(pCur, &res);
        !           355:   sqlite3BtreeLeave(pCur->pBtree);
        !           356:   if( rc ){
        !           357:     Tcl_AppendResult(interp, errorName(rc), 0);
        !           358:     return TCL_ERROR;
        !           359:   }
        !           360:   sqlite3_snprintf(sizeof(zBuf),zBuf,"%d",res);
        !           361:   Tcl_AppendResult(interp, zBuf, 0);
        !           362:   return SQLITE_OK;
        !           363: }
        !           364: 
        !           365: /*
        !           366: ** Usage:   btree_eof ID
        !           367: **
        !           368: ** Return TRUE if the given cursor is not pointing at a valid entry.
        !           369: ** Return FALSE if the cursor does point to a valid entry.
        !           370: */
        !           371: static int btree_eof(
        !           372:   void *NotUsed,
        !           373:   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
        !           374:   int argc,              /* Number of arguments */
        !           375:   const char **argv      /* Text of each argument */
        !           376: ){
        !           377:   BtCursor *pCur;
        !           378:   int rc;
        !           379:   char zBuf[50];
        !           380: 
        !           381:   if( argc!=2 ){
        !           382:     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
        !           383:        " ID\"", 0);
        !           384:     return TCL_ERROR;
        !           385:   }
        !           386:   pCur = sqlite3TestTextToPtr(argv[1]);
        !           387:   sqlite3BtreeEnter(pCur->pBtree);
        !           388:   rc = sqlite3BtreeEof(pCur);
        !           389:   sqlite3BtreeLeave(pCur->pBtree);
        !           390:   sqlite3_snprintf(sizeof(zBuf),zBuf, "%d", rc);
        !           391:   Tcl_AppendResult(interp, zBuf, 0);
        !           392:   return SQLITE_OK;
        !           393: }
        !           394: 
        !           395: /*
        !           396: ** Usage:   btree_payload_size ID
        !           397: **
        !           398: ** Return the number of bytes of payload
        !           399: */
        !           400: static int btree_payload_size(
        !           401:   void *NotUsed,
        !           402:   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
        !           403:   int argc,              /* Number of arguments */
        !           404:   const char **argv      /* Text of each argument */
        !           405: ){
        !           406:   BtCursor *pCur;
        !           407:   int n2;
        !           408:   u64 n1;
        !           409:   char zBuf[50];
        !           410: 
        !           411:   if( argc!=2 ){
        !           412:     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
        !           413:        " ID\"", 0);
        !           414:     return TCL_ERROR;
        !           415:   }
        !           416:   pCur = sqlite3TestTextToPtr(argv[1]);
        !           417:   sqlite3BtreeEnter(pCur->pBtree);
        !           418: 
        !           419:   /* The cursor may be in "require-seek" state. If this is the case, the
        !           420:   ** call to BtreeDataSize() will fix it. */
        !           421:   sqlite3BtreeDataSize(pCur, (u32*)&n2);
        !           422:   if( pCur->apPage[pCur->iPage]->intKey ){
        !           423:     n1 = 0;
        !           424:   }else{
        !           425:     sqlite3BtreeKeySize(pCur, (i64*)&n1);
        !           426:   }
        !           427:   sqlite3BtreeLeave(pCur->pBtree);
        !           428:   sqlite3_snprintf(sizeof(zBuf),zBuf, "%d", (int)(n1+n2));
        !           429:   Tcl_AppendResult(interp, zBuf, 0);
        !           430:   return SQLITE_OK;
        !           431: }
        !           432: 
        !           433: /*
        !           434: ** usage:   varint_test  START  MULTIPLIER  COUNT  INCREMENT
        !           435: **
        !           436: ** This command tests the putVarint() and getVarint()
        !           437: ** routines, both for accuracy and for speed.
        !           438: **
        !           439: ** An integer is written using putVarint() and read back with
        !           440: ** getVarint() and varified to be unchanged.  This repeats COUNT
        !           441: ** times.  The first integer is START*MULTIPLIER.  Each iteration
        !           442: ** increases the integer by INCREMENT.
        !           443: **
        !           444: ** This command returns nothing if it works.  It returns an error message
        !           445: ** if something goes wrong.
        !           446: */
        !           447: static int btree_varint_test(
        !           448:   void *NotUsed,
        !           449:   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
        !           450:   int argc,              /* Number of arguments */
        !           451:   const char **argv      /* Text of each argument */
        !           452: ){
        !           453:   u32 start, mult, count, incr;
        !           454:   u64 in, out;
        !           455:   int n1, n2, i, j;
        !           456:   unsigned char zBuf[100];
        !           457:   if( argc!=5 ){
        !           458:     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
        !           459:        " START MULTIPLIER COUNT INCREMENT\"", 0);
        !           460:     return TCL_ERROR;
        !           461:   }
        !           462:   if( Tcl_GetInt(interp, argv[1], (int*)&start) ) return TCL_ERROR;
        !           463:   if( Tcl_GetInt(interp, argv[2], (int*)&mult) ) return TCL_ERROR;
        !           464:   if( Tcl_GetInt(interp, argv[3], (int*)&count) ) return TCL_ERROR;
        !           465:   if( Tcl_GetInt(interp, argv[4], (int*)&incr) ) return TCL_ERROR;
        !           466:   in = start;
        !           467:   in *= mult;
        !           468:   for(i=0; i<count; i++){
        !           469:     char zErr[200];
        !           470:     n1 = putVarint(zBuf, in);
        !           471:     if( n1>9 || n1<1 ){
        !           472:       sprintf(zErr, "putVarint returned %d - should be between 1 and 9", n1);
        !           473:       Tcl_AppendResult(interp, zErr, 0);
        !           474:       return TCL_ERROR;
        !           475:     }
        !           476:     n2 = getVarint(zBuf, &out);
        !           477:     if( n1!=n2 ){
        !           478:       sprintf(zErr, "putVarint returned %d and getVarint returned %d", n1, n2);
        !           479:       Tcl_AppendResult(interp, zErr, 0);
        !           480:       return TCL_ERROR;
        !           481:     }
        !           482:     if( in!=out ){
        !           483:       sprintf(zErr, "Wrote 0x%016llx and got back 0x%016llx", in, out);
        !           484:       Tcl_AppendResult(interp, zErr, 0);
        !           485:       return TCL_ERROR;
        !           486:     }
        !           487:     if( (in & 0xffffffff)==in ){
        !           488:       u32 out32;
        !           489:       n2 = getVarint32(zBuf, out32);
        !           490:       out = out32;
        !           491:       if( n1!=n2 ){
        !           492:         sprintf(zErr, "putVarint returned %d and GetVarint32 returned %d", 
        !           493:                   n1, n2);
        !           494:         Tcl_AppendResult(interp, zErr, 0);
        !           495:         return TCL_ERROR;
        !           496:       }
        !           497:       if( in!=out ){
        !           498:         sprintf(zErr, "Wrote 0x%016llx and got back 0x%016llx from GetVarint32",
        !           499:             in, out);
        !           500:         Tcl_AppendResult(interp, zErr, 0);
        !           501:         return TCL_ERROR;
        !           502:       }
        !           503:     }
        !           504: 
        !           505:     /* In order to get realistic timings, run getVarint 19 more times.
        !           506:     ** This is because getVarint is called about 20 times more often
        !           507:     ** than putVarint.
        !           508:     */
        !           509:     for(j=0; j<19; j++){
        !           510:       getVarint(zBuf, &out);
        !           511:     }
        !           512:     in += incr;
        !           513:   }
        !           514:   return TCL_OK;
        !           515: }
        !           516: 
        !           517: /*
        !           518: ** usage:   btree_from_db  DB-HANDLE
        !           519: **
        !           520: ** This command returns the btree handle for the main database associated
        !           521: ** with the database-handle passed as the argument. Example usage:
        !           522: **
        !           523: ** sqlite3 db test.db
        !           524: ** set bt [btree_from_db db]
        !           525: */
        !           526: static int btree_from_db(
        !           527:   void *NotUsed,
        !           528:   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
        !           529:   int argc,              /* Number of arguments */
        !           530:   const char **argv      /* Text of each argument */
        !           531: ){
        !           532:   char zBuf[100];
        !           533:   Tcl_CmdInfo info;
        !           534:   sqlite3 *db;
        !           535:   Btree *pBt;
        !           536:   int iDb = 0;
        !           537: 
        !           538:   if( argc!=2 && argc!=3 ){
        !           539:     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
        !           540:        " DB-HANDLE ?N?\"", 0);
        !           541:     return TCL_ERROR;
        !           542:   }
        !           543: 
        !           544:   if( 1!=Tcl_GetCommandInfo(interp, argv[1], &info) ){
        !           545:     Tcl_AppendResult(interp, "No such db-handle: \"", argv[1], "\"", 0);
        !           546:     return TCL_ERROR;
        !           547:   }
        !           548:   if( argc==3 ){
        !           549:     iDb = atoi(argv[2]);
        !           550:   }
        !           551: 
        !           552:   db = *((sqlite3 **)info.objClientData);
        !           553:   assert( db );
        !           554: 
        !           555:   pBt = db->aDb[iDb].pBt;
        !           556:   sqlite3_snprintf(sizeof(zBuf), zBuf, "%p", pBt);
        !           557:   Tcl_SetResult(interp, zBuf, TCL_VOLATILE);
        !           558:   return TCL_OK;
        !           559: }
        !           560: 
        !           561: /*
        !           562: ** Usage:   btree_ismemdb ID
        !           563: **
        !           564: ** Return true if the B-Tree is in-memory.
        !           565: */
        !           566: static int btree_ismemdb(
        !           567:   void *NotUsed,
        !           568:   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
        !           569:   int argc,              /* Number of arguments */
        !           570:   const char **argv      /* Text of each argument */
        !           571: ){
        !           572:   Btree *pBt;
        !           573:   int res;
        !           574: 
        !           575:   if( argc!=2 ){
        !           576:     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
        !           577:        " ID\"", 0);
        !           578:     return TCL_ERROR;
        !           579:   }
        !           580:   pBt = sqlite3TestTextToPtr(argv[1]);
        !           581:   sqlite3_mutex_enter(pBt->db->mutex);
        !           582:   sqlite3BtreeEnter(pBt);
        !           583:   res = sqlite3PagerIsMemdb(sqlite3BtreePager(pBt));
        !           584:   sqlite3BtreeLeave(pBt);
        !           585:   sqlite3_mutex_leave(pBt->db->mutex);
        !           586:   Tcl_SetObjResult(interp, Tcl_NewBooleanObj(res));
        !           587:   return SQLITE_OK;
        !           588: }
        !           589: 
        !           590: /*
        !           591: ** usage:   btree_set_cache_size ID NCACHE
        !           592: **
        !           593: ** Set the size of the cache used by btree $ID.
        !           594: */
        !           595: static int btree_set_cache_size(
        !           596:   void *NotUsed,
        !           597:   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
        !           598:   int argc,              /* Number of arguments */
        !           599:   const char **argv      /* Text of each argument */
        !           600: ){
        !           601:   int nCache;
        !           602:   Btree *pBt;
        !           603:   
        !           604:   if( argc!=3 ){
        !           605:     Tcl_AppendResult(
        !           606:         interp, "wrong # args: should be \"", argv[0], " BT NCACHE\"", 0);
        !           607:     return TCL_ERROR;
        !           608:   }
        !           609:   pBt = sqlite3TestTextToPtr(argv[1]);
        !           610:   if( Tcl_GetInt(interp, argv[2], &nCache) ) return TCL_ERROR;
        !           611: 
        !           612:   sqlite3_mutex_enter(pBt->db->mutex);
        !           613:   sqlite3BtreeEnter(pBt);
        !           614:   sqlite3BtreeSetCacheSize(pBt, nCache);
        !           615:   sqlite3BtreeLeave(pBt);
        !           616:   sqlite3_mutex_leave(pBt->db->mutex);
        !           617:   return TCL_OK;
        !           618: }      
        !           619: 
        !           620: 
        !           621: 
        !           622: /*
        !           623: ** Register commands with the TCL interpreter.
        !           624: */
        !           625: int Sqlitetest3_Init(Tcl_Interp *interp){
        !           626:   static struct {
        !           627:      char *zName;
        !           628:      Tcl_CmdProc *xProc;
        !           629:   } aCmd[] = {
        !           630:      { "btree_open",               (Tcl_CmdProc*)btree_open               },
        !           631:      { "btree_close",              (Tcl_CmdProc*)btree_close              },
        !           632:      { "btree_begin_transaction",  (Tcl_CmdProc*)btree_begin_transaction  },
        !           633:      { "btree_pager_stats",        (Tcl_CmdProc*)btree_pager_stats        },
        !           634:      { "btree_cursor",             (Tcl_CmdProc*)btree_cursor             },
        !           635:      { "btree_close_cursor",       (Tcl_CmdProc*)btree_close_cursor       },
        !           636:      { "btree_next",               (Tcl_CmdProc*)btree_next               },
        !           637:      { "btree_eof",                (Tcl_CmdProc*)btree_eof                },
        !           638:      { "btree_payload_size",       (Tcl_CmdProc*)btree_payload_size       },
        !           639:      { "btree_first",              (Tcl_CmdProc*)btree_first              },
        !           640:      { "btree_varint_test",        (Tcl_CmdProc*)btree_varint_test        },
        !           641:      { "btree_from_db",            (Tcl_CmdProc*)btree_from_db            },
        !           642:      { "btree_ismemdb",            (Tcl_CmdProc*)btree_ismemdb            },
        !           643:      { "btree_set_cache_size",     (Tcl_CmdProc*)btree_set_cache_size     }
        !           644:   };
        !           645:   int i;
        !           646: 
        !           647:   for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){
        !           648:     Tcl_CreateCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0);
        !           649:   }
        !           650: 
        !           651:   return TCL_OK;
        !           652: }

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