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