blob: 9dd084105d3090257cd81d5797e989de5476742b [file] [log] [blame]
drh5c4d9702001-08-20 00:33:58 +00001/*
drhb19a2bc2001-09-16 00:13:26 +00002** 2001 September 15
drh5c4d9702001-08-20 00:33:58 +00003**
drhb19a2bc2001-09-16 00:13:26 +00004** The author disclaims copyright to this source code. In place of
5** a legal notice, here is a blessing:
drh5c4d9702001-08-20 00:33:58 +00006**
drhb19a2bc2001-09-16 00:13:26 +00007** 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.
drh5c4d9702001-08-20 00:33:58 +000010**
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**
drhb19a2bc2001-09-16 00:13:26 +000016** $Id: test3.c,v 1.11 2001/09/16 00:13:27 drh Exp $
drh5c4d9702001-08-20 00:33:58 +000017*/
18#include "sqliteInt.h"
19#include "pager.h"
20#include "btree.h"
21#include "tcl.h"
22#include <stdlib.h>
23#include <string.h>
24
25/*
26** Interpret an SQLite error number
27*/
28static char *errorName(int rc){
29 char *zName;
30 switch( rc ){
31 case SQLITE_OK: zName = "SQLITE_OK"; break;
32 case SQLITE_ERROR: zName = "SQLITE_ERROR"; break;
33 case SQLITE_INTERNAL: zName = "SQLITE_INTERNAL"; break;
34 case SQLITE_PERM: zName = "SQLITE_PERM"; break;
35 case SQLITE_ABORT: zName = "SQLITE_ABORT"; break;
36 case SQLITE_BUSY: zName = "SQLITE_BUSY"; break;
37 case SQLITE_NOMEM: zName = "SQLITE_NOMEM"; break;
38 case SQLITE_READONLY: zName = "SQLITE_READONLY"; break;
39 case SQLITE_INTERRUPT: zName = "SQLITE_INTERRUPT"; break;
40 case SQLITE_IOERR: zName = "SQLITE_IOERR"; break;
41 case SQLITE_CORRUPT: zName = "SQLITE_CORRUPT"; break;
42 case SQLITE_NOTFOUND: zName = "SQLITE_NOTFOUND"; break;
43 case SQLITE_FULL: zName = "SQLITE_FULL"; break;
44 case SQLITE_CANTOPEN: zName = "SQLITE_CANTOPEN"; break;
45 case SQLITE_PROTOCOL: zName = "SQLITE_PROTOCOL"; break;
46 default: zName = "SQLITE_Unknown"; break;
47 }
48 return zName;
49}
50
51/*
52** Usage: btree_open FILENAME
53**
54** Open a new database
55*/
56static int btree_open(
57 void *NotUsed,
58 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
59 int argc, /* Number of arguments */
60 char **argv /* Text of each argument */
61){
62 Btree *pBt;
63 int rc;
64 char zBuf[100];
65 if( argc!=2 ){
66 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
67 " FILENAME\"", 0);
68 return TCL_ERROR;
69 }
70 rc = sqliteBtreeOpen(argv[1], 0666, 10, &pBt);
71 if( rc!=SQLITE_OK ){
72 Tcl_AppendResult(interp, errorName(rc), 0);
73 return TCL_ERROR;
74 }
75 sprintf(zBuf,"0x%x",(int)pBt);
76 Tcl_AppendResult(interp, zBuf, 0);
77 return TCL_OK;
78}
79
80/*
81** Usage: btree_close ID
82**
83** Close the given database.
84*/
85static int btree_close(
86 void *NotUsed,
87 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
88 int argc, /* Number of arguments */
89 char **argv /* Text of each argument */
90){
91 Btree *pBt;
92 int rc;
93 if( argc!=2 ){
94 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
95 " ID\"", 0);
96 return TCL_ERROR;
97 }
98 if( Tcl_GetInt(interp, argv[1], (int*)&pBt) ) return TCL_ERROR;
99 rc = sqliteBtreeClose(pBt);
100 if( rc!=SQLITE_OK ){
101 Tcl_AppendResult(interp, errorName(rc), 0);
102 return TCL_ERROR;
103 }
104 return TCL_OK;
105}
106
107/*
108** Usage: btree_begin_transaction ID
109**
110** Start a new transaction
111*/
112static int btree_begin_transaction(
113 void *NotUsed,
114 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
115 int argc, /* Number of arguments */
116 char **argv /* Text of each argument */
117){
118 Btree *pBt;
119 int rc;
120 if( argc!=2 ){
121 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
122 " ID\"", 0);
123 return TCL_ERROR;
124 }
125 if( Tcl_GetInt(interp, argv[1], (int*)&pBt) ) return TCL_ERROR;
126 rc = sqliteBtreeBeginTrans(pBt);
127 if( rc!=SQLITE_OK ){
128 Tcl_AppendResult(interp, errorName(rc), 0);
129 return TCL_ERROR;
130 }
131 return TCL_OK;
132}
133
134/*
135** Usage: btree_rollback ID
136**
137** Rollback changes
138*/
139static int btree_rollback(
140 void *NotUsed,
141 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
142 int argc, /* Number of arguments */
143 char **argv /* Text of each argument */
144){
145 Btree *pBt;
146 int rc;
147 if( argc!=2 ){
148 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
149 " ID\"", 0);
150 return TCL_ERROR;
151 }
152 if( Tcl_GetInt(interp, argv[1], (int*)&pBt) ) return TCL_ERROR;
153 rc = sqliteBtreeRollback(pBt);
154 if( rc!=SQLITE_OK ){
155 Tcl_AppendResult(interp, errorName(rc), 0);
156 return TCL_ERROR;
157 }
158 return TCL_OK;
159}
160
161/*
162** Usage: btree_commit ID
163**
164** Commit all changes
165*/
166static int btree_commit(
167 void *NotUsed,
168 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
169 int argc, /* Number of arguments */
170 char **argv /* Text of each argument */
171){
172 Btree *pBt;
173 int rc;
174 if( argc!=2 ){
175 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
176 " ID\"", 0);
177 return TCL_ERROR;
178 }
179 if( Tcl_GetInt(interp, argv[1], (int*)&pBt) ) return TCL_ERROR;
180 rc = sqliteBtreeCommit(pBt);
181 if( rc!=SQLITE_OK ){
182 Tcl_AppendResult(interp, errorName(rc), 0);
183 return TCL_ERROR;
184 }
185 return TCL_OK;
186}
187
188/*
189** Usage: btree_create_table ID
190**
191** Create a new table in the database
192*/
193static int btree_create_table(
194 void *NotUsed,
195 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
196 int argc, /* Number of arguments */
197 char **argv /* Text of each argument */
198){
199 Btree *pBt;
200 int rc, iTable;
201 char zBuf[30];
202 if( argc!=2 ){
203 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
204 " ID\"", 0);
205 return TCL_ERROR;
206 }
207 if( Tcl_GetInt(interp, argv[1], (int*)&pBt) ) return TCL_ERROR;
208 rc = sqliteBtreeCreateTable(pBt, &iTable);
209 if( rc!=SQLITE_OK ){
210 Tcl_AppendResult(interp, errorName(rc), 0);
211 return TCL_ERROR;
212 }
213 sprintf(zBuf, "%d", iTable);
214 Tcl_AppendResult(interp, zBuf, 0);
215 return TCL_OK;
216}
217
218/*
219** Usage: btree_drop_table ID TABLENUM
220**
221** Delete an entire table from the database
222*/
223static int btree_drop_table(
224 void *NotUsed,
225 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
226 int argc, /* Number of arguments */
227 char **argv /* Text of each argument */
228){
229 Btree *pBt;
230 int iTable;
231 int rc;
232 if( argc!=3 ){
233 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
234 " ID TABLENUM\"", 0);
235 return TCL_ERROR;
236 }
237 if( Tcl_GetInt(interp, argv[1], (int*)&pBt) ) return TCL_ERROR;
238 if( Tcl_GetInt(interp, argv[2], &iTable) ) return TCL_ERROR;
239 rc = sqliteBtreeDropTable(pBt, iTable);
240 if( rc!=SQLITE_OK ){
241 Tcl_AppendResult(interp, errorName(rc), 0);
242 return TCL_ERROR;
243 }
244 return TCL_OK;
245}
246
247/*
248** Usage: btree_clear_table ID TABLENUM
249**
250** Remove all entries from the given table but keep the table around.
251*/
252static int btree_clear_table(
253 void *NotUsed,
254 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
255 int argc, /* Number of arguments */
256 char **argv /* Text of each argument */
257){
258 Btree *pBt;
259 int iTable;
260 int rc;
261 if( argc!=3 ){
262 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
263 " ID TABLENUM\"", 0);
264 return TCL_ERROR;
265 }
266 if( Tcl_GetInt(interp, argv[1], (int*)&pBt) ) return TCL_ERROR;
267 if( Tcl_GetInt(interp, argv[2], &iTable) ) return TCL_ERROR;
268 rc = sqliteBtreeClearTable(pBt, iTable);
269 if( rc!=SQLITE_OK ){
270 Tcl_AppendResult(interp, errorName(rc), 0);
271 return TCL_ERROR;
272 }
273 return TCL_OK;
274}
275
276/*
277** Usage: btree_get_meta ID
278**
279** Return meta data
280*/
281static int btree_get_meta(
282 void *NotUsed,
283 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
284 int argc, /* Number of arguments */
285 char **argv /* Text of each argument */
286){
287 Btree *pBt;
288 int rc;
289 int i;
290 int aMeta[SQLITE_N_BTREE_META];
291 if( argc!=2 ){
292 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
293 " ID\"", 0);
294 return TCL_ERROR;
295 }
296 if( Tcl_GetInt(interp, argv[1], (int*)&pBt) ) return TCL_ERROR;
297 rc = sqliteBtreeGetMeta(pBt, aMeta);
298 if( rc!=SQLITE_OK ){
299 Tcl_AppendResult(interp, errorName(rc), 0);
300 return TCL_ERROR;
301 }
302 for(i=0; i<SQLITE_N_BTREE_META; i++){
303 char zBuf[30];
304 sprintf(zBuf,"%d",aMeta[i]);
305 Tcl_AppendElement(interp, zBuf);
306 }
307 return TCL_OK;
308}
309
310/*
311** Usage: btree_update_meta ID METADATA...
312**
313** Return meta data
314*/
315static int btree_update_meta(
316 void *NotUsed,
317 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
318 int argc, /* Number of arguments */
319 char **argv /* Text of each argument */
320){
321 Btree *pBt;
322 int rc;
323 int i;
324 int aMeta[SQLITE_N_BTREE_META];
325
326 if( argc!=2+SQLITE_N_BTREE_META ){
327 char zBuf[30];
328 sprintf(zBuf,"%d",SQLITE_N_BTREE_META);
329 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
330 " ID METADATA...\" (METADATA is ", zBuf, " integers)", 0);
331 return TCL_ERROR;
332 }
333 if( Tcl_GetInt(interp, argv[1], (int*)&pBt) ) return TCL_ERROR;
334 for(i=0; i<SQLITE_N_BTREE_META; i++){
335 if( Tcl_GetInt(interp, argv[i+2], &aMeta[i]) ) return TCL_ERROR;
336 }
337 rc = sqliteBtreeUpdateMeta(pBt, aMeta);
338 if( rc!=SQLITE_OK ){
339 Tcl_AppendResult(interp, errorName(rc), 0);
340 return TCL_ERROR;
341 }
342 return TCL_OK;
343}
344
345/*
346** Usage: btree_page_dump ID PAGENUM
347**
348** Print a disassembly of a page on standard output
349*/
350static int btree_page_dump(
351 void *NotUsed,
352 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
353 int argc, /* Number of arguments */
354 char **argv /* Text of each argument */
355){
356 Btree *pBt;
357 int iPage;
358 int rc;
359
360 if( argc!=3 ){
361 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
362 " ID\"", 0);
363 return TCL_ERROR;
364 }
365 if( Tcl_GetInt(interp, argv[1], (int*)&pBt) ) return TCL_ERROR;
366 if( Tcl_GetInt(interp, argv[2], &iPage) ) return TCL_ERROR;
367 rc = sqliteBtreePageDump(pBt, iPage, 0);
368 if( rc!=SQLITE_OK ){
369 Tcl_AppendResult(interp, errorName(rc), 0);
370 return TCL_ERROR;
371 }
372 return TCL_OK;
373}
374
375/*
376** Usage: btree_tree_dump ID PAGENUM
377**
378** Print a disassembly of a page and all its child pages on standard output
379*/
380static int btree_tree_dump(
381 void *NotUsed,
382 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
383 int argc, /* Number of arguments */
384 char **argv /* Text of each argument */
385){
386 Btree *pBt;
387 int iPage;
388 int rc;
389
390 if( argc!=3 ){
391 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
392 " ID\"", 0);
393 return TCL_ERROR;
394 }
395 if( Tcl_GetInt(interp, argv[1], (int*)&pBt) ) return TCL_ERROR;
396 if( Tcl_GetInt(interp, argv[2], &iPage) ) return TCL_ERROR;
397 rc = sqliteBtreePageDump(pBt, iPage, 1);
398 if( rc!=SQLITE_OK ){
399 Tcl_AppendResult(interp, errorName(rc), 0);
400 return TCL_ERROR;
401 }
402 return TCL_OK;
403}
404
405/*
406** Usage: btree_pager_stats ID
407**
408** Returns pager statistics
409*/
410static int btree_pager_stats(
411 void *NotUsed,
412 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
413 int argc, /* Number of arguments */
414 char **argv /* Text of each argument */
415){
416 Btree *pBt;
417 int i;
418 int *a;
419
420 if( argc!=2 ){
421 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
422 " ID\"", 0);
423 return TCL_ERROR;
424 }
425 if( Tcl_GetInt(interp, argv[1], (int*)&pBt) ) return TCL_ERROR;
426 a = sqlitepager_stats(sqliteBtreePager(pBt));
427 for(i=0; i<9; i++){
428 static char *zName[] = {
429 "ref", "page", "max", "size", "state", "err",
430 "hit", "miss", "ovfl",
431 };
432 char zBuf[100];
433 Tcl_AppendElement(interp, zName[i]);
434 sprintf(zBuf,"%d",a[i]);
435 Tcl_AppendElement(interp, zBuf);
436 }
437 return TCL_OK;
438}
439
440/*
441** Usage: btree_pager_ref_dump ID
442**
443** Print out all outstanding pages.
444*/
445static int btree_pager_ref_dump(
446 void *NotUsed,
447 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
448 int argc, /* Number of arguments */
449 char **argv /* Text of each argument */
450){
451 Btree *pBt;
452
453 if( argc!=2 ){
454 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
455 " ID\"", 0);
456 return TCL_ERROR;
457 }
458 if( Tcl_GetInt(interp, argv[1], (int*)&pBt) ) return TCL_ERROR;
459 sqlitepager_refdump(sqliteBtreePager(pBt));
460 return TCL_OK;
461}
462
463/*
464** Usage: btree_sanity_check ID ROOT ...
465**
466** Look through every page of the given BTree file to verify correct
467** formatting and linkage. Return a line of text for each problem found.
468** Return an empty string if everything worked.
469*/
470static int btree_sanity_check(
471 void *NotUsed,
472 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
473 int argc, /* Number of arguments */
474 char **argv /* Text of each argument */
475){
476 Btree *pBt;
477 char *zResult;
478 int nRoot;
479 int *aRoot;
480 int i;
481
482 if( argc<3 ){
483 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
484 " ID ROOT ...\"", 0);
485 return TCL_ERROR;
486 }
487 if( Tcl_GetInt(interp, argv[1], (int*)&pBt) ) return TCL_ERROR;
488 nRoot = argc-2;
489 aRoot = malloc( sizeof(int)*(argc-2) );
490 for(i=0; i<argc-2; i++){
491 if( Tcl_GetInt(interp, argv[i+2], &aRoot[i]) ) return TCL_ERROR;
492 }
493 zResult = sqliteBtreeSanityCheck(pBt, aRoot, nRoot);
494 if( zResult ){
495 Tcl_AppendResult(interp, zResult, 0);
496 free(zResult);
497 }
498 return TCL_OK;
499}
500
501/*
502** Usage: btree_cursor ID TABLENUM
503**
504** Create a new cursor. Return the ID for the cursor.
505*/
506static int btree_cursor(
507 void *NotUsed,
508 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
509 int argc, /* Number of arguments */
510 char **argv /* Text of each argument */
511){
512 Btree *pBt;
513 int iTable;
514 BtCursor *pCur;
515 int rc;
516 char zBuf[30];
517
518 if( argc!=3 ){
519 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
520 " ID TABLENUM\"", 0);
521 return TCL_ERROR;
522 }
523 if( Tcl_GetInt(interp, argv[1], (int*)&pBt) ) return TCL_ERROR;
524 if( Tcl_GetInt(interp, argv[2], &iTable) ) return TCL_ERROR;
525 rc = sqliteBtreeCursor(pBt, iTable, &pCur);
526 if( rc ){
527 Tcl_AppendResult(interp, errorName(rc), 0);
528 return TCL_ERROR;
529 }
530 sprintf(zBuf,"0x%x", (int)pCur);
531 Tcl_AppendResult(interp, zBuf, 0);
532 return SQLITE_OK;
533}
534
535/*
536** Usage: btree_close_cursor ID
537**
538** Close a cursor opened using btree_cursor.
539*/
540static int btree_close_cursor(
541 void *NotUsed,
542 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
543 int argc, /* Number of arguments */
544 char **argv /* Text of each argument */
545){
546 BtCursor *pCur;
547 int rc;
548
549 if( argc!=2 ){
550 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
551 " ID\"", 0);
552 return TCL_ERROR;
553 }
554 if( Tcl_GetInt(interp, argv[1], (int*)&pCur) ) return TCL_ERROR;
555 rc = sqliteBtreeCloseCursor(pCur);
556 if( rc ){
557 Tcl_AppendResult(interp, errorName(rc), 0);
558 return TCL_ERROR;
559 }
560 return SQLITE_OK;
561}
562
563/*
564** Usage: btree_move_to ID KEY
565**
566** Move the cursor to the entry with the given key.
567*/
568static int btree_move_to(
569 void *NotUsed,
570 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
571 int argc, /* Number of arguments */
572 char **argv /* Text of each argument */
573){
574 BtCursor *pCur;
575 int rc;
576 int res;
577 char zBuf[20];
578
579 if( argc!=3 ){
580 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
581 " ID KEY\"", 0);
582 return TCL_ERROR;
583 }
584 if( Tcl_GetInt(interp, argv[1], (int*)&pCur) ) return TCL_ERROR;
585 rc = sqliteBtreeMoveto(pCur, argv[2], strlen(argv[2]), &res);
586 if( rc ){
587 Tcl_AppendResult(interp, errorName(rc), 0);
588 return TCL_ERROR;
589 }
590 sprintf(zBuf,"%d",res);
591 Tcl_AppendResult(interp, zBuf, 0);
592 return SQLITE_OK;
593}
594
595/*
596** Usage: btree_delete ID
597**
598** Delete the entry that the cursor is pointing to
599*/
600static int btree_delete(
601 void *NotUsed,
602 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
603 int argc, /* Number of arguments */
604 char **argv /* Text of each argument */
605){
606 BtCursor *pCur;
607 int rc;
608
609 if( argc!=2 ){
610 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
611 " ID\"", 0);
612 return TCL_ERROR;
613 }
614 if( Tcl_GetInt(interp, argv[1], (int*)&pCur) ) return TCL_ERROR;
615 rc = sqliteBtreeDelete(pCur);
616 if( rc ){
617 Tcl_AppendResult(interp, errorName(rc), 0);
618 return TCL_ERROR;
619 }
620 return SQLITE_OK;
621}
622
623/*
624** Usage: btree_insert ID KEY DATA
625**
626** Create a new entry with the given key and data. If an entry already
627** exists with the same key the old entry is overwritten.
628*/
629static int btree_insert(
630 void *NotUsed,
631 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
632 int argc, /* Number of arguments */
633 char **argv /* Text of each argument */
634){
635 BtCursor *pCur;
636 int rc;
637
638 if( argc!=4 ){
639 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
640 " ID KEY DATA\"", 0);
641 return TCL_ERROR;
642 }
643 if( Tcl_GetInt(interp, argv[1], (int*)&pCur) ) return TCL_ERROR;
644 rc = sqliteBtreeInsert(pCur, argv[2], strlen(argv[2]),
645 argv[3], strlen(argv[3]));
646 if( rc ){
647 Tcl_AppendResult(interp, errorName(rc), 0);
648 return TCL_ERROR;
649 }
650 return SQLITE_OK;
651}
652
653/*
654** Usage: btree_next ID
655**
656** Move the cursor to the next entry in the table.
657*/
658static int btree_next(
659 void *NotUsed,
660 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
661 int argc, /* Number of arguments */
662 char **argv /* Text of each argument */
663){
664 BtCursor *pCur;
665 int rc;
666
667 if( argc!=2 ){
668 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
669 " ID\"", 0);
670 return TCL_ERROR;
671 }
672 if( Tcl_GetInt(interp, argv[1], (int*)&pCur) ) return TCL_ERROR;
673 rc = sqliteBtreeNext(pCur, 0);
674 if( rc ){
675 Tcl_AppendResult(interp, errorName(rc), 0);
676 return TCL_ERROR;
677 }
678 return SQLITE_OK;
679}
680
681/*
682** Usage: btree_key ID
683**
684** Return the key for the entry at which the cursor is pointing.
685*/
686static int btree_key(
687 void *NotUsed,
688 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
689 int argc, /* Number of arguments */
690 char **argv /* Text of each argument */
691){
692 BtCursor *pCur;
693 int rc;
694 int n;
695 char *zBuf;
696
697 if( argc!=2 ){
698 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
699 " ID\"", 0);
700 return TCL_ERROR;
701 }
702 if( Tcl_GetInt(interp, argv[1], (int*)&pCur) ) return TCL_ERROR;
703 sqliteBtreeKeySize(pCur, &n);
704 zBuf = malloc( n+1 );
705 rc = sqliteBtreeKey(pCur, 0, n, zBuf);
drh5edc3122001-09-13 21:53:09 +0000706 if( rc!=n ){
707 char zMsg[100];
drh5c4d9702001-08-20 00:33:58 +0000708 free(zBuf);
drh5edc3122001-09-13 21:53:09 +0000709 sprintf(zMsg, "truncated key: got %d of %d bytes", rc, n);
710 Tcl_AppendResult(interp, zMsg, 0);
drh5c4d9702001-08-20 00:33:58 +0000711 return TCL_ERROR;
712 }
713 zBuf[n] = 0;
714 Tcl_AppendResult(interp, zBuf, 0);
715 free(zBuf);
716 return SQLITE_OK;
717}
718
719/*
720** Usage: btree_data ID
721**
722** Return the data for the entry at which the cursor is pointing.
723*/
724static int btree_data(
725 void *NotUsed,
726 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
727 int argc, /* Number of arguments */
728 char **argv /* Text of each argument */
729){
730 BtCursor *pCur;
731 int rc;
732 int n;
733 char *zBuf;
734
735 if( argc!=2 ){
736 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
737 " ID\"", 0);
738 return TCL_ERROR;
739 }
740 if( Tcl_GetInt(interp, argv[1], (int*)&pCur) ) return TCL_ERROR;
741 sqliteBtreeDataSize(pCur, &n);
742 zBuf = malloc( n+1 );
743 rc = sqliteBtreeData(pCur, 0, n, zBuf);
drh5edc3122001-09-13 21:53:09 +0000744 if( rc!=n ){
745 char zMsg[100];
drh5c4d9702001-08-20 00:33:58 +0000746 free(zBuf);
drh5edc3122001-09-13 21:53:09 +0000747 sprintf(zMsg, "truncated data: got %d of %d bytes", rc, n);
748 Tcl_AppendResult(interp, zMsg, 0);
drh5c4d9702001-08-20 00:33:58 +0000749 return TCL_ERROR;
750 }
751 zBuf[n] = 0;
752 Tcl_AppendResult(interp, zBuf, 0);
753 free(zBuf);
754 return SQLITE_OK;
755}
756
757/*
758** Usage: btree_cursor_dump ID
759**
760** Return eight integers containing information about the entry the
761** cursor is pointing to:
762**
763** aResult[0] = The page number
764** aResult[1] = The entry number
765** aResult[2] = Total number of entries on this page
766** aResult[3] = Size of this entry
767** aResult[4] = Number of free bytes on this page
768** aResult[5] = Number of free blocks on the page
769** aResult[6] = Page number of the left child of this entry
770** aResult[7] = Page number of the right child for the whole page
771*/
772static int btree_cursor_dump(
773 void *NotUsed,
774 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
775 int argc, /* Number of arguments */
776 char **argv /* Text of each argument */
777){
778 BtCursor *pCur;
779 int rc;
780 int i, j;
781 int aResult[8];
782 char zBuf[400];
783
784 if( argc!=2 ){
785 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
786 " ID\"", 0);
787 return TCL_ERROR;
788 }
789 if( Tcl_GetInt(interp, argv[1], (int*)&pCur) ) return TCL_ERROR;
790 rc = sqliteBtreeCursorDump(pCur, aResult);
791 if( rc ){
792 Tcl_AppendResult(interp, errorName(rc), 0);
793 return TCL_ERROR;
794 }
795 j = 0;
796 for(i=0; i<sizeof(aResult)/sizeof(aResult[0]); i++){
797 sprintf(&zBuf[j]," %d", aResult[i]);
798 j += strlen(&zBuf[j]);
799 }
800 Tcl_AppendResult(interp, &zBuf[1], 0);
801 return SQLITE_OK;
802}
803
804/*
805** Register commands with the TCL interpreter.
806*/
807int Sqlitetest3_Init(Tcl_Interp *interp){
808 Tcl_CreateCommand(interp, "btree_open", btree_open, 0, 0);
809 Tcl_CreateCommand(interp, "btree_close", btree_close, 0, 0);
810 Tcl_CreateCommand(interp, "btree_begin_transaction",
811 btree_begin_transaction, 0, 0);
812 Tcl_CreateCommand(interp, "btree_commit", btree_commit, 0, 0);
813 Tcl_CreateCommand(interp, "btree_rollback", btree_rollback, 0, 0);
814 Tcl_CreateCommand(interp, "btree_create_table", btree_create_table, 0, 0);
815 Tcl_CreateCommand(interp, "btree_drop_table", btree_drop_table, 0, 0);
816 Tcl_CreateCommand(interp, "btree_clear_table", btree_clear_table, 0, 0);
817 Tcl_CreateCommand(interp, "btree_get_meta", btree_get_meta, 0, 0);
818 Tcl_CreateCommand(interp, "btree_update_meta", btree_update_meta, 0, 0);
819 Tcl_CreateCommand(interp, "btree_page_dump", btree_page_dump, 0, 0);
820 Tcl_CreateCommand(interp, "btree_tree_dump", btree_tree_dump, 0, 0);
821 Tcl_CreateCommand(interp, "btree_pager_stats", btree_pager_stats, 0, 0);
822 Tcl_CreateCommand(interp, "btree_pager_ref_dump", btree_pager_ref_dump, 0, 0);
823 Tcl_CreateCommand(interp, "btree_cursor", btree_cursor, 0, 0);
824 Tcl_CreateCommand(interp, "btree_close_cursor", btree_close_cursor, 0, 0);
825 Tcl_CreateCommand(interp, "btree_move_to", btree_move_to, 0, 0);
826 Tcl_CreateCommand(interp, "btree_delete", btree_delete, 0, 0);
827 Tcl_CreateCommand(interp, "btree_insert", btree_insert, 0, 0);
828 Tcl_CreateCommand(interp, "btree_next", btree_next, 0, 0);
829 Tcl_CreateCommand(interp, "btree_key", btree_key, 0, 0);
830 Tcl_CreateCommand(interp, "btree_data", btree_data, 0, 0);
831 Tcl_CreateCommand(interp, "btree_cursor_dump", btree_cursor_dump, 0, 0);
832 Tcl_CreateCommand(interp, "btree_sanity_check", btree_sanity_check, 0, 0);
833 Tcl_LinkVar(interp, "pager_refinfo_enable", (char*)&pager_refinfo_enable,
834 TCL_LINK_INT);
835 return TCL_OK;
836}