1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-11-18 10:21:03 +03:00

Cause opening a transaction on a sharable b-tree module automatically obtain a read-lock on page 1. This means there is no way for sqlite3BtreeGetMeta() to fail. (CVS 6836)

FossilOrigin-Name: e3c055f167f895ae45858de9d9d8a264df2f36b6
This commit is contained in:
danielk1977
2009-07-02 07:47:33 +00:00
parent 325ccfa90e
commit 602b466e99
12 changed files with 168 additions and 163 deletions

View File

@@ -13,7 +13,7 @@
** interface, and routines that contribute to loading the database schema
** from disk.
**
** $Id: prepare.c,v 1.125 2009/06/25 11:50:21 drh Exp $
** $Id: prepare.c,v 1.126 2009/07/02 07:47:33 danielk1977 Exp $
*/
#include "sqliteInt.h"
@@ -128,7 +128,6 @@ int sqlite3InitCallback(void *pInit, int argc, char **argv, char **NotUsed){
static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
int rc;
int i;
BtCursor *curMain;
int size;
Table *pTab;
Db *pDb;
@@ -137,6 +136,7 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
InitData initData;
char const *zMasterSchema;
char const *zMasterName = SCHEMA_TABLE(iDb);
int openedTransaction;
/*
** The master database table has a structure like this
@@ -210,14 +210,21 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
}
return SQLITE_OK;
}
curMain = sqlite3MallocZero(sqlite3BtreeCursorSize());
if( !curMain ){
rc = SQLITE_NOMEM;
goto error_out;
}
/* If there is not already a read-only (or read-write) transaction opened
** on the b-tree database, open one now. If a transaction is opened, it
** will be closed before this function returns. */
sqlite3BtreeEnter(pDb->pBt);
rc = sqlite3BtreeCursor(pDb->pBt, MASTER_ROOT, 0, 0, curMain);
if( rc==SQLITE_EMPTY ) rc = SQLITE_OK;
if( !sqlite3BtreeIsInReadTrans(pDb->pBt) ){
rc = sqlite3BtreeBeginTrans(pDb->pBt, 0);
if( rc!=SQLITE_OK ){
sqlite3SetString(pzErrMsg, db, "%s", sqlite3ErrStr(rc));
goto initone_error_out;
}
openedTransaction = 1;
}else{
openedTransaction = 0;
}
/* Get the database meta information.
**
@@ -236,12 +243,8 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
** Note: The #defined SQLITE_UTF* symbols in sqliteInt.h correspond to
** the possible values of meta[4].
*/
for(i=0; rc==SQLITE_OK && i<ArraySize(meta); i++){
rc = sqlite3BtreeGetMeta(pDb->pBt, i+1, (u32 *)&meta[i]);
}
if( rc ){
sqlite3SetString(pzErrMsg, db, "%s", sqlite3ErrStr(rc));
goto initone_error_out;
for(i=0; i<ArraySize(meta); i++){
sqlite3BtreeGetMeta(pDb->pBt, i+1, (u32 *)&meta[i]);
}
pDb->pSchema->schema_cookie = meta[BTREE_SCHEMA_VERSION-1];
@@ -356,8 +359,9 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
** before that point, jump to error_out.
*/
initone_error_out:
sqlite3BtreeCloseCursor(curMain);
sqlite3_free(curMain);
if( openedTransaction ){
sqlite3BtreeCommit(pDb->pBt);
}
sqlite3BtreeLeave(pDb->pBt);
error_out:
@@ -437,13 +441,46 @@ int sqlite3ReadSchema(Parse *pParse){
** Check schema cookies in all databases. If any cookie is out
** of date, return 0. If all schema cookies are current, return 1.
*/
static int schemaIsValid(sqlite3 *db){
static void schemaIsValid(Parse *pParse){
sqlite3 *db = pParse->db;
int iDb;
int rc;
BtCursor *curTemp;
int cookie;
int allOk = 1;
assert( pParse->checkSchema );
assert( sqlite3_mutex_held(db->mutex) );
for(iDb=0; iDb<db->nDb; iDb++){
int openedTransaction = 0; /* True if a transaction is opened */
Btree *pBt = db->aDb[iDb].pBt; /* Btree database to read cookie from */
if( pBt==0 ) continue;
/* If there is not already a read-only (or read-write) transaction opened
** on the b-tree database, open one now. If a transaction is opened, it
** will be closed immediately after reading the meta-value. */
if( !sqlite3BtreeIsInReadTrans(pBt) ){
rc = sqlite3BtreeBeginTrans(pBt, 0);
if( NEVER(rc==SQLITE_NOMEM) || rc==SQLITE_IOERR_NOMEM ){
db->mallocFailed = 1;
}
if( rc!=SQLITE_OK ) return;
openedTransaction = 1;
}
/* Read the schema cookie from the database. If it does not match the
** value stored as part of the in the in-memory schema representation,
** set Parse.rc to SQLITE_SCHEMA. */
sqlite3BtreeGetMeta(pBt, BTREE_SCHEMA_VERSION, (u32 *)&cookie);
if( cookie!=db->aDb[iDb].pSchema->schema_cookie ){
pParse->rc = SQLITE_SCHEMA;
}
/* Close the transaction, if one was opened. */
if( openedTransaction ){
sqlite3BtreeCommit(pBt);
}
}
#if 0
curTemp = (BtCursor *)sqlite3Malloc(sqlite3BtreeCursorSize());
if( curTemp ){
assert( sqlite3_mutex_held(db->mutex) );
@@ -470,8 +507,8 @@ static int schemaIsValid(sqlite3 *db){
allOk = 0;
db->mallocFailed = 1;
}
return allOk;
#endif
}
/*
@@ -604,8 +641,8 @@ static int sqlite3Prepare(
pParse->rc = SQLITE_NOMEM;
}
if( pParse->rc==SQLITE_DONE ) pParse->rc = SQLITE_OK;
if( pParse->checkSchema && !schemaIsValid(db) ){
pParse->rc = SQLITE_SCHEMA;
if( pParse->checkSchema ){
schemaIsValid(pParse);
}
if( pParse->rc==SQLITE_SCHEMA ){
sqlite3ResetInternalSchema(db, 0);