wasCSharpSQLite – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 using System.Diagnostics;
2  
3 using i64 = System.Int64;
4 using u32 = System.UInt32;
5  
6 namespace Community.CsharpSqlite
7 {
8 #if TCLSH
9 using tcl.lang;
10 using Tcl_CmdProc = tcl.lang.Interp.dxObjCmdProc;
11 using Tcl_Interp = tcl.lang.Interp;
12 using System.Text;
13  
14 public partial class Sqlite3
15 {
16 /*
17 ** 2001 September 15
18 **
19 ** The author disclaims copyright to this source code. In place of
20 ** a legal notice, here is a blessing:
21 **
22 ** May you do good and not evil.
23 ** May you find forgiveness for yourself and forgive others.
24 ** May you share freely, never taking more than you give.
25 **
26 *************************************************************************
27 ** Code for testing the btree.c module in SQLite. This code
28 ** is not included in the SQLite library. It is used for automated
29 ** testing of the SQLite library.
30 *************************************************************************
31 ** Included in SQLite3 port to C#-SQLite; 2008 Noah B Hart
32 ** C#-SQLite is an independent reimplementation of the SQLite software library
33 **
34 ** SQLITE_SOURCE_ID: 2011-06-23 19:49:22 4374b7e83ea0a3fbc3691f9c0c936272862f32f2
35 **
36 *************************************************************************
37 */
38 //#include "sqliteInt.h"
39 //#include "btreeInt.h"
40 //#include "tcl.h"
41 //#include <stdlib.h>
42 //#include <string.h>
43  
44 /*
45 ** Interpret an SQLite error number
46 */
47 static string errorName( int rc )
48 {
49 string zName;
50 switch ( rc )
51 {
52 case SQLITE_OK:
53 zName = "SQLITE_OK";
54 break;
55 case SQLITE_ERROR:
56 zName = "SQLITE_ERROR";
57 break;
58 case SQLITE_PERM:
59 zName = "SQLITE_PERM";
60 break;
61 case SQLITE_ABORT:
62 zName = "SQLITE_ABORT";
63 break;
64 case SQLITE_BUSY:
65 zName = "SQLITE_BUSY";
66 break;
67 case SQLITE_NOMEM:
68 zName = "SQLITE_NOMEM";
69 break;
70 case SQLITE_READONLY:
71 zName = "SQLITE_READONLY";
72 break;
73 case SQLITE_INTERRUPT:
74 zName = "SQLITE_INTERRUPT";
75 break;
76 case SQLITE_IOERR:
77 zName = "SQLITE_IOERR";
78 break;
79 case SQLITE_CORRUPT:
80 zName = "SQLITE_CORRUPT";
81 break;
82 case SQLITE_FULL:
83 zName = "SQLITE_FULL";
84 break;
85 case SQLITE_CANTOPEN:
86 zName = "SQLITE_CANTOPEN";
87 break;
88 case SQLITE_PROTOCOL:
89 zName = "SQLITE_PROTOCOL";
90 break;
91 case SQLITE_EMPTY:
92 zName = "SQLITE_EMPTY";
93 break;
94 case SQLITE_LOCKED:
95 zName = "SQLITE_LOCKED";
96 break;
97 default:
98 zName = "SQLITE_Unknown";
99 break;
100 }
101 return zName;
102 }
103  
104 /*
105 ** A bogus sqlite3 connection structure for use in the btree
106 ** tests.
107 */
108 static sqlite3 sDb = new sqlite3();
109 static int nRefSqlite3 = 0;
110  
111 /*
112 ** Usage: btree_open FILENAME NCACHE
113 **
114 ** Open a new database
115 */
116 static int btree_open(
117 object NotUsed,
118 Tcl_Interp interp, /* The TCL interpreter that invoked this command */
119 int argc, /* Number of arguments */
120 TclObject[] argv /* Text of each argument */
121 )
122 {
123 Btree pBt = null;
124 int rc;
125 int nCache = 0;
126 StringBuilder zBuf = new StringBuilder( 100 );
127 if ( argc != 3 )
128 {
129 TCL.Tcl_AppendResult( interp, "wrong # args: should be \"", argv[0].ToString(),
130 " FILENAME NCACHE\"", "" );
131 return TCL.TCL_ERROR;
132 }
133 if ( TCL.Tcl_GetInt( interp, argv[2], out nCache ) )
134 return TCL.TCL_ERROR;
135 nRefSqlite3++;
136 if ( nRefSqlite3 == 1 )
137 {
138 sDb.pVfs = sqlite3_vfs_find( null );
139 sDb.mutex = sqlite3MutexAlloc( SQLITE_MUTEX_RECURSIVE );
140 sqlite3_mutex_enter( sDb.mutex );
141 }
142 rc = sqlite3BtreeOpen( sDb.pVfs, argv[1].ToString(), sDb, ref pBt, 0,
143 SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_MAIN_DB );
144 if ( rc != SQLITE_OK )
145 {
146 TCL.Tcl_AppendResult( interp, errorName( rc ), null );
147 return TCL.TCL_ERROR;
148 }
149 sqlite3BtreeSetCacheSize( pBt, nCache );
150 sqlite3_snprintf( 100, zBuf, "->%p", pBt );
151 if ( TCL.Tcl_CreateCommandPointer( interp, zBuf, pBt ) )
152 {
153 return TCL.TCL_ERROR;
154 }
155 else
156 TCL.Tcl_AppendResult( interp, zBuf, null );
157 return TCL.TCL_OK;
158 }
159  
160 /*
161 ** Usage: btree_close ID
162 **
163 ** Close the given database.
164 */
165 static int btree_close(
166 object NotUsed,
167 Tcl_Interp interp, /* The TCL interpreter that invoked this command */
168 int argc, /* Number of arguments */
169 TclObject[] argv /* Text of each argument */
170 )
171 {
172 Btree pBt;
173 int rc;
174 if ( argc != 2 )
175 {
176 TCL.Tcl_AppendResult( interp, "wrong # args: should be \"", argv[0].ToString(),
177 " ID\"", null );
178 return TCL.TCL_ERROR;
179 }
180 pBt = (Btree)sqlite3TestTextToPtr( interp, argv[1].ToString() );
181 rc = sqlite3BtreeClose( ref pBt );
182 if ( rc != SQLITE_OK )
183 {
184 TCL.Tcl_AppendResult( interp, errorName( rc ), null );
185 return TCL.TCL_ERROR;
186 }
187 nRefSqlite3--;
188 if ( nRefSqlite3 == 0 )
189 {
190 sqlite3_mutex_leave( sDb.mutex );
191 sqlite3_mutex_free( sDb.mutex );
192 sDb.mutex = null;
193 sDb.pVfs = null;
194 }
195 return TCL.TCL_OK;
196 }
197  
198  
199 /*
200 ** Usage: btree_begin_transaction ID
201 **
202 ** Start a new transaction
203 */
204 static int btree_begin_transaction(
205 object NotUsed,
206 Tcl_Interp interp, /* The TCL interpreter that invoked this command */
207 int argc, /* Number of arguments */
208 TclObject[] argv /* Text of each argument */
209 )
210 {
211 Btree pBt;
212 int rc;
213 if ( argc != 2 )
214 {
215 TCL.Tcl_AppendResult( interp, "wrong # args: should be \"", argv[0].ToString(),
216 " ID\"", null );
217 return TCL.TCL_ERROR;
218 }
219 pBt = (Btree)sqlite3TestTextToPtr( interp, argv[1].ToString() );
220 sqlite3BtreeEnter( pBt );
221 rc = sqlite3BtreeBeginTrans( pBt, 1 );
222 sqlite3BtreeLeave( pBt );
223 if ( rc != SQLITE_OK )
224 {
225 TCL.Tcl_AppendResult( interp, errorName( rc ), null );
226 ;
227 return TCL.TCL_ERROR;
228 }
229 return TCL.TCL_OK;
230 }
231  
232 /*
233 ** Usage: btree_pager_stats ID
234 **
235 ** Returns pager statistics
236 */
237 static int btree_pager_stats(
238 object NotUsed,
239 Tcl_Interp interp, /* The TCL interpreter that invoked this command */
240 int argc, /* Number of arguments */
241 TclObject[] argv /* Text of each argument */
242 )
243 {
244 Btree pBt;
245 int i;
246 int[] a;
247  
248 if ( argc != 2 )
249 {
250 TCL.Tcl_AppendResult( interp, "wrong # args: should be \"", argv[0].ToString(),
251 " ID\"" );
252 return TCL.TCL_ERROR;
253 }
254 pBt = (Btree)sqlite3TestTextToPtr( interp, argv[1].ToString() );
255  
256 /* Normally in this file, with a b-tree handle opened using the
257 ** [btree_open] command it is safe to call sqlite3BtreeEnter() directly.
258 ** But this function is sometimes called with a btree handle obtained
259 ** from an open SQLite connection (using [btree_from_db]). In this case
260 ** we need to obtain the mutex for the controlling SQLite handle before
261 ** it is safe to call sqlite3BtreeEnter().
262 */
263 sqlite3_mutex_enter( pBt.db.mutex );
264  
265 sqlite3BtreeEnter( pBt );
266 a = sqlite3PagerStats( sqlite3BtreePager( pBt ) );
267 for ( i = 0; i < 11; i++ )
268 {
269 string[] zName = new string[]{
270 "ref", "page", "max", "size", "state", "err",
271 "hit", "miss", "ovfl", "read", "write"
272 };
273 StringBuilder zBuf = new StringBuilder( 100 );
274 TCL.Tcl_AppendElement( interp, zName[i] );
275 sqlite3_snprintf( 100, zBuf, "%d", a[i] );
276 TCL.Tcl_AppendElement( interp, zBuf );
277 }
278 sqlite3BtreeLeave( pBt );
279 /* Release the mutex on the SQLite handle that controls this b-tree */
280 sqlite3_mutex_leave( pBt.db.mutex );
281 return TCL.TCL_OK;
282 }
283  
284 /*
285 ** Usage: btree_cursor ID TABLENUM WRITEABLE
286 **
287 ** Create a new cursor. Return the ID for the cursor.
288 */
289 static int btree_cursor(
290 object NotUsed,
291 Tcl_Interp interp, /* The TCL interpreter that invoked this command */
292 int argc, /* Number of arguments */
293 TclObject[] argv /* Text of each argument */
294 )
295 {
296 Btree pBt;
297 int iTable = 0;
298 BtCursor pCur;
299 int rc = SQLITE_OK;
300 int wrFlag = 0;
301 StringBuilder zBuf = new StringBuilder( 30 );
302  
303 if ( argc != 4 )
304 {
305 TCL.Tcl_AppendResult( interp, "wrong # args: should be \"", argv[0].ToString(),
306 " ID TABLENUM WRITEABLE\"" );
307 return TCL.TCL_ERROR;
308 }
309 pBt = (Btree)sqlite3TestTextToPtr( interp, argv[1].ToString() );
310 if ( TCL.Tcl_GetInt( interp, argv[2], out iTable ) )
311 return TCL.TCL_ERROR;
312 if ( TCL.Tcl_GetBoolean( interp, argv[3], out wrFlag ) )
313 return TCL.TCL_ERROR;
314 //pCur = (BtCursor )ckalloc(sqlite3BtreeCursorSize());
315 pCur = new BtCursor();// memset( pCur, 0, sqlite3BtreeCursorSize() );
316 sqlite3BtreeEnter( pBt );
317 #if !SQLITE_OMIT_SHARED_CACHE
318 rc = sqlite3BtreeLockTable( pBt, iTable, wrFlag );
319 #endif
320 if ( rc == SQLITE_OK )
321 {
322 rc = sqlite3BtreeCursor( pBt, iTable, wrFlag, null, pCur );
323 }
324 sqlite3BtreeLeave( pBt );
325 if ( rc != 0 )
326 {
327 pCur = null;// ckfree( pCur );
328 TCL.Tcl_AppendResult( interp, errorName( rc ), null );
329 ;
330 return TCL.TCL_ERROR;
331 }
332 sqlite3_snprintf( 30, zBuf, "->%p", pCur );
333 if ( TCL.Tcl_CreateCommandPointer( interp, zBuf, pCur ) )
334 {
335 return TCL.TCL_ERROR;
336 }
337 else
338 TCL.Tcl_AppendResult( interp, zBuf );
339 return SQLITE_OK;
340 }
341  
342 /*
343 ** Usage: btree_close_cursor ID
344 **
345 ** Close a cursor opened using btree_cursor.
346 */
347 static int btree_close_cursor(
348 object NotUsed,
349 Tcl_Interp interp, /* The TCL interpreter that invoked this command */
350 int argc, /* Number of arguments */
351 TclObject[] argv /* Text of each argument */
352 )
353 {
354 BtCursor pCur;
355 Btree pBt;
356 int rc;
357  
358 if ( argc != 2 )
359 {
360 TCL.Tcl_AppendResult( interp, "wrong # args: should be \"", argv[0].ToString(),
361 " ID\"" );
362 return TCL.TCL_ERROR;
363 }
364 pCur = (BtCursor)sqlite3TestTextToPtr( interp, argv[1].ToString() );
365 pBt = pCur.pBtree;
366 sqlite3BtreeEnter( pBt );
367 rc = sqlite3BtreeCloseCursor( pCur );
368 sqlite3BtreeLeave( pBt );
369 pCur = null;//ckfree( (char*)pCur );
370 if ( rc != 0 )
371 {
372 TCL.Tcl_AppendResult( interp, errorName( rc ), null );
373 ;
374 return TCL.TCL_ERROR;
375 }
376 return SQLITE_OK;
377 }
378  
379 /*
380 ** Usage: btree_next ID
381 **
382 ** Move the cursor to the next entry in the table. Return 0 on success
383 ** or 1 if the cursor was already on the last entry in the table or if
384 ** the table is empty.
385 */
386 static int btree_next(
387 object NotUsed,
388 Tcl_Interp interp, /* The TCL interpreter that invoked this command */
389 int argc, /* Number of arguments */
390 TclObject[] argv /* Text of each argument */
391 )
392 {
393 BtCursor pCur;
394 int rc;
395 int res = 0;
396 StringBuilder zBuf = new StringBuilder( 100 );
397  
398 if ( argc != 2 )
399 {
400 TCL.Tcl_AppendResult( interp, "wrong # args: should be \"", argv[0].ToString(),
401 " ID\"" );
402 return TCL.TCL_ERROR;
403 }
404 pCur = (BtCursor)sqlite3TestTextToPtr( interp, argv[1].ToString() );
405 #if SQLITE_TEST
406 sqlite3BtreeEnter( pCur.pBtree );
407 #endif
408 rc = sqlite3BtreeNext( pCur, ref res );
409 #if SQLITE_TEST
410 sqlite3BtreeLeave( pCur.pBtree );
411 #endif
412 if ( rc != 0 )
413 {
414 TCL.Tcl_AppendResult( interp, errorName( rc ), null );
415 ;
416 return TCL.TCL_ERROR;
417 }
418 sqlite3_snprintf( 100, zBuf, "%d", res );
419 TCL.Tcl_AppendResult( interp, zBuf );
420 return SQLITE_OK;
421 }
422  
423 /*
424 ** Usage: btree_first ID
425 **
426 ** Move the cursor to the first entry in the table. Return 0 if the
427 ** cursor was left point to something and 1 if the table is empty.
428 */
429 static int btree_first(
430 object NotUsed,
431 Tcl_Interp interp, /* The TCL interpreter that invoked this command */
432 int argc, /* Number of arguments */
433 TclObject[] argv /* Text of each argument */
434 )
435 {
436 BtCursor pCur;
437 int rc;
438 int res = 0;
439 StringBuilder zBuf = new StringBuilder( 100 );
440  
441 if ( argc != 2 )
442 {
443 TCL.Tcl_AppendResult( interp, "wrong # args: should be \"", argv[0].ToString(),
444 " ID\"" );
445 return TCL.TCL_ERROR;
446 }
447 pCur = (BtCursor)sqlite3TestTextToPtr( interp, argv[1].ToString() );
448 #if SQLITE_TEST
449 sqlite3BtreeEnter( pCur.pBtree );
450 #endif
451 rc = sqlite3BtreeFirst( pCur, ref res );
452 #if SQLITE_TEST
453 sqlite3BtreeLeave( pCur.pBtree );
454 #endif
455 if ( rc != 0 )
456 {
457 TCL.Tcl_AppendResult( interp, errorName( rc ), null );
458 ;
459 return TCL.TCL_ERROR;
460 }
461 sqlite3_snprintf( 100, zBuf, "%d", res );
462 TCL.Tcl_AppendResult( interp, zBuf );
463 return SQLITE_OK;
464 }
465  
466 /*
467 ** Usage: btree_eof ID
468 **
469 ** Return TRUE if the given cursor is not pointing at a valid entry.
470 ** Return FALSE if the cursor does point to a valid entry.
471 */
472 //static int btree_eof(
473 // object NotUsed,
474 // Tcl_Interp interp, /* The TCL interpreter that invoked this command */
475 // int argc, /* Number of arguments */
476 // TclObject[] argv /* Text of each argument */
477 //){
478 // BtCursor pCur;
479 // int rc;
480 // char zBuf[50];
481  
482 // if( argc!=2 ){
483 // TCL.Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0].ToString(),
484 // " ID\"");
485 // return TCL.TCL_ERROR;
486 // }
487 // pCur = (BtCursor)sqlite3TestTextToPtr(interp,argv[1].ToString());
488 // sqlite3BtreeEnter(pCur.pBtree);
489 // rc = sqlite3BtreeEof(pCur);
490 // sqlite3BtreeLeave(pCur.pBtree);
491 // sqlite3_snprintf(100, ref zBuf, "%d", rc);
492 // TCL.Tcl_AppendResult(interp, zBuf);
493 // return SQLITE_OK;
494 //}
495  
496 /*
497 ** Usage: btree_payload_size ID
498 **
499 ** Return the number of bytes of payload
500 */
501 static int btree_payload_size(
502 object NotUsed,
503 Tcl_Interp interp, /* The TCL interpreter that invoked this command */
504 int argc, /* Number of arguments */
505 TclObject[] argv /* Text of each argument */
506 )
507 {
508 BtCursor pCur;
509 i64 n1 = 0;
510 u32 n2 = 0;
511 StringBuilder zBuf = new StringBuilder( 50 );
512  
513 if ( argc != 2 )
514 {
515 TCL.Tcl_AppendResult( interp, "wrong # args: should be \"", argv[0].ToString(),
516 " ID\"" );
517 return TCL.TCL_ERROR;
518 }
519 pCur = (BtCursor)sqlite3TestTextToPtr( interp, argv[1].ToString() );
520 #if SQLITE_TEST
521 sqlite3BtreeEnter( pCur.pBtree );
522 #endif
523  
524 /* The cursor may be in "require-seek" state. If this is the case, the
525 ** call to BtreeDataSize() will fix it. */
526 sqlite3BtreeDataSize( pCur, ref n2 );
527 if ( pCur.apPage[pCur.iPage].intKey != 0 )
528 {
529 n1 = 0;
530 }
531 else
532 {
533 sqlite3BtreeKeySize( pCur, ref n1 );
534 }
535 sqlite3BtreeLeave( pCur.pBtree );
536 sqlite3_snprintf( 30, zBuf, "%d", (int)( n1 + n2 ) );
537 TCL.Tcl_AppendResult( interp, zBuf );
538 return SQLITE_OK;
539 }
540  
541 /*
542 ** usage: varint_test START MULTIPLIER COUNT INCREMENT
543 **
544 ** This command tests the putVarint() and getVarint()
545 ** routines, both for accuracy and for speed.
546 **
547 ** An integer is written using putVarint() and read back with
548 ** getVarint() and varified to be unchanged. This repeats COUNT
549 ** times. The first integer is START*MULTIPLIER. Each iteration
550 ** increases the integer by INCREMENT.
551 **
552 ** This command returns nothing if it works. It returns an error message
553 ** if something goes wrong.
554 */
555 static int btree_varint_test(
556 object NotUsed,
557 Tcl_Interp interp, /* The TCL interpreter that _invoked this command */
558 int argc, /* Number of arguments */
559 TclObject[] argv /* Text of each argument */
560 )
561 {
562 int start = 0, mult = 0, count = 0, incr = 0;
563 int _in;
564 u32 _out = 0;
565 int n1, n2, i, j;
566 byte[] zBuf = new byte[100];
567 if ( argc != 5 )
568 {
569 TCL.Tcl_AppendResult( interp, "wrong # args: should be \"", argv[0].ToString(),
570 " START MULTIPLIER COUNT incrEMENT\"", 0 );
571 return TCL.TCL_ERROR;
572 }
573 if ( TCL.Tcl_GetInt( interp, argv[1], out start ) )
574 return TCL.TCL_ERROR;
575 if ( TCL.Tcl_GetInt( interp, argv[2], out mult ) )
576 return TCL.TCL_ERROR;
577 if ( TCL.Tcl_GetInt( interp, argv[3], out count ) )
578 return TCL.TCL_ERROR;
579 if ( TCL.Tcl_GetInt( interp, argv[4], out incr ) )
580 return TCL.TCL_ERROR;
581 _in = start;
582 _in *= mult;
583 for ( i = 0; i < count; i++ )
584 {
585 StringBuilder zErr = new StringBuilder( 200 );
586 n1 = putVarint( zBuf, 0, _in );
587 if ( n1 > 9 || n1 < 1 )
588 {
589 sqlite3_snprintf( 100, zErr, "putVarint returned %d - should be between 1 and 9", n1 );
590 TCL.Tcl_AppendResult( interp, zErr );
591 return TCL.TCL_ERROR;
592 }
593 n2 = getVarint( zBuf, 0, out _out );
594 if ( n1 != n2 )
595 {
596 sqlite3_snprintf( 100, zErr, "putVarint returned %d and GetVar_int returned %d", n1, n2 );
597 TCL.Tcl_AppendResult( interp, zErr );
598 return TCL.TCL_ERROR;
599 }
600 if ( _in != (int)_out )
601 {
602 sqlite3_snprintf( 100, zErr, "Wrote 0x%016llx and got back 0x%016llx", _in, _out );
603 TCL.Tcl_AppendResult( interp, zErr );
604 return TCL.TCL_ERROR;
605 }
606 if ( ( _in & 0xffffffff ) == _in )
607 {
608 u32 _out32 = 0;
609 n2 = getVarint32( zBuf, out _out32 );
610 _out = _out32;
611 if ( n1 != n2 )
612 {
613 sqlite3_snprintf( 100, zErr, "putVarint returned %d and GetVar_int32 returned %d",
614 n1, n2 );
615 TCL.Tcl_AppendResult( interp, zErr );
616 return TCL.TCL_ERROR;
617 }
618 if ( _in != (int)_out )
619 {
620 sqlite3_snprintf( 100, zErr, "Wrote 0x%016llx and got back 0x%016llx from GetVar_int32",
621 _in, _out );
622 TCL.Tcl_AppendResult( interp, zErr );
623 return TCL.TCL_ERROR;
624 }
625 }
626  
627 /* _in order to get realistic tim_ings, run getVar_int 19 more times.
628 ** This is because getVar_int is called ab_out 20 times more often
629 ** than putVarint.
630 */
631 for ( j = 0; j < 19; j++ )
632 {
633 getVarint( zBuf, 0, out _out );
634 }
635 _in += incr;
636 }
637 return TCL.TCL_OK;
638 }
639  
640 /*
641 ** usage: btree_from_db DB-HANDLE
642 **
643 ** This command returns the btree handle for the main database associated
644 ** with the database-handle passed as the argument. Example usage:
645 **
646 ** sqlite3 db test.db
647 ** set bt [btree_from_db db]
648 */
649 static int btree_from_db(
650 object NotUsed,
651 Tcl_Interp interp, /* The TCL interpreter that invoked this command */
652 int argc, /* Number of arguments */
653 TclObject[] argv /* Text of each argument */
654 )
655 {
656 StringBuilder zBuf = new StringBuilder( 100 );
657 WrappedCommand info = null;
658 sqlite3 db;
659 Btree pBt;
660 int iDb = 0;
661  
662 if ( argc != 2 && argc != 3 )
663 {
664 TCL.Tcl_AppendResult( interp, "wrong # args: should be \"", argv[0].ToString(),
665 " DB-HANDLE ?N?\"" );
666 return TCL.TCL_ERROR;
667 }
668  
669 if ( TCL.Tcl_GetCommandInfo( interp, argv[1].ToString(), out info ) )
670 {
671 TCL.Tcl_AppendResult( interp, "No such db-handle: \"", argv[1], "\"" );
672 return TCL.TCL_ERROR;
673 }
674 if ( argc == 3 )
675 {
676 iDb = atoi( argv[2].ToString() );
677 }
678  
679 db = ( (SqliteDb)info.objClientData ).db;
680 Debug.Assert( db != null );
681  
682 pBt = db.aDb[iDb].pBt;
683 sqlite3_snprintf( 50, zBuf, "->%p", pBt );
684 if ( TCL.Tcl_CreateCommandPointer( interp, zBuf, pBt ) )
685 {
686 return TCL.TCL_ERROR;
687 }
688 else
689 TCL.Tcl_SetResult( interp, zBuf, TCL.TCL_VOLATILE );
690 return TCL.TCL_OK;
691 }
692  
693  
694 /*
695 ** Usage: btree_ismemdb ID
696 **
697 ** Return true if the B-Tree is in-memory.
698 */
699 static int btree_ismemdb(
700 object NotUsed,
701 Tcl_Interp interp, /* The TCL interpreter that invoked this command */
702 int argc, /* Number of arguments */
703 TclObject[] argv /* Text of each argument */
704 )
705 {
706 Btree pBt;
707 int res;
708  
709 if ( argc != 2 )
710 {
711 TCL.Tcl_AppendResult( interp, "wrong # args: should be \"", argv[0],
712 " ID\"" );
713 return TCL.TCL_ERROR;
714 }
715 pBt = (Btree)sqlite3TestTextToPtr( interp, argv[1].ToString() );
716 sqlite3_mutex_enter( pBt.db.mutex );
717 sqlite3BtreeEnter( pBt );
718 res = sqlite3PagerIsMemdb( sqlite3BtreePager( pBt ) ) ? 1 : 0;
719 sqlite3BtreeLeave( pBt );
720 sqlite3_mutex_leave( pBt.db.mutex );
721 TCL.Tcl_SetObjResult( interp, TCL.Tcl_NewBooleanObj( res ) );
722 return TCL.TCL_OK;
723 }
724  
725 /*
726 ** usage: btree_set_cache_size ID NCACHE
727 **
728 ** Set the size of the cache used by btree $ID.
729 */
730 //static int btree_set_cache_size(
731 // object NotUsed,
732 // Tcl_Interp interp, /* The TCL interpreter that invoked this command */
733 // int argc, /* Number of arguments */
734 // TclObject[] argv /* Text of each argument */
735 //){
736 // int nCache;
737 // Btree pBt;
738  
739 // if( argc!=3 ){
740 // TCL.Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0].ToString(),
741 // " BT NCACHE\"");
742 // return TCL.TCL_ERROR;
743 // }
744 // pBt = (Btree)sqlite3TestTextToPtr(interp,argv[1].ToString());
745 // if(TCL.Tcl_GetInt(interp, argv[2], nCache) ) return TCL.TCL_ERROR;
746  
747 // sqlite3_mutex_enter(pBt.db.mutex);
748 // sqlite3BtreeEnter(pBt);
749 // sqlite3BtreeSetCacheSize(pBt, nCache);
750 // sqlite3BtreeLeave(pBt);
751 // sqlite3_mutex_leave(pBt.db.mutex);
752  
753 // return TCL.TCL_OK;
754 //}
755  
756  
757 /*
758 ** Register commands with the TCL interpreter.
759 */
760 public class _aCmd
761 {
762 public string zName;
763 public Tcl_CmdProc xProc;
764  
765 public _aCmd( string zName, Tcl_CmdProc xProc )
766 {
767 this.zName = zName;
768 this.xProc = xProc;
769 }
770 }
771  
772  
773 public static int Sqlitetest3_Init( Tcl_Interp interp )
774 {
775 _aCmd[] aCmd = new _aCmd[] {
776 new _aCmd( "btree_open", (Tcl_CmdProc)btree_open ),
777 new _aCmd( "btree_close", (Tcl_CmdProc)btree_close ),
778 new _aCmd( "btree_begin_transaction", (Tcl_CmdProc)btree_begin_transaction ),
779 new _aCmd( "btree_pager_stats", (Tcl_CmdProc)btree_pager_stats ),
780 new _aCmd( "btree_cursor", (Tcl_CmdProc)btree_cursor ),
781 new _aCmd( "btree_close_cursor", (Tcl_CmdProc)btree_close_cursor ),
782 new _aCmd( "btree_next", (Tcl_CmdProc)btree_next ),
783 //new _aCmd( "btree_eof", (Tcl_CmdProc)btree_eof ),
784 new _aCmd( "btree_payload_size", (Tcl_CmdProc)btree_payload_size ),
785 new _aCmd( "btree_first", (Tcl_CmdProc)btree_first ),
786 new _aCmd( "btree_varint_test", (Tcl_CmdProc)btree_varint_test ),
787 new _aCmd( "btree_from_db", (Tcl_CmdProc)btree_from_db ),
788 new _aCmd( "btree_ismemdb", (Tcl_CmdProc)btree_ismemdb ),
789 //new _aCmd( "btree_set_cache_size", (Tcl_CmdProc)btree_set_cache_size ),
790 };
791 int i;
792  
793 for ( i = 0; i < aCmd.Length; i++ )
794 { //sizeof(aCmd)/sizeof(aCmd[0]); i++){
795 TCL.Tcl_CreateCommand( interp, aCmd[i].zName, aCmd[i].xProc, null, null );
796 }
797  
798 return TCL.TCL_OK;
799 }
800 }
801 #endif
802 }