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
[email protected]
http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users