I am developing an application that needs both SQL capability and also
simple Btree functions.  I searched the SQLite FAQ for information about
direct access to the Btree level, but was unable to find any help or
examples.  I have successfully gained access to the Btree routines after
making minor changes to the amalgamation source which I then compiled with
MS Visual Studio and linked with my application.

Note: Since the Btree routines are only semi-documented, and my procedure
requires changes to the SQLite source, there is no guarantee that this will
work with future versions.

Changes to SQLite amalgamation code:

1. Insert the following definition to make the routines externally callable
(rather than static):

#define SQLITE_PRIVATE

2. Extract the embedded Btree.h header file from the amalgamation and create
a Btree.h file.  The embedded section to be extracted is enclosed in:
_BTREE_H_ Use the Btree.h file with your application along with sqlite3.h.

3. Add the following routine which returns a pointer to the Btree structure
connected to a specified database handle:

/*--------------------------------------------------------------------------
------------
 *  Get a pointer to the Btree structure associated with an entry in the
database table.
 */
int sqlite3GetBtreePointer(sqlite3 *db, int dbIndex, Btree **pBt) {
    Db *pDb;
/*
 *  Get the Btree handle out of the database table.
 */
    pDb = &db->aDb[dbIndex];
    *pBt = pDb->pBt;
/*
 *  Finished
 */
    return(SQLITE_OK);

--  This is all the changes required to SQLite  --

Here is an example program that creates a database with a Btree table,
writes a couple of records to it and then verifies that it can be accessed.
The routine can be called to either create a new database or open and check
an existing one.

/*-----------------------------------------------------------------------
 *  Btree test.
 *
 *  Input arguments:
 *  Create = true to create a new database with a Btree table.
 *  Create = false to open an existing database and check it.
 */
void BtreeTest(bool Create)
{
    static char *FileName = "C:\\Test\\Btree.db";
    int status,Result;
    unsigned int DataSize;
    Btree *bt;
    sqlite3 *db;
    BtCursor *BtCursor;
    sqlite3_stmt *pStmt;
    int BtPage = -1;
    char *Key1 = "1";
    char *Data1 = "Record 1";
    char *Key2 = "2";
    char *Data2 = "Record 2";
    char buf[100],Command[200];

/*
 *  Decide if the test run should create the database and table or open an
existing one.
 */
    if (Create) {
/*
 *  Create a database with a Btree table.
 */
        /* Start with a new database */
        DeleteFile(FileName);
        /* Create a new database */
        status =
sqlite3_open_v2(FileName,&db,SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE,0);
        /* Get a pointer to the Btree for the primary database (# 0) */
        status = sqlite3GetBtreePointer(db,0,&bt);
        /* Create a Btree table within the database. We get back the root
page in BtPage */
        status = sqlite3BtreeBeginTrans(bt,1);
        status = sqlite3BtreeCreateTable(bt,&BtPage,0);
        status = sqlite3BtreeCommit(bt);
        /* Write the root page number of the Btree to a table so that we can
find it later */
        status = sqlite3_exec(db,"CREATE TABLE Configuration (BtreeName TEXT
UNIQUE, RootPage INTEGER)",0,0,0);
        sprintf(Command,"INSERT INTO Configuration VALUES
(\'MyBtree\',%d)",BtPage);
        status = sqlite3_exec(db,Command,0,0,0);
        /* Create a cursor to go with the Btree (BtPage is the root page
index #) */
        status = sqlite3BtreeCursor(bt,BtPage,1,0,0,&BtCursor);
        /* Write a couple of records to the Btree table */
        status = sqlite3BtreeBeginTrans(bt,1);
        status =
sqlite3BtreeInsert(BtCursor,Key1,1,Data1,strlen(Data1)+1,0,0);
        status =
sqlite3BtreeInsert(BtCursor,Key2,1,Data2,strlen(Data2)+1,0,0);
        status = sqlite3BtreeCommit(bt);
    } else {
/*
 *  Open an existing Btree.
 */
        /* Open an existing database */
        status = sqlite3_open_v2(FileName,&db,SQLITE_OPEN_READWRITE,0);
        /* Get a pointer to the Btree structure associated with database 0
*/
        status = sqlite3GetBtreePointer(db,0,&bt);
        /* Get the root page number of the Btree out of our Configuration
table */
        sprintf(Command,"SELECT RootPage FROM Configuration WHERE
BtreeName=\'MyBtree\'");
        status = sqlite3_prepare_v2(db,Command,-1,&pStmt,0);
        status = sqlite3_step(pStmt);
        ASSERT(status == SQLITE_ROW);
        BtPage = sqlite3_column_int(pStmt,0);
        sqlite3_finalize(pStmt);
    }
/*
 *  Read from the Btree and verify the data.
 */
    /* Create a cursor associated with the Btree (the BtPage index selects
the Btree) */
    status = sqlite3BtreeCursor(bt,BtPage,1,0,0,&BtCursor);
    /* Check if we can read the first record */
    status = sqlite3BtreeMoveto(BtCursor,Key1,1,0,&Result);
    status = sqlite3BtreeDataSize(BtCursor,&DataSize);
    status = sqlite3BtreeData(BtCursor,0,DataSize,buf);
    ASSERT(strcmp(buf,Data1) == 0);
    /* Check if we can read the second record */
    status = sqlite3BtreeMoveto(BtCursor,Key2,1,0,&Result);
    status = sqlite3BtreeDataSize(BtCursor,&DataSize);
    status = sqlite3BtreeData(BtCursor,0,DataSize,buf);
    ASSERT(strcmp(buf,Data2) == 0);
    /* Close the cursor */
    status = sqlite3BtreeCloseCursor(BtCursor);
/*
 *  Close the database.
 */
    status = sqlite3_close(db);
/*
 *  Finished
 */
    return;
}

I would like to see the Btree routines documented and supported.

Phil Sherrod


_______________________________________________
sqlite-users mailing list
sqlite-users@sqlite.org
http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users

Reply via email to