Index: third_party/sqlite_google/src/btree.c =================================================================== --- third_party/sqlite_google/src/btree.c (revision 1639) +++ third_party/sqlite_google/src/btree.c (working copy) @@ -29,6 +29,12 @@ */ static const char zPoisonHeader[] = "SQLite poison 3"; +/* +** The user cookie position in the database meta information +** (see prepare.c#215), incremented by one, because first position is actually +** the number of free pages in Btree (see vdbe.c#2521) +*/ +static const int kUserCookie = 6; /* ** Set this global variable to 1 to enable tracing using the TRACE @@ -6422,3 +6428,41 @@ } #endif + +int sqlite3_get_user_version(sqlite3 *sqlite, int *user_version) { + Btree *bt; + + if( sqlite == NULL ) return SQLITE_ERROR; + if( sqlite->nDb<1 ) return SQLITE_ERROR; + + /* grab actual (not temporary tables) database */ + bt = sqlite->aDb[0].pBt; + /* because sqlite3BtreeGetMeta sets a table read lock, it is safe to use + ** without explicit read transaction. Besides, it is very unlikely we will + ** ever call this outside of a transaction. + */ + return sqlite3BtreeGetMeta(bt, kUserCookie, (u32 *)user_version); +} + +int sqlite3_set_user_version(sqlite3 *sqlite, int user_version) { + Btree *bt; + int rc; + + if( sqlite == NULL ) return SQLITE_ERROR; + if( sqlite->nDb<1 ) return SQLITE_ERROR; + + bt = sqlite->aDb[0].pBt; + if( bt->inTrans!= TRANS_WRITE ) { + return sqlite3BtreeUpdateMeta(bt, kUserCookie, (u32)user_version); + }else{ + /* transacion isn't already in progress, have to enclose in + ** a write-transaction + */ + rc = sqlite3BtreeBeginTrans(bt, 1); + if( rc!=SQLITE_OK ) return rc; + rc = sqlite3BtreeUpdateMeta(bt, kUserCookie, (u32)user_version); + if( rc==SQLITE_OK ) return sqlite3BtreeCommit(bt); + sqlite3BtreeRollback(bt); + return rc; + } +}