Hi Phil and list! Thank you for this very instructive post about SQLite's internals and btrees. I'm just curious about what could be real-life use cases of having direct access to the btree stuff. As I understand your example, you store (key,value) pairs inside the btree and then get them back. Then, what's the purpose of not using a normal SQLite table to do so?
On the other hand, since those "direct btree information" are necessarily stored inside a reguar SQLite file, doesn't this introduce possible side effects with other functions of the sqlite library, which would not be aware that some btree roots inside the file are neither a table nor an index? (vacuum, etc.) Last but not least, I am currently developping a virtual table and I've just realized that I could use SQLite btrees for indexing data coming from an "external database" (cf recent thread about virtual tables and access to big external databases). According to you, would it be a good idea to use this technique in order to implement an alternative indexing technique (for "external tables") based on SQLite btrees? Thanks a lot for sharing about that, any help would be greatly appreciated, Aladdin > From: [EMAIL PROTECTED] > To: sqlite-users@sqlite.org > Date: Mon, 7 Apr 2008 19:28:30 -0500 > Subject: [sqlite] Direct access to Btree routines in SQLite > > 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 _________________________________________________________________ Créez votre disque dur virtuel Windows Live SkyDrive, 5Go de stockage gratuit ! http://www.windowslive.fr/skydrive/ _______________________________________________ sqlite-users mailing list sqlite-users@sqlite.org http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users