aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/sqlite/unix/sqlite-3.5.1/src/test3.c
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/sqlite/unix/sqlite-3.5.1/src/test3.c')
-rw-r--r--libraries/sqlite/unix/sqlite-3.5.1/src/test3.c1670
1 files changed, 1670 insertions, 0 deletions
diff --git a/libraries/sqlite/unix/sqlite-3.5.1/src/test3.c b/libraries/sqlite/unix/sqlite-3.5.1/src/test3.c
new file mode 100644
index 0000000..4f14330
--- /dev/null
+++ b/libraries/sqlite/unix/sqlite-3.5.1/src/test3.c
@@ -0,0 +1,1670 @@
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** $Id: test3.c,v 1.87 2007/09/12 17:01:45 danielk1977 Exp $
17*/
18#include "sqliteInt.h"
19#include "btreeInt.h"
20#include "tcl.h"
21#include <stdlib.h>
22#include <string.h>
23
24/*
25** Interpret an SQLite error number
26*/
27static char *errorName(int rc){
28 char *zName;
29 switch( rc ){
30 case SQLITE_OK: zName = "SQLITE_OK"; break;
31 case SQLITE_ERROR: zName = "SQLITE_ERROR"; break;
32 case SQLITE_PERM: zName = "SQLITE_PERM"; break;
33 case SQLITE_ABORT: zName = "SQLITE_ABORT"; break;
34 case SQLITE_BUSY: zName = "SQLITE_BUSY"; break;
35 case SQLITE_NOMEM: zName = "SQLITE_NOMEM"; break;
36 case SQLITE_READONLY: zName = "SQLITE_READONLY"; break;
37 case SQLITE_INTERRUPT: zName = "SQLITE_INTERRUPT"; break;
38 case SQLITE_IOERR: zName = "SQLITE_IOERR"; break;
39 case SQLITE_CORRUPT: zName = "SQLITE_CORRUPT"; break;
40 case SQLITE_FULL: zName = "SQLITE_FULL"; break;
41 case SQLITE_CANTOPEN: zName = "SQLITE_CANTOPEN"; break;
42 case SQLITE_PROTOCOL: zName = "SQLITE_PROTOCOL"; break;
43 case SQLITE_EMPTY: zName = "SQLITE_EMPTY"; break;
44 case SQLITE_LOCKED: zName = "SQLITE_LOCKED"; break;
45 default: zName = "SQLITE_Unknown"; break;
46 }
47 return zName;
48}
49
50/*
51** A bogus sqlite3 connection structure for use in the btree
52** tests.
53*/
54static sqlite3 sDb;
55static int nRefSqlite3 = 0;
56
57/*
58** Usage: btree_open FILENAME NCACHE FLAGS
59**
60** Open a new database
61*/
62static int btree_open(
63 void *NotUsed,
64 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
65 int argc, /* Number of arguments */
66 const char **argv /* Text of each argument */
67){
68 Btree *pBt;
69 int rc, nCache, flags;
70 char zBuf[100];
71 if( argc!=4 ){
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 if( Tcl_GetInt(interp, argv[3], &flags) ) return TCL_ERROR;
78 nRefSqlite3++;
79 if( nRefSqlite3==1 ){
80 sDb.pVfs = sqlite3_vfs_find(0);
81 sDb.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_RECURSIVE);
82 sqlite3_mutex_enter(sDb.mutex);
83 }
84 rc = sqlite3BtreeOpen(argv[1], &sDb, &pBt, flags,
85 SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_MAIN_DB);
86 if( rc!=SQLITE_OK ){
87 Tcl_AppendResult(interp, errorName(rc), 0);
88 return TCL_ERROR;
89 }
90 sqlite3BtreeSetCacheSize(pBt, nCache);
91 sqlite3_snprintf(sizeof(zBuf), zBuf,"%p", pBt);
92 Tcl_AppendResult(interp, zBuf, 0);
93 return TCL_OK;
94}
95
96/*
97** Usage: btree_close ID
98**
99** Close the given database.
100*/
101static int btree_close(
102 void *NotUsed,
103 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
104 int argc, /* Number of arguments */
105 const char **argv /* Text of each argument */
106){
107 Btree *pBt;
108 int rc;
109 if( argc!=2 ){
110 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
111 " ID\"", 0);
112 return TCL_ERROR;
113 }
114 pBt = sqlite3TextToPtr(argv[1]);
115 rc = sqlite3BtreeClose(pBt);
116 if( rc!=SQLITE_OK ){
117 Tcl_AppendResult(interp, errorName(rc), 0);
118 return TCL_ERROR;
119 }
120 nRefSqlite3--;
121 if( nRefSqlite3==0 ){
122 sqlite3_mutex_leave(sDb.mutex);
123 sqlite3_mutex_free(sDb.mutex);
124 sDb.mutex = 0;
125 sDb.pVfs = 0;
126 }
127 return TCL_OK;
128}
129
130
131/*
132** Usage: btree_begin_transaction ID
133**
134** Start a new transaction
135*/
136static int btree_begin_transaction(
137 void *NotUsed,
138 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
139 int argc, /* Number of arguments */
140 const char **argv /* Text of each argument */
141){
142 Btree *pBt;
143 int rc;
144 if( argc!=2 ){
145 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
146 " ID\"", 0);
147 return TCL_ERROR;
148 }
149 pBt = sqlite3TextToPtr(argv[1]);
150 sqlite3BtreeEnter(pBt);
151 rc = sqlite3BtreeBeginTrans(pBt, 1);
152 sqlite3BtreeLeave(pBt);
153 if( rc!=SQLITE_OK ){
154 Tcl_AppendResult(interp, errorName(rc), 0);
155 return TCL_ERROR;
156 }
157 return TCL_OK;
158}
159
160/*
161** Usage: btree_rollback ID
162**
163** Rollback changes
164*/
165static int btree_rollback(
166 void *NotUsed,
167 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
168 int argc, /* Number of arguments */
169 const char **argv /* Text of each argument */
170){
171 Btree *pBt;
172 int rc;
173 if( argc!=2 ){
174 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
175 " ID\"", 0);
176 return TCL_ERROR;
177 }
178 pBt = sqlite3TextToPtr(argv[1]);
179 sqlite3BtreeEnter(pBt);
180 rc = sqlite3BtreeRollback(pBt);
181 sqlite3BtreeLeave(pBt);
182 if( rc!=SQLITE_OK ){
183 Tcl_AppendResult(interp, errorName(rc), 0);
184 return TCL_ERROR;
185 }
186 return TCL_OK;
187}
188
189/*
190** Usage: btree_commit ID
191**
192** Commit all changes
193*/
194static int btree_commit(
195 void *NotUsed,
196 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
197 int argc, /* Number of arguments */
198 const char **argv /* Text of each argument */
199){
200 Btree *pBt;
201 int rc;
202 if( argc!=2 ){
203 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
204 " ID\"", 0);
205 return TCL_ERROR;
206 }
207 pBt = sqlite3TextToPtr(argv[1]);
208 sqlite3BtreeEnter(pBt);
209 rc = sqlite3BtreeCommit(pBt);
210 sqlite3BtreeLeave(pBt);
211 if( rc!=SQLITE_OK ){
212 Tcl_AppendResult(interp, errorName(rc), 0);
213 return TCL_ERROR;
214 }
215 return TCL_OK;
216}
217
218/*
219** Usage: btree_begin_statement ID
220**
221** Start a new statement transaction
222*/
223static int btree_begin_statement(
224 void *NotUsed,
225 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
226 int argc, /* Number of arguments */
227 const char **argv /* Text of each argument */
228){
229 Btree *pBt;
230 int rc;
231 if( argc!=2 ){
232 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
233 " ID\"", 0);
234 return TCL_ERROR;
235 }
236 pBt = sqlite3TextToPtr(argv[1]);
237 sqlite3BtreeEnter(pBt);
238 rc = sqlite3BtreeBeginStmt(pBt);
239 sqlite3BtreeLeave(pBt);
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_rollback_statement ID
249**
250** Rollback changes
251*/
252static int btree_rollback_statement(
253 void *NotUsed,
254 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
255 int argc, /* Number of arguments */
256 const char **argv /* Text of each argument */
257){
258 Btree *pBt;
259 int rc;
260 if( argc!=2 ){
261 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
262 " ID\"", 0);
263 return TCL_ERROR;
264 }
265 pBt = sqlite3TextToPtr(argv[1]);
266 sqlite3BtreeEnter(pBt);
267 rc = sqlite3BtreeRollbackStmt(pBt);
268 sqlite3BtreeLeave(pBt);
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_commit_statement ID
278**
279** Commit all changes
280*/
281static int btree_commit_statement(
282 void *NotUsed,
283 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
284 int argc, /* Number of arguments */
285 const char **argv /* Text of each argument */
286){
287 Btree *pBt;
288 int rc;
289 if( argc!=2 ){
290 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
291 " ID\"", 0);
292 return TCL_ERROR;
293 }
294 pBt = sqlite3TextToPtr(argv[1]);
295 sqlite3BtreeEnter(pBt);
296 rc = sqlite3BtreeCommitStmt(pBt);
297 sqlite3BtreeLeave(pBt);
298 if( rc!=SQLITE_OK ){
299 Tcl_AppendResult(interp, errorName(rc), 0);
300 return TCL_ERROR;
301 }
302 return TCL_OK;
303}
304
305/*
306** Usage: btree_create_table ID FLAGS
307**
308** Create a new table in the database
309*/
310static int btree_create_table(
311 void *NotUsed,
312 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
313 int argc, /* Number of arguments */
314 const char **argv /* Text of each argument */
315){
316 Btree *pBt;
317 int rc, iTable, flags;
318 char zBuf[30];
319 if( argc!=3 ){
320 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
321 " ID FLAGS\"", 0);
322 return TCL_ERROR;
323 }
324 pBt = sqlite3TextToPtr(argv[1]);
325 if( Tcl_GetInt(interp, argv[2], &flags) ) return TCL_ERROR;
326 sqlite3BtreeEnter(pBt);
327 rc = sqlite3BtreeCreateTable(pBt, &iTable, flags);
328 sqlite3BtreeLeave(pBt);
329 if( rc!=SQLITE_OK ){
330 Tcl_AppendResult(interp, errorName(rc), 0);
331 return TCL_ERROR;
332 }
333 sqlite3_snprintf(sizeof(zBuf), zBuf, "%d", iTable);
334 Tcl_AppendResult(interp, zBuf, 0);
335 return TCL_OK;
336}
337
338/*
339** Usage: btree_drop_table ID TABLENUM
340**
341** Delete an entire table from the database
342*/
343static int btree_drop_table(
344 void *NotUsed,
345 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
346 int argc, /* Number of arguments */
347 const char **argv /* Text of each argument */
348){
349 Btree *pBt;
350 int iTable;
351 int rc;
352 int notUsed1;
353 if( argc!=3 ){
354 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
355 " ID TABLENUM\"", 0);
356 return TCL_ERROR;
357 }
358 pBt = sqlite3TextToPtr(argv[1]);
359 if( Tcl_GetInt(interp, argv[2], &iTable) ) return TCL_ERROR;
360 sqlite3BtreeEnter(pBt);
361 rc = sqlite3BtreeDropTable(pBt, iTable, &notUsed1);
362 sqlite3BtreeLeave(pBt);
363 if( rc!=SQLITE_OK ){
364 Tcl_AppendResult(interp, errorName(rc), 0);
365 return TCL_ERROR;
366 }
367 return TCL_OK;
368}
369
370/*
371** Usage: btree_clear_table ID TABLENUM
372**
373** Remove all entries from the given table but keep the table around.
374*/
375static int btree_clear_table(
376 void *NotUsed,
377 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
378 int argc, /* Number of arguments */
379 const char **argv /* Text of each argument */
380){
381 Btree *pBt;
382 int iTable;
383 int rc;
384 if( argc!=3 ){
385 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
386 " ID TABLENUM\"", 0);
387 return TCL_ERROR;
388 }
389 pBt = sqlite3TextToPtr(argv[1]);
390 if( Tcl_GetInt(interp, argv[2], &iTable) ) return TCL_ERROR;
391 sqlite3BtreeEnter(pBt);
392 rc = sqlite3BtreeClearTable(pBt, iTable);
393 sqlite3BtreeLeave(pBt);
394 if( rc!=SQLITE_OK ){
395 Tcl_AppendResult(interp, errorName(rc), 0);
396 return TCL_ERROR;
397 }
398 return TCL_OK;
399}
400
401/*
402** Usage: btree_get_meta ID
403**
404** Return meta data
405*/
406static int btree_get_meta(
407 void *NotUsed,
408 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
409 int argc, /* Number of arguments */
410 const char **argv /* Text of each argument */
411){
412 Btree *pBt;
413 int rc;
414 int i;
415 if( argc!=2 ){
416 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
417 " ID\"", 0);
418 return TCL_ERROR;
419 }
420 pBt = sqlite3TextToPtr(argv[1]);
421 for(i=0; i<SQLITE_N_BTREE_META; i++){
422 char zBuf[30];
423 unsigned int v;
424 sqlite3BtreeEnter(pBt);
425 rc = sqlite3BtreeGetMeta(pBt, i, &v);
426 sqlite3BtreeLeave(pBt);
427 if( rc!=SQLITE_OK ){
428 Tcl_AppendResult(interp, errorName(rc), 0);
429 return TCL_ERROR;
430 }
431 sqlite3_snprintf(sizeof(zBuf), zBuf,"%d",v);
432 Tcl_AppendElement(interp, zBuf);
433 }
434 return TCL_OK;
435}
436
437/*
438** Usage: btree_update_meta ID METADATA...
439**
440** Return meta data
441*/
442static int btree_update_meta(
443 void *NotUsed,
444 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
445 int argc, /* Number of arguments */
446 const char **argv /* Text of each argument */
447){
448 Btree *pBt;
449 int rc;
450 int i;
451 int aMeta[SQLITE_N_BTREE_META];
452
453 if( argc!=2+SQLITE_N_BTREE_META ){
454 char zBuf[30];
455 sqlite3_snprintf(sizeof(zBuf), zBuf,"%d",SQLITE_N_BTREE_META);
456 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
457 " ID METADATA...\" (METADATA is ", zBuf, " integers)", 0);
458 return TCL_ERROR;
459 }
460 pBt = sqlite3TextToPtr(argv[1]);
461 for(i=1; i<SQLITE_N_BTREE_META; i++){
462 if( Tcl_GetInt(interp, argv[i+2], &aMeta[i]) ) return TCL_ERROR;
463 }
464 for(i=1; i<SQLITE_N_BTREE_META; i++){
465 sqlite3BtreeEnter(pBt);
466 rc = sqlite3BtreeUpdateMeta(pBt, i, aMeta[i]);
467 sqlite3BtreeLeave(pBt);
468 if( rc!=SQLITE_OK ){
469 Tcl_AppendResult(interp, errorName(rc), 0);
470 return TCL_ERROR;
471 }
472 }
473 return TCL_OK;
474}
475
476/*
477** Usage: btree_page_dump ID PAGENUM
478**
479** Print a disassembly of a page on standard output
480*/
481static int btree_page_dump(
482 void *NotUsed,
483 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
484 int argc, /* Number of arguments */
485 const char **argv /* Text of each argument */
486){
487 Btree *pBt;
488 int iPage;
489 int rc;
490
491 if( argc!=3 ){
492 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
493 " ID\"", 0);
494 return TCL_ERROR;
495 }
496 pBt = sqlite3TextToPtr(argv[1]);
497 if( Tcl_GetInt(interp, argv[2], &iPage) ) return TCL_ERROR;
498 sqlite3BtreeEnter(pBt);
499 rc = sqlite3BtreePageDump(pBt, iPage, 0);
500 sqlite3BtreeLeave(pBt);
501 if( rc!=SQLITE_OK ){
502 Tcl_AppendResult(interp, errorName(rc), 0);
503 return TCL_ERROR;
504 }
505 return TCL_OK;
506}
507
508/*
509** Usage: btree_tree_dump ID PAGENUM
510**
511** Print a disassembly of a page and all its child pages on standard output
512*/
513static int btree_tree_dump(
514 void *NotUsed,
515 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
516 int argc, /* Number of arguments */
517 const char **argv /* Text of each argument */
518){
519 Btree *pBt;
520 int iPage;
521 int rc;
522
523 if( argc!=3 ){
524 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
525 " ID\"", 0);
526 return TCL_ERROR;
527 }
528 pBt = sqlite3TextToPtr(argv[1]);
529 if( Tcl_GetInt(interp, argv[2], &iPage) ) return TCL_ERROR;
530 sqlite3BtreeEnter(pBt);
531 rc = sqlite3BtreePageDump(pBt, iPage, 1);
532 sqlite3BtreeLeave(pBt);
533 if( rc!=SQLITE_OK ){
534 Tcl_AppendResult(interp, errorName(rc), 0);
535 return TCL_ERROR;
536 }
537 return TCL_OK;
538}
539
540/*
541** Usage: btree_pager_stats ID
542**
543** Returns pager statistics
544*/
545static int btree_pager_stats(
546 void *NotUsed,
547 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
548 int argc, /* Number of arguments */
549 const char **argv /* Text of each argument */
550){
551 Btree *pBt;
552 int i;
553 int *a;
554
555 if( argc!=2 ){
556 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
557 " ID\"", 0);
558 return TCL_ERROR;
559 }
560 pBt = sqlite3TextToPtr(argv[1]);
561
562 /* Normally in this file, with a b-tree handle opened using the
563 ** [btree_open] command it is safe to call sqlite3BtreeEnter() directly.
564 ** But this function is sometimes called with a btree handle obtained
565 ** from an open SQLite connection (using [btree_from_db]). In this case
566 ** we need to obtain the mutex for the controlling SQLite handle before
567 ** it is safe to call sqlite3BtreeEnter().
568 */
569 sqlite3_mutex_enter(pBt->pSqlite->mutex);
570
571 sqlite3BtreeEnter(pBt);
572 a = sqlite3PagerStats(sqlite3BtreePager(pBt));
573 for(i=0; i<11; i++){
574 static char *zName[] = {
575 "ref", "page", "max", "size", "state", "err",
576 "hit", "miss", "ovfl", "read", "write"
577 };
578 char zBuf[100];
579 Tcl_AppendElement(interp, zName[i]);
580 sqlite3_snprintf(sizeof(zBuf), zBuf,"%d",a[i]);
581 Tcl_AppendElement(interp, zBuf);
582 }
583 sqlite3BtreeLeave(pBt);
584
585 /* Release the mutex on the SQLite handle that controls this b-tree */
586 sqlite3_mutex_leave(pBt->pSqlite->mutex);
587 return TCL_OK;
588}
589
590/*
591** Usage: btree_pager_ref_dump ID
592**
593** Print out all outstanding pages.
594*/
595static int btree_pager_ref_dump(
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 Btree *pBt;
602
603 if( argc!=2 ){
604 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
605 " ID\"", 0);
606 return TCL_ERROR;
607 }
608 pBt = sqlite3TextToPtr(argv[1]);
609#ifdef SQLITE_DEBUG
610 sqlite3BtreeEnter(pBt);
611 sqlite3PagerRefdump(sqlite3BtreePager(pBt));
612 sqlite3BtreeLeave(pBt);
613#endif
614 return TCL_OK;
615}
616
617/*
618** Usage: btree_integrity_check ID ROOT ...
619**
620** Look through every page of the given BTree file to verify correct
621** formatting and linkage. Return a line of text for each problem found.
622** Return an empty string if everything worked.
623*/
624static int btree_integrity_check(
625 void *NotUsed,
626 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
627 int argc, /* Number of arguments */
628 const char **argv /* Text of each argument */
629){
630 Btree *pBt;
631 int nRoot;
632 int *aRoot;
633 int i;
634 int nErr;
635 char *zResult;
636
637 if( argc<3 ){
638 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
639 " ID ROOT ...\"", 0);
640 return TCL_ERROR;
641 }
642 pBt = sqlite3TextToPtr(argv[1]);
643 nRoot = argc-2;
644 aRoot = (int*)sqlite3_malloc( sizeof(int)*(argc-2) );
645 for(i=0; i<argc-2; i++){
646 if( Tcl_GetInt(interp, argv[i+2], &aRoot[i]) ) return TCL_ERROR;
647 }
648#ifndef SQLITE_OMIT_INTEGRITY_CHECK
649 sqlite3BtreeEnter(pBt);
650 zResult = sqlite3BtreeIntegrityCheck(pBt, aRoot, nRoot, 10000, &nErr);
651 sqlite3BtreeLeave(pBt);
652#else
653 zResult = 0;
654#endif
655 sqlite3_free((void*)aRoot);
656 if( zResult ){
657 Tcl_AppendResult(interp, zResult, 0);
658 sqlite3_free(zResult);
659 }
660 return TCL_OK;
661}
662
663/*
664** Usage: btree_cursor_list ID
665**
666** Print information about all cursors to standard output for debugging.
667*/
668static int btree_cursor_list(
669 void *NotUsed,
670 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
671 int argc, /* Number of arguments */
672 const char **argv /* Text of each argument */
673){
674 Btree *pBt;
675
676 if( argc!=2 ){
677 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
678 " ID\"", 0);
679 return TCL_ERROR;
680 }
681 pBt = sqlite3TextToPtr(argv[1]);
682 sqlite3BtreeEnter(pBt);
683 sqlite3BtreeCursorList(pBt);
684 sqlite3BtreeLeave(pBt);
685 return SQLITE_OK;
686}
687
688/*
689** Usage: btree_cursor ID TABLENUM WRITEABLE
690**
691** Create a new cursor. Return the ID for the cursor.
692*/
693static int btree_cursor(
694 void *NotUsed,
695 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
696 int argc, /* Number of arguments */
697 const char **argv /* Text of each argument */
698){
699 Btree *pBt;
700 int iTable;
701 BtCursor *pCur;
702 int rc;
703 int wrFlag;
704 char zBuf[30];
705
706 if( argc!=4 ){
707 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
708 " ID TABLENUM WRITEABLE\"", 0);
709 return TCL_ERROR;
710 }
711 pBt = sqlite3TextToPtr(argv[1]);
712 if( Tcl_GetInt(interp, argv[2], &iTable) ) return TCL_ERROR;
713 if( Tcl_GetBoolean(interp, argv[3], &wrFlag) ) return TCL_ERROR;
714 sqlite3BtreeEnter(pBt);
715 rc = sqlite3BtreeCursor(pBt, iTable, wrFlag, 0, 0, &pCur);
716 sqlite3BtreeLeave(pBt);
717 if( rc ){
718 Tcl_AppendResult(interp, errorName(rc), 0);
719 return TCL_ERROR;
720 }
721 sqlite3_snprintf(sizeof(zBuf), zBuf,"%p", pCur);
722 Tcl_AppendResult(interp, zBuf, 0);
723 return SQLITE_OK;
724}
725
726/*
727** Usage: btree_close_cursor ID
728**
729** Close a cursor opened using btree_cursor.
730*/
731static int btree_close_cursor(
732 void *NotUsed,
733 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
734 int argc, /* Number of arguments */
735 const char **argv /* Text of each argument */
736){
737 BtCursor *pCur;
738 Btree *pBt;
739 int rc;
740
741 if( argc!=2 ){
742 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
743 " ID\"", 0);
744 return TCL_ERROR;
745 }
746 pCur = sqlite3TextToPtr(argv[1]);
747 pBt = pCur->pBtree;
748 sqlite3BtreeEnter(pBt);
749 rc = sqlite3BtreeCloseCursor(pCur);
750 sqlite3BtreeLeave(pBt);
751 if( rc ){
752 Tcl_AppendResult(interp, errorName(rc), 0);
753 return TCL_ERROR;
754 }
755 return SQLITE_OK;
756}
757
758/*
759** Usage: btree_move_to ID KEY
760**
761** Move the cursor to the entry with the given key.
762*/
763static int btree_move_to(
764 void *NotUsed,
765 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
766 int argc, /* Number of arguments */
767 const char **argv /* Text of each argument */
768){
769 BtCursor *pCur;
770 int rc;
771 int res;
772 char zBuf[20];
773
774 if( argc!=3 ){
775 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
776 " ID KEY\"", 0);
777 return TCL_ERROR;
778 }
779 pCur = sqlite3TextToPtr(argv[1]);
780 sqlite3BtreeEnter(pCur->pBtree);
781 if( sqlite3BtreeFlags(pCur) & BTREE_INTKEY ){
782 int iKey;
783 if( Tcl_GetInt(interp, argv[2], &iKey) ){
784 sqlite3BtreeLeave(pCur->pBtree);
785 return TCL_ERROR;
786 }
787 rc = sqlite3BtreeMoveto(pCur, 0, iKey, 0, &res);
788 }else{
789 rc = sqlite3BtreeMoveto(pCur, argv[2], strlen(argv[2]), 0, &res);
790 }
791 sqlite3BtreeLeave(pCur->pBtree);
792 if( rc ){
793 Tcl_AppendResult(interp, errorName(rc), 0);
794 return TCL_ERROR;
795 }
796 if( res<0 ) res = -1;
797 if( res>0 ) res = 1;
798 sqlite3_snprintf(sizeof(zBuf), zBuf,"%d",res);
799 Tcl_AppendResult(interp, zBuf, 0);
800 return SQLITE_OK;
801}
802
803/*
804** Usage: btree_delete ID
805**
806** Delete the entry that the cursor is pointing to
807*/
808static int btree_delete(
809 void *NotUsed,
810 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
811 int argc, /* Number of arguments */
812 const char **argv /* Text of each argument */
813){
814 BtCursor *pCur;
815 int rc;
816
817 if( argc!=2 ){
818 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
819 " ID\"", 0);
820 return TCL_ERROR;
821 }
822 pCur = sqlite3TextToPtr(argv[1]);
823 sqlite3BtreeEnter(pCur->pBtree);
824 rc = sqlite3BtreeDelete(pCur);
825 sqlite3BtreeLeave(pCur->pBtree);
826 if( rc ){
827 Tcl_AppendResult(interp, errorName(rc), 0);
828 return TCL_ERROR;
829 }
830 return SQLITE_OK;
831}
832
833/*
834** Usage: btree_insert ID KEY DATA ?NZERO?
835**
836** Create a new entry with the given key and data. If an entry already
837** exists with the same key the old entry is overwritten.
838*/
839static int btree_insert(
840 void * clientData,
841 Tcl_Interp *interp,
842 int objc,
843 Tcl_Obj *CONST objv[]
844){
845 BtCursor *pCur;
846 int rc;
847 int nZero;
848
849 if( objc!=4 && objc!=5 ){
850 Tcl_WrongNumArgs(interp, 1, objv, "ID KEY DATA ?NZERO?");
851 return TCL_ERROR;
852 }
853 pCur = sqlite3TextToPtr(Tcl_GetString(objv[1]));
854 if( objc==5 ){
855 if( Tcl_GetIntFromObj(interp, objv[4], &nZero) ) return TCL_ERROR;
856 }else{
857 nZero = 0;
858 }
859 sqlite3BtreeEnter(pCur->pBtree);
860 if( sqlite3BtreeFlags(pCur) & BTREE_INTKEY ){
861 i64 iKey;
862 int len;
863 unsigned char *pBuf;
864 if( Tcl_GetWideIntFromObj(interp, objv[2], &iKey) ){
865 sqlite3BtreeLeave(pCur->pBtree);
866 return TCL_ERROR;
867 }
868 pBuf = Tcl_GetByteArrayFromObj(objv[3], &len);
869 rc = sqlite3BtreeInsert(pCur, 0, iKey, pBuf, len, nZero, 0);
870 }else{
871 int keylen;
872 int dlen;
873 unsigned char *pKBuf;
874 unsigned char *pDBuf;
875 pKBuf = Tcl_GetByteArrayFromObj(objv[2], &keylen);
876 pDBuf = Tcl_GetByteArrayFromObj(objv[3], &dlen);
877 rc = sqlite3BtreeInsert(pCur, pKBuf, keylen, pDBuf, dlen, nZero, 0);
878 }
879 sqlite3BtreeLeave(pCur->pBtree);
880 if( rc ){
881 Tcl_AppendResult(interp, errorName(rc), 0);
882 return TCL_ERROR;
883 }
884 return SQLITE_OK;
885}
886
887/*
888** Usage: btree_next ID
889**
890** Move the cursor to the next entry in the table. Return 0 on success
891** or 1 if the cursor was already on the last entry in the table or if
892** the table is empty.
893*/
894static int btree_next(
895 void *NotUsed,
896 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
897 int argc, /* Number of arguments */
898 const char **argv /* Text of each argument */
899){
900 BtCursor *pCur;
901 int rc;
902 int res = 0;
903 char zBuf[100];
904
905 if( argc!=2 ){
906 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
907 " ID\"", 0);
908 return TCL_ERROR;
909 }
910 pCur = sqlite3TextToPtr(argv[1]);
911 sqlite3BtreeEnter(pCur->pBtree);
912 rc = sqlite3BtreeNext(pCur, &res);
913 sqlite3BtreeLeave(pCur->pBtree);
914 if( rc ){
915 Tcl_AppendResult(interp, errorName(rc), 0);
916 return TCL_ERROR;
917 }
918 sqlite3_snprintf(sizeof(zBuf),zBuf,"%d",res);
919 Tcl_AppendResult(interp, zBuf, 0);
920 return SQLITE_OK;
921}
922
923/*
924** Usage: btree_prev ID
925**
926** Move the cursor to the previous entry in the table. Return 0 on
927** success and 1 if the cursor was already on the first entry in
928** the table or if the table was empty.
929*/
930static int btree_prev(
931 void *NotUsed,
932 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
933 int argc, /* Number of arguments */
934 const char **argv /* Text of each argument */
935){
936 BtCursor *pCur;
937 int rc;
938 int res = 0;
939 char zBuf[100];
940
941 if( argc!=2 ){
942 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
943 " ID\"", 0);
944 return TCL_ERROR;
945 }
946 pCur = sqlite3TextToPtr(argv[1]);
947 sqlite3BtreeEnter(pCur->pBtree);
948 rc = sqlite3BtreePrevious(pCur, &res);
949 sqlite3BtreeLeave(pCur->pBtree);
950 if( rc ){
951 Tcl_AppendResult(interp, errorName(rc), 0);
952 return TCL_ERROR;
953 }
954 sqlite3_snprintf(sizeof(zBuf),zBuf,"%d",res);
955 Tcl_AppendResult(interp, zBuf, 0);
956 return SQLITE_OK;
957}
958
959/*
960** Usage: btree_first ID
961**
962** Move the cursor to the first entry in the table. Return 0 if the
963** cursor was left point to something and 1 if the table is empty.
964*/
965static int btree_first(
966 void *NotUsed,
967 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
968 int argc, /* Number of arguments */
969 const char **argv /* Text of each argument */
970){
971 BtCursor *pCur;
972 int rc;
973 int res = 0;
974 char zBuf[100];
975
976 if( argc!=2 ){
977 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
978 " ID\"", 0);
979 return TCL_ERROR;
980 }
981 pCur = sqlite3TextToPtr(argv[1]);
982 sqlite3BtreeEnter(pCur->pBtree);
983 rc = sqlite3BtreeFirst(pCur, &res);
984 sqlite3BtreeLeave(pCur->pBtree);
985 if( rc ){
986 Tcl_AppendResult(interp, errorName(rc), 0);
987 return TCL_ERROR;
988 }
989 sqlite3_snprintf(sizeof(zBuf),zBuf,"%d",res);
990 Tcl_AppendResult(interp, zBuf, 0);
991 return SQLITE_OK;
992}
993
994/*
995** Usage: btree_last ID
996**
997** Move the cursor to the last entry in the table. Return 0 if the
998** cursor was left point to something and 1 if the table is empty.
999*/
1000static int btree_last(
1001 void *NotUsed,
1002 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1003 int argc, /* Number of arguments */
1004 const char **argv /* Text of each argument */
1005){
1006 BtCursor *pCur;
1007 int rc;
1008 int res = 0;
1009 char zBuf[100];
1010
1011 if( argc!=2 ){
1012 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
1013 " ID\"", 0);
1014 return TCL_ERROR;
1015 }
1016 pCur = sqlite3TextToPtr(argv[1]);
1017 sqlite3BtreeEnter(pCur->pBtree);
1018 rc = sqlite3BtreeLast(pCur, &res);
1019 sqlite3BtreeLeave(pCur->pBtree);
1020 if( rc ){
1021 Tcl_AppendResult(interp, errorName(rc), 0);
1022 return TCL_ERROR;
1023 }
1024 sqlite3_snprintf(sizeof(zBuf),zBuf,"%d",res);
1025 Tcl_AppendResult(interp, zBuf, 0);
1026 return SQLITE_OK;
1027}
1028
1029/*
1030** Usage: btree_eof ID
1031**
1032** Return TRUE if the given cursor is not pointing at a valid entry.
1033** Return FALSE if the cursor does point to a valid entry.
1034*/
1035static int btree_eof(
1036 void *NotUsed,
1037 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1038 int argc, /* Number of arguments */
1039 const char **argv /* Text of each argument */
1040){
1041 BtCursor *pCur;
1042 int rc;
1043 char zBuf[50];
1044
1045 if( argc!=2 ){
1046 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
1047 " ID\"", 0);
1048 return TCL_ERROR;
1049 }
1050 pCur = sqlite3TextToPtr(argv[1]);
1051 sqlite3BtreeEnter(pCur->pBtree);
1052 rc = sqlite3BtreeEof(pCur);
1053 sqlite3BtreeLeave(pCur->pBtree);
1054 sqlite3_snprintf(sizeof(zBuf),zBuf, "%d", rc);
1055 Tcl_AppendResult(interp, zBuf, 0);
1056 return SQLITE_OK;
1057}
1058
1059/*
1060** Usage: btree_keysize ID
1061**
1062** Return the number of bytes of key. For an INTKEY table, this
1063** returns the key itself.
1064*/
1065static int btree_keysize(
1066 void *NotUsed,
1067 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1068 int argc, /* Number of arguments */
1069 const char **argv /* Text of each argument */
1070){
1071 BtCursor *pCur;
1072 u64 n;
1073 char zBuf[50];
1074
1075 if( argc!=2 ){
1076 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
1077 " ID\"", 0);
1078 return TCL_ERROR;
1079 }
1080 pCur = sqlite3TextToPtr(argv[1]);
1081 sqlite3BtreeEnter(pCur->pBtree);
1082 sqlite3BtreeKeySize(pCur, (i64*)&n);
1083 sqlite3BtreeLeave(pCur->pBtree);
1084 sqlite3_snprintf(sizeof(zBuf),zBuf, "%llu", n);
1085 Tcl_AppendResult(interp, zBuf, 0);
1086 return SQLITE_OK;
1087}
1088
1089/*
1090** Usage: btree_key ID
1091**
1092** Return the key for the entry at which the cursor is pointing.
1093*/
1094static int btree_key(
1095 void *NotUsed,
1096 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1097 int argc, /* Number of arguments */
1098 const char **argv /* Text of each argument */
1099){
1100 BtCursor *pCur;
1101 int rc;
1102 u64 n;
1103 char *zBuf;
1104
1105 if( argc!=2 ){
1106 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
1107 " ID\"", 0);
1108 return TCL_ERROR;
1109 }
1110 pCur = sqlite3TextToPtr(argv[1]);
1111 sqlite3BtreeEnter(pCur->pBtree);
1112 sqlite3BtreeKeySize(pCur, (i64*)&n);
1113 if( sqlite3BtreeFlags(pCur) & BTREE_INTKEY ){
1114 char zBuf2[60];
1115 sqlite3_snprintf(sizeof(zBuf2),zBuf2, "%llu", n);
1116 Tcl_AppendResult(interp, zBuf2, 0);
1117 }else{
1118 zBuf = sqlite3_malloc( n+1 );
1119 rc = sqlite3BtreeKey(pCur, 0, n, zBuf);
1120 if( rc ){
1121 sqlite3BtreeLeave(pCur->pBtree);
1122 Tcl_AppendResult(interp, errorName(rc), 0);
1123 return TCL_ERROR;
1124 }
1125 zBuf[n] = 0;
1126 Tcl_AppendResult(interp, zBuf, 0);
1127 sqlite3_free(zBuf);
1128 }
1129 sqlite3BtreeLeave(pCur->pBtree);
1130 return SQLITE_OK;
1131}
1132
1133/*
1134** Usage: btree_data ID ?N?
1135**
1136** Return the data for the entry at which the cursor is pointing.
1137*/
1138static int btree_data(
1139 void *NotUsed,
1140 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1141 int argc, /* Number of arguments */
1142 const char **argv /* Text of each argument */
1143){
1144 BtCursor *pCur;
1145 int rc;
1146 u32 n;
1147 char *zBuf;
1148
1149 if( argc!=2 && argc!=3 ){
1150 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
1151 " ID\"", 0);
1152 return TCL_ERROR;
1153 }
1154 pCur = sqlite3TextToPtr(argv[1]);
1155 sqlite3BtreeEnter(pCur->pBtree);
1156 if( argc==2 ){
1157 sqlite3BtreeDataSize(pCur, &n);
1158 }else{
1159 n = atoi(argv[2]);
1160 }
1161 zBuf = sqlite3_malloc( n+1 );
1162 rc = sqlite3BtreeData(pCur, 0, n, zBuf);
1163 sqlite3BtreeLeave(pCur->pBtree);
1164 if( rc ){
1165 Tcl_AppendResult(interp, errorName(rc), 0);
1166 sqlite3_free(zBuf);
1167 return TCL_ERROR;
1168 }
1169 zBuf[n] = 0;
1170 Tcl_AppendResult(interp, zBuf, 0);
1171 sqlite3_free(zBuf);
1172 return SQLITE_OK;
1173}
1174
1175/*
1176** Usage: btree_fetch_key ID AMT
1177**
1178** Use the sqlite3BtreeKeyFetch() routine to get AMT bytes of the key.
1179** If sqlite3BtreeKeyFetch() fails, return an empty string.
1180*/
1181static int btree_fetch_key(
1182 void *NotUsed,
1183 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1184 int argc, /* Number of arguments */
1185 const char **argv /* Text of each argument */
1186){
1187 BtCursor *pCur;
1188 int n;
1189 int amt;
1190 u64 nKey;
1191 const char *zBuf;
1192 char zStatic[1000];
1193
1194 if( argc!=3 ){
1195 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
1196 " ID AMT\"", 0);
1197 return TCL_ERROR;
1198 }
1199 pCur = sqlite3TextToPtr(argv[1]);
1200 if( Tcl_GetInt(interp, argv[2], &n) ) return TCL_ERROR;
1201 sqlite3BtreeEnter(pCur->pBtree);
1202 sqlite3BtreeKeySize(pCur, (i64*)&nKey);
1203 zBuf = sqlite3BtreeKeyFetch(pCur, &amt);
1204 if( zBuf && amt>=n ){
1205 assert( nKey<sizeof(zStatic) );
1206 if( n>0 ) nKey = n;
1207 memcpy(zStatic, zBuf, (int)nKey);
1208 zStatic[nKey] = 0;
1209 Tcl_AppendResult(interp, zStatic, 0);
1210 }
1211 sqlite3BtreeLeave(pCur->pBtree);
1212 return TCL_OK;
1213}
1214
1215/*
1216** Usage: btree_fetch_data ID AMT
1217**
1218** Use the sqlite3BtreeDataFetch() routine to get AMT bytes of the key.
1219** If sqlite3BtreeDataFetch() fails, return an empty string.
1220*/
1221static int btree_fetch_data(
1222 void *NotUsed,
1223 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1224 int argc, /* Number of arguments */
1225 const char **argv /* Text of each argument */
1226){
1227 BtCursor *pCur;
1228 int n;
1229 int amt;
1230 u32 nData;
1231 const char *zBuf;
1232 char zStatic[1000];
1233
1234 if( argc!=3 ){
1235 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
1236 " ID AMT\"", 0);
1237 return TCL_ERROR;
1238 }
1239 pCur = sqlite3TextToPtr(argv[1]);
1240 if( Tcl_GetInt(interp, argv[2], &n) ) return TCL_ERROR;
1241 sqlite3BtreeEnter(pCur->pBtree);
1242 sqlite3BtreeDataSize(pCur, &nData);
1243 zBuf = sqlite3BtreeDataFetch(pCur, &amt);
1244 if( zBuf && amt>=n ){
1245 assert( nData<sizeof(zStatic) );
1246 if( n>0 ) nData = n;
1247 memcpy(zStatic, zBuf, (int)nData);
1248 zStatic[nData] = 0;
1249 Tcl_AppendResult(interp, zStatic, 0);
1250 }
1251 sqlite3BtreeLeave(pCur->pBtree);
1252 return TCL_OK;
1253}
1254
1255/*
1256** Usage: btree_payload_size ID
1257**
1258** Return the number of bytes of payload
1259*/
1260static int btree_payload_size(
1261 void *NotUsed,
1262 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1263 int argc, /* Number of arguments */
1264 const char **argv /* Text of each argument */
1265){
1266 BtCursor *pCur;
1267 int n2;
1268 u64 n1;
1269 char zBuf[50];
1270
1271 if( argc!=2 ){
1272 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
1273 " ID\"", 0);
1274 return TCL_ERROR;
1275 }
1276 pCur = sqlite3TextToPtr(argv[1]);
1277 sqlite3BtreeEnter(pCur->pBtree);
1278 if( sqlite3BtreeFlags(pCur) & BTREE_INTKEY ){
1279 n1 = 0;
1280 }else{
1281 sqlite3BtreeKeySize(pCur, (i64*)&n1);
1282 }
1283 sqlite3BtreeDataSize(pCur, (u32*)&n2);
1284 sqlite3BtreeLeave(pCur->pBtree);
1285 sqlite3_snprintf(sizeof(zBuf),zBuf, "%d", (int)(n1+n2));
1286 Tcl_AppendResult(interp, zBuf, 0);
1287 return SQLITE_OK;
1288}
1289
1290/*
1291** Usage: btree_cursor_info ID ?UP-CNT?
1292**
1293** Return integers containing information about the entry the
1294** cursor is pointing to:
1295**
1296** aResult[0] = The page number
1297** aResult[1] = The entry number
1298** aResult[2] = Total number of entries on this page
1299** aResult[3] = Cell size (local payload + header)
1300** aResult[4] = Number of free bytes on this page
1301** aResult[5] = Number of free blocks on the page
1302** aResult[6] = Total payload size (local + overflow)
1303** aResult[7] = Header size in bytes
1304** aResult[8] = Local payload size
1305** aResult[9] = Parent page number
1306** aResult[10]= Page number of the first overflow page
1307*/
1308static int btree_cursor_info(
1309 void *NotUsed,
1310 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1311 int argc, /* Number of arguments */
1312 const char **argv /* Text of each argument */
1313){
1314 BtCursor *pCur;
1315 int rc;
1316 int i, j;
1317 int up;
1318 int aResult[11];
1319 char zBuf[400];
1320
1321 if( argc!=2 && argc!=3 ){
1322 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
1323 " ID ?UP-CNT?\"", 0);
1324 return TCL_ERROR;
1325 }
1326 pCur = sqlite3TextToPtr(argv[1]);
1327 if( argc==3 ){
1328 if( Tcl_GetInt(interp, argv[2], &up) ) return TCL_ERROR;
1329 }else{
1330 up = 0;
1331 }
1332 sqlite3BtreeEnter(pCur->pBtree);
1333 rc = sqlite3BtreeCursorInfo(pCur, aResult, up);
1334 if( rc ){
1335 Tcl_AppendResult(interp, errorName(rc), 0);
1336 sqlite3BtreeLeave(pCur->pBtree);
1337 return TCL_ERROR;
1338 }
1339 j = 0;
1340 for(i=0; i<sizeof(aResult)/sizeof(aResult[0]); i++){
1341 sqlite3_snprintf(40,&zBuf[j]," %d", aResult[i]);
1342 j += strlen(&zBuf[j]);
1343 }
1344 sqlite3BtreeLeave(pCur->pBtree);
1345 Tcl_AppendResult(interp, &zBuf[1], 0);
1346 return SQLITE_OK;
1347}
1348
1349/*
1350** Copied from btree.c:
1351*/
1352static u32 t4Get4byte(unsigned char *p){
1353 return (p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3];
1354}
1355
1356/*
1357** btree_ovfl_info BTREE CURSOR
1358**
1359** Given a cursor, return the sequence of pages number that form the
1360** overflow pages for the data of the entry that the cursor is point
1361** to.
1362*/
1363static int btree_ovfl_info(
1364 void *NotUsed,
1365 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1366 int argc, /* Number of arguments */
1367 const char **argv /* Text of each argument */
1368){
1369 Btree *pBt;
1370 BtCursor *pCur;
1371 Pager *pPager;
1372 int rc;
1373 int n;
1374 int dataSize;
1375 u32 pgno;
1376 void *pPage;
1377 int aResult[11];
1378 char zElem[100];
1379 Tcl_DString str;
1380
1381 if( argc!=3 ){
1382 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
1383 " BTREE CURSOR", 0);
1384 return TCL_ERROR;
1385 }
1386 pBt = sqlite3TextToPtr(argv[1]);
1387 pCur = sqlite3TextToPtr(argv[2]);
1388 if( (*(void**)pCur) != (void*)pBt ){
1389 Tcl_AppendResult(interp, "Cursor ", argv[2], " does not belong to btree ",
1390 argv[1], 0);
1391 return TCL_ERROR;
1392 }
1393 sqlite3BtreeEnter(pBt);
1394 pPager = sqlite3BtreePager(pBt);
1395 rc = sqlite3BtreeCursorInfo(pCur, aResult, 0);
1396 if( rc ){
1397 Tcl_AppendResult(interp, errorName(rc), 0);
1398 sqlite3BtreeLeave(pBt);
1399 return TCL_ERROR;
1400 }
1401 dataSize = pBt->pBt->usableSize;
1402 Tcl_DStringInit(&str);
1403 n = aResult[6] - aResult[8];
1404 n = (n + dataSize - 1)/dataSize;
1405 pgno = (u32)aResult[10];
1406 while( pgno && n-- ){
1407 DbPage *pDbPage;
1408 sprintf(zElem, "%d", pgno);
1409 Tcl_DStringAppendElement(&str, zElem);
1410 if( sqlite3PagerGet(pPager, pgno, &pDbPage)!=SQLITE_OK ){
1411 Tcl_DStringFree(&str);
1412 Tcl_AppendResult(interp, "unable to get page ", zElem, 0);
1413 sqlite3BtreeLeave(pBt);
1414 return TCL_ERROR;
1415 }
1416 pPage = sqlite3PagerGetData(pDbPage);
1417 pgno = t4Get4byte((unsigned char*)pPage);
1418 sqlite3PagerUnref(pDbPage);
1419 }
1420 sqlite3BtreeLeave(pBt);
1421 Tcl_DStringResult(interp, &str);
1422 return SQLITE_OK;
1423}
1424
1425/*
1426** The command is provided for the purpose of setting breakpoints.
1427** in regression test scripts.
1428**
1429** By setting a GDB breakpoint on this procedure and executing the
1430** btree_breakpoint command in a test script, we can stop GDB at
1431** the point in the script where the btree_breakpoint command is
1432** inserted. This is useful for debugging.
1433*/
1434static int btree_breakpoint(
1435 void *NotUsed,
1436 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1437 int argc, /* Number of arguments */
1438 const char **argv /* Text of each argument */
1439){
1440 return TCL_OK;
1441}
1442
1443/*
1444** usage: varint_test START MULTIPLIER COUNT INCREMENT
1445**
1446** This command tests the sqlite3PutVarint() and sqlite3GetVarint()
1447** routines, both for accuracy and for speed.
1448**
1449** An integer is written using PutVarint() and read back with
1450** GetVarint() and varified to be unchanged. This repeats COUNT
1451** times. The first integer is START*MULTIPLIER. Each iteration
1452** increases the integer by INCREMENT.
1453**
1454** This command returns nothing if it works. It returns an error message
1455** if something goes wrong.
1456*/
1457static int btree_varint_test(
1458 void *NotUsed,
1459 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1460 int argc, /* Number of arguments */
1461 const char **argv /* Text of each argument */
1462){
1463 u32 start, mult, count, incr;
1464 u64 in, out;
1465 int n1, n2, i, j;
1466 unsigned char zBuf[100];
1467 if( argc!=5 ){
1468 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
1469 " START MULTIPLIER COUNT INCREMENT\"", 0);
1470 return TCL_ERROR;
1471 }
1472 if( Tcl_GetInt(interp, argv[1], (int*)&start) ) return TCL_ERROR;
1473 if( Tcl_GetInt(interp, argv[2], (int*)&mult) ) return TCL_ERROR;
1474 if( Tcl_GetInt(interp, argv[3], (int*)&count) ) return TCL_ERROR;
1475 if( Tcl_GetInt(interp, argv[4], (int*)&incr) ) return TCL_ERROR;
1476 in = start;
1477 in *= mult;
1478 for(i=0; i<count; i++){
1479 char zErr[200];
1480 n1 = sqlite3PutVarint(zBuf, in);
1481 if( n1>9 || n1<1 ){
1482 sprintf(zErr, "PutVarint returned %d - should be between 1 and 9", n1);
1483 Tcl_AppendResult(interp, zErr, 0);
1484 return TCL_ERROR;
1485 }
1486 n2 = sqlite3GetVarint(zBuf, &out);
1487 if( n1!=n2 ){
1488 sprintf(zErr, "PutVarint returned %d and GetVarint returned %d", n1, n2);
1489 Tcl_AppendResult(interp, zErr, 0);
1490 return TCL_ERROR;
1491 }
1492 if( in!=out ){
1493 sprintf(zErr, "Wrote 0x%016llx and got back 0x%016llx", in, out);
1494 Tcl_AppendResult(interp, zErr, 0);
1495 return TCL_ERROR;
1496 }
1497 if( (in & 0xffffffff)==in ){
1498 u32 out32;
1499 n2 = sqlite3GetVarint32(zBuf, &out32);
1500 out = out32;
1501 if( n1!=n2 ){
1502 sprintf(zErr, "PutVarint returned %d and GetVarint32 returned %d",
1503 n1, n2);
1504 Tcl_AppendResult(interp, zErr, 0);
1505 return TCL_ERROR;
1506 }
1507 if( in!=out ){
1508 sprintf(zErr, "Wrote 0x%016llx and got back 0x%016llx from GetVarint32",
1509 in, out);
1510 Tcl_AppendResult(interp, zErr, 0);
1511 return TCL_ERROR;
1512 }
1513 }
1514
1515 /* In order to get realistic timings, run getVarint 19 more times.
1516 ** This is because getVarint is called about 20 times more often
1517 ** than putVarint.
1518 */
1519 for(j=0; j<19; j++){
1520 sqlite3GetVarint(zBuf, &out);
1521 }
1522 in += incr;
1523 }
1524 return TCL_OK;
1525}
1526
1527/*
1528** usage: btree_from_db DB-HANDLE
1529**
1530** This command returns the btree handle for the main database associated
1531** with the database-handle passed as the argument. Example usage:
1532**
1533** sqlite3 db test.db
1534** set bt [btree_from_db db]
1535*/
1536static int btree_from_db(
1537 void *NotUsed,
1538 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1539 int argc, /* Number of arguments */
1540 const char **argv /* Text of each argument */
1541){
1542 char zBuf[100];
1543 Tcl_CmdInfo info;
1544 sqlite3 *db;
1545 Btree *pBt;
1546 int iDb = 0;
1547
1548 if( argc!=2 && argc!=3 ){
1549 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
1550 " DB-HANDLE ?N?\"", 0);
1551 return TCL_ERROR;
1552 }
1553
1554 if( 1!=Tcl_GetCommandInfo(interp, argv[1], &info) ){
1555 Tcl_AppendResult(interp, "No such db-handle: \"", argv[1], "\"", 0);
1556 return TCL_ERROR;
1557 }
1558 if( argc==3 ){
1559 iDb = atoi(argv[2]);
1560 }
1561
1562 db = *((sqlite3 **)info.objClientData);
1563 assert( db );
1564
1565 pBt = db->aDb[iDb].pBt;
1566 sqlite3_snprintf(sizeof(zBuf), zBuf, "%p", pBt);
1567 Tcl_SetResult(interp, zBuf, TCL_VOLATILE);
1568 return TCL_OK;
1569}
1570
1571
1572/*
1573** usage: btree_set_cache_size ID NCACHE
1574**
1575** Set the size of the cache used by btree $ID.
1576*/
1577static int btree_set_cache_size(
1578 void *NotUsed,
1579 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1580 int argc, /* Number of arguments */
1581 const char **argv /* Text of each argument */
1582){
1583 int nCache;
1584 Btree *pBt;
1585
1586 if( argc!=3 ){
1587 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
1588 " BT NCACHE\"", 0);
1589 return TCL_ERROR;
1590 }
1591 pBt = sqlite3TextToPtr(argv[1]);
1592 if( Tcl_GetInt(interp, argv[2], &nCache) ) return TCL_ERROR;
1593
1594 sqlite3_mutex_enter(pBt->pSqlite->mutex);
1595 sqlite3BtreeEnter(pBt);
1596 sqlite3BtreeSetCacheSize(pBt, nCache);
1597 sqlite3BtreeLeave(pBt);
1598 sqlite3_mutex_leave(pBt->pSqlite->mutex);
1599
1600 return TCL_OK;
1601}
1602
1603
1604/*
1605** Register commands with the TCL interpreter.
1606*/
1607int Sqlitetest3_Init(Tcl_Interp *interp){
1608 extern int sqlite3_btree_trace;
1609 static struct {
1610 char *zName;
1611 Tcl_CmdProc *xProc;
1612 } aCmd[] = {
1613 { "btree_open", (Tcl_CmdProc*)btree_open },
1614 { "btree_close", (Tcl_CmdProc*)btree_close },
1615 { "btree_begin_transaction", (Tcl_CmdProc*)btree_begin_transaction },
1616 { "btree_commit", (Tcl_CmdProc*)btree_commit },
1617 { "btree_rollback", (Tcl_CmdProc*)btree_rollback },
1618 { "btree_create_table", (Tcl_CmdProc*)btree_create_table },
1619 { "btree_drop_table", (Tcl_CmdProc*)btree_drop_table },
1620 { "btree_clear_table", (Tcl_CmdProc*)btree_clear_table },
1621 { "btree_get_meta", (Tcl_CmdProc*)btree_get_meta },
1622 { "btree_update_meta", (Tcl_CmdProc*)btree_update_meta },
1623 { "btree_page_dump", (Tcl_CmdProc*)btree_page_dump },
1624 { "btree_tree_dump", (Tcl_CmdProc*)btree_tree_dump },
1625 { "btree_pager_stats", (Tcl_CmdProc*)btree_pager_stats },
1626 { "btree_pager_ref_dump", (Tcl_CmdProc*)btree_pager_ref_dump },
1627 { "btree_cursor", (Tcl_CmdProc*)btree_cursor },
1628 { "btree_close_cursor", (Tcl_CmdProc*)btree_close_cursor },
1629 { "btree_move_to", (Tcl_CmdProc*)btree_move_to },
1630 { "btree_delete", (Tcl_CmdProc*)btree_delete },
1631 { "btree_next", (Tcl_CmdProc*)btree_next },
1632 { "btree_prev", (Tcl_CmdProc*)btree_prev },
1633 { "btree_eof", (Tcl_CmdProc*)btree_eof },
1634 { "btree_keysize", (Tcl_CmdProc*)btree_keysize },
1635 { "btree_key", (Tcl_CmdProc*)btree_key },
1636 { "btree_data", (Tcl_CmdProc*)btree_data },
1637 { "btree_fetch_key", (Tcl_CmdProc*)btree_fetch_key },
1638 { "btree_fetch_data", (Tcl_CmdProc*)btree_fetch_data },
1639 { "btree_payload_size", (Tcl_CmdProc*)btree_payload_size },
1640 { "btree_first", (Tcl_CmdProc*)btree_first },
1641 { "btree_last", (Tcl_CmdProc*)btree_last },
1642 { "btree_integrity_check", (Tcl_CmdProc*)btree_integrity_check },
1643 { "btree_breakpoint", (Tcl_CmdProc*)btree_breakpoint },
1644 { "btree_varint_test", (Tcl_CmdProc*)btree_varint_test },
1645 { "btree_begin_statement", (Tcl_CmdProc*)btree_begin_statement },
1646 { "btree_commit_statement", (Tcl_CmdProc*)btree_commit_statement },
1647 { "btree_rollback_statement", (Tcl_CmdProc*)btree_rollback_statement },
1648 { "btree_from_db", (Tcl_CmdProc*)btree_from_db },
1649 { "btree_set_cache_size", (Tcl_CmdProc*)btree_set_cache_size },
1650 { "btree_cursor_info", (Tcl_CmdProc*)btree_cursor_info },
1651 { "btree_ovfl_info", (Tcl_CmdProc*)btree_ovfl_info },
1652 { "btree_cursor_list", (Tcl_CmdProc*)btree_cursor_list },
1653 };
1654 int i;
1655
1656 for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){
1657 Tcl_CreateCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0);
1658 }
1659 Tcl_LinkVar(interp, "pager_refinfo_enable", (char*)&pager3_refinfo_enable,
1660 TCL_LINK_INT);
1661 Tcl_LinkVar(interp, "btree_trace", (char*)&sqlite3_btree_trace,
1662 TCL_LINK_INT);
1663
1664 /* The btree_insert command is implemented using the tcl 'object'
1665 ** interface, not the string interface like the other commands in this
1666 ** file. This is so binary data can be inserted into btree tables.
1667 */
1668 Tcl_CreateObjCommand(interp, "btree_insert", btree_insert, 0, 0);
1669 return TCL_OK;
1670}