test3.c 17 KB

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