00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "sqliteInt.h"
00019 #include "pager.h"
00020 #include "btree.h"
00021 #include "tcl.h"
00022 #include <stdlib.h>
00023 #include <string.h>
00024
00025
00026
00027
00028 static char *errorName(int rc){
00029 char *zName;
00030 switch( rc ){
00031 case SQLITE_OK: zName = "SQLITE_OK"; break;
00032 case SQLITE_ERROR: zName = "SQLITE_ERROR"; break;
00033 case SQLITE_INTERNAL: zName = "SQLITE_INTERNAL"; break;
00034 case SQLITE_PERM: zName = "SQLITE_PERM"; break;
00035 case SQLITE_ABORT: zName = "SQLITE_ABORT"; break;
00036 case SQLITE_BUSY: zName = "SQLITE_BUSY"; break;
00037 case SQLITE_NOMEM: zName = "SQLITE_NOMEM"; break;
00038 case SQLITE_READONLY: zName = "SQLITE_READONLY"; break;
00039 case SQLITE_INTERRUPT: zName = "SQLITE_INTERRUPT"; break;
00040 case SQLITE_IOERR: zName = "SQLITE_IOERR"; break;
00041 case SQLITE_CORRUPT: zName = "SQLITE_CORRUPT"; break;
00042 case SQLITE_NOTFOUND: zName = "SQLITE_NOTFOUND"; break;
00043 case SQLITE_FULL: zName = "SQLITE_FULL"; break;
00044 case SQLITE_CANTOPEN: zName = "SQLITE_CANTOPEN"; break;
00045 case SQLITE_PROTOCOL: zName = "SQLITE_PROTOCOL"; break;
00046 default: zName = "SQLITE_Unknown"; break;
00047 }
00048 return zName;
00049 }
00050
00051
00052
00053
00054
00055
00056 static int btree_open(
00057 void *NotUsed,
00058 Tcl_Interp *interp,
00059 int argc,
00060 const char **argv
00061 ){
00062 Btree *pBt;
00063 int rc;
00064 char zBuf[100];
00065 if( argc!=2 ){
00066 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
00067 " FILENAME\"", 0);
00068 return TCL_ERROR;
00069 }
00070 rc = sqliteBtreeFactory(0, argv[1], 0, 1000, &pBt);
00071 if( rc!=SQLITE_OK ){
00072 Tcl_AppendResult(interp, errorName(rc), 0);
00073 return TCL_ERROR;
00074 }
00075 sprintf(zBuf,"%p", pBt);
00076 if( strncmp(zBuf,"0x",2) ){
00077 sprintf(zBuf, "0x%p", pBt);
00078 }
00079 Tcl_AppendResult(interp, zBuf, 0);
00080 return TCL_OK;
00081 }
00082
00083
00084
00085
00086
00087
00088 static int btree_close(
00089 void *NotUsed,
00090 Tcl_Interp *interp,
00091 int argc,
00092 const char **argv
00093 ){
00094 Btree *pBt;
00095 int rc;
00096 if( argc!=2 ){
00097 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
00098 " ID\"", 0);
00099 return TCL_ERROR;
00100 }
00101 if( Tcl_GetInt(interp, argv[1], (int*)&pBt) ) return TCL_ERROR;
00102 rc = sqliteBtreeClose(pBt);
00103 if( rc!=SQLITE_OK ){
00104 Tcl_AppendResult(interp, errorName(rc), 0);
00105 return TCL_ERROR;
00106 }
00107 return TCL_OK;
00108 }
00109
00110
00111
00112
00113
00114
00115 static int btree_begin_transaction(
00116 void *NotUsed,
00117 Tcl_Interp *interp,
00118 int argc,
00119 const char **argv
00120 ){
00121 Btree *pBt;
00122 int rc;
00123 if( argc!=2 ){
00124 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
00125 " ID\"", 0);
00126 return TCL_ERROR;
00127 }
00128 if( Tcl_GetInt(interp, argv[1], (int*)&pBt) ) return TCL_ERROR;
00129 rc = sqliteBtreeBeginTrans(pBt);
00130 if( rc!=SQLITE_OK ){
00131 Tcl_AppendResult(interp, errorName(rc), 0);
00132 return TCL_ERROR;
00133 }
00134 return TCL_OK;
00135 }
00136
00137
00138
00139
00140
00141
00142 static int btree_rollback(
00143 void *NotUsed,
00144 Tcl_Interp *interp,
00145 int argc,
00146 const char **argv
00147 ){
00148 Btree *pBt;
00149 int rc;
00150 if( argc!=2 ){
00151 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
00152 " ID\"", 0);
00153 return TCL_ERROR;
00154 }
00155 if( Tcl_GetInt(interp, argv[1], (int*)&pBt) ) return TCL_ERROR;
00156 rc = sqliteBtreeRollback(pBt);
00157 if( rc!=SQLITE_OK ){
00158 Tcl_AppendResult(interp, errorName(rc), 0);
00159 return TCL_ERROR;
00160 }
00161 return TCL_OK;
00162 }
00163
00164
00165
00166
00167
00168
00169 static int btree_commit(
00170 void *NotUsed,
00171 Tcl_Interp *interp,
00172 int argc,
00173 const char **argv
00174 ){
00175 Btree *pBt;
00176 int rc;
00177 if( argc!=2 ){
00178 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
00179 " ID\"", 0);
00180 return TCL_ERROR;
00181 }
00182 if( Tcl_GetInt(interp, argv[1], (int*)&pBt) ) return TCL_ERROR;
00183 rc = sqliteBtreeCommit(pBt);
00184 if( rc!=SQLITE_OK ){
00185 Tcl_AppendResult(interp, errorName(rc), 0);
00186 return TCL_ERROR;
00187 }
00188 return TCL_OK;
00189 }
00190
00191
00192
00193
00194
00195
00196 static int btree_create_table(
00197 void *NotUsed,
00198 Tcl_Interp *interp,
00199 int argc,
00200 const char **argv
00201 ){
00202 Btree *pBt;
00203 int rc, iTable;
00204 char zBuf[30];
00205 if( argc!=2 ){
00206 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
00207 " ID\"", 0);
00208 return TCL_ERROR;
00209 }
00210 if( Tcl_GetInt(interp, argv[1], (int*)&pBt) ) return TCL_ERROR;
00211 rc = sqliteBtreeCreateTable(pBt, &iTable);
00212 if( rc!=SQLITE_OK ){
00213 Tcl_AppendResult(interp, errorName(rc), 0);
00214 return TCL_ERROR;
00215 }
00216 sprintf(zBuf, "%d", iTable);
00217 Tcl_AppendResult(interp, zBuf, 0);
00218 return TCL_OK;
00219 }
00220
00221
00222
00223
00224
00225
00226 static int btree_drop_table(
00227 void *NotUsed,
00228 Tcl_Interp *interp,
00229 int argc,
00230 const char **argv
00231 ){
00232 Btree *pBt;
00233 int iTable;
00234 int rc;
00235 if( argc!=3 ){
00236 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
00237 " ID TABLENUM\"", 0);
00238 return TCL_ERROR;
00239 }
00240 if( Tcl_GetInt(interp, argv[1], (int*)&pBt) ) return TCL_ERROR;
00241 if( Tcl_GetInt(interp, argv[2], &iTable) ) return TCL_ERROR;
00242 rc = sqliteBtreeDropTable(pBt, iTable);
00243 if( rc!=SQLITE_OK ){
00244 Tcl_AppendResult(interp, errorName(rc), 0);
00245 return TCL_ERROR;
00246 }
00247 return TCL_OK;
00248 }
00249
00250
00251
00252
00253
00254
00255 static int btree_clear_table(
00256 void *NotUsed,
00257 Tcl_Interp *interp,
00258 int argc,
00259 const char **argv
00260 ){
00261 Btree *pBt;
00262 int iTable;
00263 int rc;
00264 if( argc!=3 ){
00265 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
00266 " ID TABLENUM\"", 0);
00267 return TCL_ERROR;
00268 }
00269 if( Tcl_GetInt(interp, argv[1], (int*)&pBt) ) return TCL_ERROR;
00270 if( Tcl_GetInt(interp, argv[2], &iTable) ) return TCL_ERROR;
00271 rc = sqliteBtreeClearTable(pBt, iTable);
00272 if( rc!=SQLITE_OK ){
00273 Tcl_AppendResult(interp, errorName(rc), 0);
00274 return TCL_ERROR;
00275 }
00276 return TCL_OK;
00277 }
00278
00279
00280
00281
00282
00283
00284 static int btree_get_meta(
00285 void *NotUsed,
00286 Tcl_Interp *interp,
00287 int argc,
00288 const char **argv
00289 ){
00290 Btree *pBt;
00291 int rc;
00292 int i;
00293 int aMeta[SQLITE_N_BTREE_META];
00294 if( argc!=2 ){
00295 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
00296 " ID\"", 0);
00297 return TCL_ERROR;
00298 }
00299 if( Tcl_GetInt(interp, argv[1], (int*)&pBt) ) return TCL_ERROR;
00300 rc = sqliteBtreeGetMeta(pBt, aMeta);
00301 if( rc!=SQLITE_OK ){
00302 Tcl_AppendResult(interp, errorName(rc), 0);
00303 return TCL_ERROR;
00304 }
00305 for(i=0; i<SQLITE_N_BTREE_META; i++){
00306 char zBuf[30];
00307 sprintf(zBuf,"%d",aMeta[i]);
00308 Tcl_AppendElement(interp, zBuf);
00309 }
00310 return TCL_OK;
00311 }
00312
00313
00314
00315
00316
00317
00318 static int btree_update_meta(
00319 void *NotUsed,
00320 Tcl_Interp *interp,
00321 int argc,
00322 const char **argv
00323 ){
00324 Btree *pBt;
00325 int rc;
00326 int i;
00327 int aMeta[SQLITE_N_BTREE_META];
00328
00329 if( argc!=2+SQLITE_N_BTREE_META ){
00330 char zBuf[30];
00331 sprintf(zBuf,"%d",SQLITE_N_BTREE_META);
00332 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
00333 " ID METADATA...\" (METADATA is ", zBuf, " integers)", 0);
00334 return TCL_ERROR;
00335 }
00336 if( Tcl_GetInt(interp, argv[1], (int*)&pBt) ) return TCL_ERROR;
00337 for(i=0; i<SQLITE_N_BTREE_META; i++){
00338 if( Tcl_GetInt(interp, argv[i+2], &aMeta[i]) ) return TCL_ERROR;
00339 }
00340 rc = sqliteBtreeUpdateMeta(pBt, aMeta);
00341 if( rc!=SQLITE_OK ){
00342 Tcl_AppendResult(interp, errorName(rc), 0);
00343 return TCL_ERROR;
00344 }
00345 return TCL_OK;
00346 }
00347
00348
00349
00350
00351
00352
00353 static int btree_page_dump(
00354 void *NotUsed,
00355 Tcl_Interp *interp,
00356 int argc,
00357 const char **argv
00358 ){
00359 Btree *pBt;
00360 int iPage;
00361 int rc;
00362
00363 if( argc!=3 ){
00364 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
00365 " ID\"", 0);
00366 return TCL_ERROR;
00367 }
00368 if( Tcl_GetInt(interp, argv[1], (int*)&pBt) ) return TCL_ERROR;
00369 if( Tcl_GetInt(interp, argv[2], &iPage) ) return TCL_ERROR;
00370 rc = sqliteBtreePageDump(pBt, iPage, 0);
00371 if( rc!=SQLITE_OK ){
00372 Tcl_AppendResult(interp, errorName(rc), 0);
00373 return TCL_ERROR;
00374 }
00375 return TCL_OK;
00376 }
00377
00378
00379
00380
00381
00382
00383 static int btree_tree_dump(
00384 void *NotUsed,
00385 Tcl_Interp *interp,
00386 int argc,
00387 const char **argv
00388 ){
00389 Btree *pBt;
00390 int iPage;
00391 int rc;
00392
00393 if( argc!=3 ){
00394 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
00395 " ID\"", 0);
00396 return TCL_ERROR;
00397 }
00398 if( Tcl_GetInt(interp, argv[1], (int*)&pBt) ) return TCL_ERROR;
00399 if( Tcl_GetInt(interp, argv[2], &iPage) ) return TCL_ERROR;
00400 rc = sqliteBtreePageDump(pBt, iPage, 1);
00401 if( rc!=SQLITE_OK ){
00402 Tcl_AppendResult(interp, errorName(rc), 0);
00403 return TCL_ERROR;
00404 }
00405 return TCL_OK;
00406 }
00407
00408
00409
00410
00411
00412
00413 static int btree_pager_stats(
00414 void *NotUsed,
00415 Tcl_Interp *interp,
00416 int argc,
00417 const char **argv
00418 ){
00419 Btree *pBt;
00420 int i;
00421 int *a;
00422
00423 if( argc!=2 ){
00424 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
00425 " ID\"", 0);
00426 return TCL_ERROR;
00427 }
00428 if( Tcl_GetInt(interp, argv[1], (int*)&pBt) ) return TCL_ERROR;
00429 a = sqlitepager_stats(sqliteBtreePager(pBt));
00430 for(i=0; i<9; i++){
00431 static char *zName[] = {
00432 "ref", "page", "max", "size", "state", "err",
00433 "hit", "miss", "ovfl",
00434 };
00435 char zBuf[100];
00436 Tcl_AppendElement(interp, zName[i]);
00437 sprintf(zBuf,"%d",a[i]);
00438 Tcl_AppendElement(interp, zBuf);
00439 }
00440 return TCL_OK;
00441 }
00442
00443
00444
00445
00446
00447
00448 static int btree_pager_ref_dump(
00449 void *NotUsed,
00450 Tcl_Interp *interp,
00451 int argc,
00452 const char **argv
00453 ){
00454 Btree *pBt;
00455
00456 if( argc!=2 ){
00457 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
00458 " ID\"", 0);
00459 return TCL_ERROR;
00460 }
00461 if( Tcl_GetInt(interp, argv[1], (int*)&pBt) ) return TCL_ERROR;
00462 sqlitepager_refdump(sqliteBtreePager(pBt));
00463 return TCL_OK;
00464 }
00465
00466
00467
00468
00469
00470
00471
00472
00473 static int btree_integrity_check(
00474 void *NotUsed,
00475 Tcl_Interp *interp,
00476 int argc,
00477 const char **argv
00478 ){
00479 Btree *pBt;
00480 char *zResult;
00481 int nRoot;
00482 int *aRoot;
00483 int i;
00484
00485 if( argc<3 ){
00486 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
00487 " ID ROOT ...\"", 0);
00488 return TCL_ERROR;
00489 }
00490 if( Tcl_GetInt(interp, argv[1], (int*)&pBt) ) return TCL_ERROR;
00491 nRoot = argc-2;
00492 aRoot = malloc( sizeof(int)*(argc-2) );
00493 for(i=0; i<argc-2; i++){
00494 if( Tcl_GetInt(interp, argv[i+2], &aRoot[i]) ) return TCL_ERROR;
00495 }
00496 zResult = sqliteBtreeIntegrityCheck(pBt, aRoot, nRoot);
00497 if( zResult ){
00498 Tcl_AppendResult(interp, zResult, 0);
00499 sqliteFree(zResult);
00500 }
00501 return TCL_OK;
00502 }
00503
00504
00505
00506
00507
00508
00509 static int btree_cursor(
00510 void *NotUsed,
00511 Tcl_Interp *interp,
00512 int argc,
00513 const char **argv
00514 ){
00515 Btree *pBt;
00516 int iTable;
00517 BtCursor *pCur;
00518 int rc;
00519 int wrFlag;
00520 char zBuf[30];
00521
00522 if( argc!=4 ){
00523 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
00524 " ID TABLENUM WRITEABLE\"", 0);
00525 return TCL_ERROR;
00526 }
00527 if( Tcl_GetInt(interp, argv[1], (int*)&pBt) ) return TCL_ERROR;
00528 if( Tcl_GetInt(interp, argv[2], &iTable) ) return TCL_ERROR;
00529 if( Tcl_GetBoolean(interp, argv[3], &wrFlag) ) return TCL_ERROR;
00530 rc = sqliteBtreeCursor(pBt, iTable, wrFlag, &pCur);
00531 if( rc ){
00532 Tcl_AppendResult(interp, errorName(rc), 0);
00533 return TCL_ERROR;
00534 }
00535 sprintf(zBuf,"0x%x", (int)pCur);
00536 Tcl_AppendResult(interp, zBuf, 0);
00537 return SQLITE_OK;
00538 }
00539
00540
00541
00542
00543
00544
00545 static int btree_close_cursor(
00546 void *NotUsed,
00547 Tcl_Interp *interp,
00548 int argc,
00549 const char **argv
00550 ){
00551 BtCursor *pCur;
00552 int rc;
00553
00554 if( argc!=2 ){
00555 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
00556 " ID\"", 0);
00557 return TCL_ERROR;
00558 }
00559 if( Tcl_GetInt(interp, argv[1], (int*)&pCur) ) return TCL_ERROR;
00560 rc = sqliteBtreeCloseCursor(pCur);
00561 if( rc ){
00562 Tcl_AppendResult(interp, errorName(rc), 0);
00563 return TCL_ERROR;
00564 }
00565 return SQLITE_OK;
00566 }
00567
00568
00569
00570
00571
00572
00573 static int btree_move_to(
00574 void *NotUsed,
00575 Tcl_Interp *interp,
00576 int argc,
00577 const char **argv
00578 ){
00579 BtCursor *pCur;
00580 int rc;
00581 int res;
00582 char zBuf[20];
00583
00584 if( argc!=3 ){
00585 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
00586 " ID KEY\"", 0);
00587 return TCL_ERROR;
00588 }
00589 if( Tcl_GetInt(interp, argv[1], (int*)&pCur) ) return TCL_ERROR;
00590 rc = sqliteBtreeMoveto(pCur, argv[2], strlen(argv[2]), &res);
00591 if( rc ){
00592 Tcl_AppendResult(interp, errorName(rc), 0);
00593 return TCL_ERROR;
00594 }
00595 if( res<0 ) res = -1;
00596 if( res>0 ) res = 1;
00597 sprintf(zBuf,"%d",res);
00598 Tcl_AppendResult(interp, zBuf, 0);
00599 return SQLITE_OK;
00600 }
00601
00602
00603
00604
00605
00606
00607 static int btree_delete(
00608 void *NotUsed,
00609 Tcl_Interp *interp,
00610 int argc,
00611 const char **argv
00612 ){
00613 BtCursor *pCur;
00614 int rc;
00615
00616 if( argc!=2 ){
00617 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
00618 " ID\"", 0);
00619 return TCL_ERROR;
00620 }
00621 if( Tcl_GetInt(interp, argv[1], (int*)&pCur) ) return TCL_ERROR;
00622 rc = sqliteBtreeDelete(pCur);
00623 if( rc ){
00624 Tcl_AppendResult(interp, errorName(rc), 0);
00625 return TCL_ERROR;
00626 }
00627 return SQLITE_OK;
00628 }
00629
00630
00631
00632
00633
00634
00635
00636 static int btree_insert(
00637 void *NotUsed,
00638 Tcl_Interp *interp,
00639 int argc,
00640 const char **argv
00641 ){
00642 BtCursor *pCur;
00643 int rc;
00644
00645 if( argc!=4 ){
00646 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
00647 " ID KEY DATA\"", 0);
00648 return TCL_ERROR;
00649 }
00650 if( Tcl_GetInt(interp, argv[1], (int*)&pCur) ) return TCL_ERROR;
00651 rc = sqliteBtreeInsert(pCur, argv[2], strlen(argv[2]),
00652 argv[3], strlen(argv[3]));
00653 if( rc ){
00654 Tcl_AppendResult(interp, errorName(rc), 0);
00655 return TCL_ERROR;
00656 }
00657 return SQLITE_OK;
00658 }
00659
00660
00661
00662
00663
00664
00665
00666
00667 static int btree_next(
00668 void *NotUsed,
00669 Tcl_Interp *interp,
00670 int argc,
00671 const char **argv
00672 ){
00673 BtCursor *pCur;
00674 int rc;
00675 int res = 0;
00676 char zBuf[100];
00677
00678 if( argc!=2 ){
00679 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
00680 " ID\"", 0);
00681 return TCL_ERROR;
00682 }
00683 if( Tcl_GetInt(interp, argv[1], (int*)&pCur) ) return TCL_ERROR;
00684 rc = sqliteBtreeNext(pCur, &res);
00685 if( rc ){
00686 Tcl_AppendResult(interp, errorName(rc), 0);
00687 return TCL_ERROR;
00688 }
00689 sprintf(zBuf,"%d",res);
00690 Tcl_AppendResult(interp, zBuf, 0);
00691 return SQLITE_OK;
00692 }
00693
00694
00695
00696
00697
00698
00699
00700
00701 static int btree_prev(
00702 void *NotUsed,
00703 Tcl_Interp *interp,
00704 int argc,
00705 const char **argv
00706 ){
00707 BtCursor *pCur;
00708 int rc;
00709 int res = 0;
00710 char zBuf[100];
00711
00712 if( argc!=2 ){
00713 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
00714 " ID\"", 0);
00715 return TCL_ERROR;
00716 }
00717 if( Tcl_GetInt(interp, argv[1], (int*)&pCur) ) return TCL_ERROR;
00718 rc = sqliteBtreePrevious(pCur, &res);
00719 if( rc ){
00720 Tcl_AppendResult(interp, errorName(rc), 0);
00721 return TCL_ERROR;
00722 }
00723 sprintf(zBuf,"%d",res);
00724 Tcl_AppendResult(interp, zBuf, 0);
00725 return SQLITE_OK;
00726 }
00727
00728
00729
00730
00731
00732
00733
00734 static int btree_first(
00735 void *NotUsed,
00736 Tcl_Interp *interp,
00737 int argc,
00738 const char **argv
00739 ){
00740 BtCursor *pCur;
00741 int rc;
00742 int res = 0;
00743 char zBuf[100];
00744
00745 if( argc!=2 ){
00746 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
00747 " ID\"", 0);
00748 return TCL_ERROR;
00749 }
00750 if( Tcl_GetInt(interp, argv[1], (int*)&pCur) ) return TCL_ERROR;
00751 rc = sqliteBtreeFirst(pCur, &res);
00752 if( rc ){
00753 Tcl_AppendResult(interp, errorName(rc), 0);
00754 return TCL_ERROR;
00755 }
00756 sprintf(zBuf,"%d",res);
00757 Tcl_AppendResult(interp, zBuf, 0);
00758 return SQLITE_OK;
00759 }
00760
00761
00762
00763
00764
00765
00766
00767 static int btree_last(
00768 void *NotUsed,
00769 Tcl_Interp *interp,
00770 int argc,
00771 const char **argv
00772 ){
00773 BtCursor *pCur;
00774 int rc;
00775 int res = 0;
00776 char zBuf[100];
00777
00778 if( argc!=2 ){
00779 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
00780 " ID\"", 0);
00781 return TCL_ERROR;
00782 }
00783 if( Tcl_GetInt(interp, argv[1], (int*)&pCur) ) return TCL_ERROR;
00784 rc = sqliteBtreeLast(pCur, &res);
00785 if( rc ){
00786 Tcl_AppendResult(interp, errorName(rc), 0);
00787 return TCL_ERROR;
00788 }
00789 sprintf(zBuf,"%d",res);
00790 Tcl_AppendResult(interp, zBuf, 0);
00791 return SQLITE_OK;
00792 }
00793
00794
00795
00796
00797
00798
00799 static int btree_key(
00800 void *NotUsed,
00801 Tcl_Interp *interp,
00802 int argc,
00803 const char **argv
00804 ){
00805 BtCursor *pCur;
00806 int rc;
00807 int n;
00808 char *zBuf;
00809
00810 if( argc!=2 ){
00811 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
00812 " ID\"", 0);
00813 return TCL_ERROR;
00814 }
00815 if( Tcl_GetInt(interp, argv[1], (int*)&pCur) ) return TCL_ERROR;
00816 sqliteBtreeKeySize(pCur, &n);
00817 zBuf = malloc( n+1 );
00818 rc = sqliteBtreeKey(pCur, 0, n, zBuf);
00819 if( rc!=n ){
00820 char zMsg[100];
00821 free(zBuf);
00822 sprintf(zMsg, "truncated key: got %d of %d bytes", rc, n);
00823 Tcl_AppendResult(interp, zMsg, 0);
00824 return TCL_ERROR;
00825 }
00826 zBuf[n] = 0;
00827 Tcl_AppendResult(interp, zBuf, 0);
00828 free(zBuf);
00829 return SQLITE_OK;
00830 }
00831
00832
00833
00834
00835
00836
00837 static int btree_data(
00838 void *NotUsed,
00839 Tcl_Interp *interp,
00840 int argc,
00841 const char **argv
00842 ){
00843 BtCursor *pCur;
00844 int rc;
00845 int n;
00846 char *zBuf;
00847
00848 if( argc!=2 ){
00849 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
00850 " ID\"", 0);
00851 return TCL_ERROR;
00852 }
00853 if( Tcl_GetInt(interp, argv[1], (int*)&pCur) ) return TCL_ERROR;
00854 sqliteBtreeDataSize(pCur, &n);
00855 zBuf = malloc( n+1 );
00856 rc = sqliteBtreeData(pCur, 0, n, zBuf);
00857 if( rc!=n ){
00858 char zMsg[100];
00859 free(zBuf);
00860 sprintf(zMsg, "truncated data: got %d of %d bytes", rc, n);
00861 Tcl_AppendResult(interp, zMsg, 0);
00862 return TCL_ERROR;
00863 }
00864 zBuf[n] = 0;
00865 Tcl_AppendResult(interp, zBuf, 0);
00866 free(zBuf);
00867 return SQLITE_OK;
00868 }
00869
00870
00871
00872
00873
00874
00875 static int btree_payload_size(
00876 void *NotUsed,
00877 Tcl_Interp *interp,
00878 int argc,
00879 const char **argv
00880 ){
00881 BtCursor *pCur;
00882 int n1, n2;
00883 char zBuf[50];
00884
00885 if( argc!=2 ){
00886 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
00887 " ID\"", 0);
00888 return TCL_ERROR;
00889 }
00890 if( Tcl_GetInt(interp, argv[1], (int*)&pCur) ) return TCL_ERROR;
00891 sqliteBtreeKeySize(pCur, &n1);
00892 sqliteBtreeDataSize(pCur, &n2);
00893 sprintf(zBuf, "%d", n1+n2);
00894 Tcl_AppendResult(interp, zBuf, 0);
00895 return SQLITE_OK;
00896 }
00897
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907
00908
00909
00910
00911
00912
00913 static int btree_cursor_dump(
00914 void *NotUsed,
00915 Tcl_Interp *interp,
00916 int argc,
00917 const char **argv
00918 ){
00919 BtCursor *pCur;
00920 int rc;
00921 int i, j;
00922 int aResult[8];
00923 char zBuf[400];
00924
00925 if( argc!=2 ){
00926 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
00927 " ID\"", 0);
00928 return TCL_ERROR;
00929 }
00930 if( Tcl_GetInt(interp, argv[1], (int*)&pCur) ) return TCL_ERROR;
00931 rc = sqliteBtreeCursorDump(pCur, aResult);
00932 if( rc ){
00933 Tcl_AppendResult(interp, errorName(rc), 0);
00934 return TCL_ERROR;
00935 }
00936 j = 0;
00937 for(i=0; i<sizeof(aResult)/sizeof(aResult[0]); i++){
00938 sprintf(&zBuf[j]," %d", aResult[i]);
00939 j += strlen(&zBuf[j]);
00940 }
00941 Tcl_AppendResult(interp, &zBuf[1], 0);
00942 return SQLITE_OK;
00943 }
00944
00945
00946
00947
00948 int Sqlitetest3_Init(Tcl_Interp *interp){
00949 static struct {
00950 char *zName;
00951 Tcl_CmdProc *xProc;
00952 } aCmd[] = {
00953 { "btree_open", (Tcl_CmdProc*)btree_open },
00954 { "btree_close", (Tcl_CmdProc*)btree_close },
00955 { "btree_begin_transaction", (Tcl_CmdProc*)btree_begin_transaction },
00956 { "btree_commit", (Tcl_CmdProc*)btree_commit },
00957 { "btree_rollback", (Tcl_CmdProc*)btree_rollback },
00958 { "btree_create_table", (Tcl_CmdProc*)btree_create_table },
00959 { "btree_drop_table", (Tcl_CmdProc*)btree_drop_table },
00960 { "btree_clear_table", (Tcl_CmdProc*)btree_clear_table },
00961 { "btree_get_meta", (Tcl_CmdProc*)btree_get_meta },
00962 { "btree_update_meta", (Tcl_CmdProc*)btree_update_meta },
00963 { "btree_page_dump", (Tcl_CmdProc*)btree_page_dump },
00964 { "btree_tree_dump", (Tcl_CmdProc*)btree_tree_dump },
00965 { "btree_pager_stats", (Tcl_CmdProc*)btree_pager_stats },
00966 { "btree_pager_ref_dump", (Tcl_CmdProc*)btree_pager_ref_dump },
00967 { "btree_cursor", (Tcl_CmdProc*)btree_cursor },
00968 { "btree_close_cursor", (Tcl_CmdProc*)btree_close_cursor },
00969 { "btree_move_to", (Tcl_CmdProc*)btree_move_to },
00970 { "btree_delete", (Tcl_CmdProc*)btree_delete },
00971 { "btree_insert", (Tcl_CmdProc*)btree_insert },
00972 { "btree_next", (Tcl_CmdProc*)btree_next },
00973 { "btree_prev", (Tcl_CmdProc*)btree_prev },
00974 { "btree_key", (Tcl_CmdProc*)btree_key },
00975 { "btree_data", (Tcl_CmdProc*)btree_data },
00976 { "btree_payload_size", (Tcl_CmdProc*)btree_payload_size },
00977 { "btree_first", (Tcl_CmdProc*)btree_first },
00978 { "btree_last", (Tcl_CmdProc*)btree_last },
00979 { "btree_cursor_dump", (Tcl_CmdProc*)btree_cursor_dump },
00980 { "btree_integrity_check", (Tcl_CmdProc*)btree_integrity_check },
00981 };
00982 int i;
00983
00984 for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){
00985 Tcl_CreateCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0);
00986 }
00987 Tcl_LinkVar(interp, "pager_refinfo_enable", (char*)&pager_refinfo_enable,
00988 TCL_LINK_INT);
00989 Tcl_LinkVar(interp, "btree_native_byte_order",(char*)&btree_native_byte_order,
00990 TCL_LINK_INT);
00991 return TCL_OK;
00992 }