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>