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