aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/attach.c10
-rw-r--r--src/btree.c19
2 files changed, 25 insertions, 4 deletions
diff --git a/src/attach.c b/src/attach.c
index d5495361b..d0f81766b 100644
--- a/src/attach.c
+++ b/src/attach.c
@@ -11,7 +11,7 @@
*************************************************************************
** This file contains code used to implement the ATTACH and DETACH commands.
**
-** $Id: attach.c,v 1.87 2009/04/30 05:40:34 drh Exp $
+** $Id: attach.c,v 1.88 2009/04/30 13:30:33 drh Exp $
*/
#include "sqliteInt.h"
@@ -119,7 +119,7 @@ static void attachFunc(
if( aNew==0 ) return;
}
db->aDb = aNew;
- aNew = &db->aDb[db->nDb++];
+ aNew = &db->aDb[db->nDb];
memset(aNew, 0, sizeof(*aNew));
/* Open the database file. If the btree is successfully opened, use
@@ -129,7 +129,11 @@ static void attachFunc(
rc = sqlite3BtreeFactory(db, zFile, 0, SQLITE_DEFAULT_CACHE_SIZE,
db->openFlags | SQLITE_OPEN_MAIN_DB,
&aNew->pBt);
- if( rc==SQLITE_OK ){
+ db->nDb++;
+ if( rc==SQLITE_CONSTRAINT ){
+ rc = SQLITE_ERROR;
+ zErrDyn = sqlite3MPrintf(db, "database is already attached");
+ }else if( rc==SQLITE_OK ){
Pager *pPager;
aNew->pSchema = sqlite3SchemaGet(db, aNew->pBt);
if( !aNew->pSchema ){
diff --git a/src/btree.c b/src/btree.c
index 315991eb5..acc4aaadd 100644
--- a/src/btree.c
+++ b/src/btree.c
@@ -9,7 +9,7 @@
** May you share freely, never taking more than you give.
**
*************************************************************************
-** $Id: btree.c,v 1.601 2009/04/30 09:10:38 danielk1977 Exp $
+** $Id: btree.c,v 1.602 2009/04/30 13:30:33 drh Exp $
**
** This file implements a external (disk-based) database using BTrees.
** See the header comment on "btreeInt.h" for additional information.
@@ -1401,6 +1401,12 @@ static int btreeInvokeBusyHandler(void *pArg){
** database file will be deleted when sqlite3BtreeClose() is called.
** If zFilename is ":memory:" then an in-memory database is created
** that is automatically destroyed when it is closed.
+**
+** If the database is already opened in the same database connection
+** and we are in shared cache mode, then the open will fail with an
+** SQLITE_CONSTRAINT error. We cannot allow two or more BtShared
+** objects in the same database connection since doing so will lead
+** to problems with locking.
*/
int sqlite3BtreeOpen(
const char *zFilename, /* Name of the file containing the BTree database */
@@ -1466,6 +1472,17 @@ int sqlite3BtreeOpen(
assert( pBt->nRef>0 );
if( 0==strcmp(zFullPathname, sqlite3PagerFilename(pBt->pPager))
&& sqlite3PagerVfs(pBt->pPager)==pVfs ){
+ int iDb;
+ for(iDb=db->nDb-1; iDb>=0; iDb--){
+ Btree *pExisting = db->aDb[iDb].pBt;
+ if( pExisting && pExisting->pBt==pBt ){
+ sqlite3_mutex_leave(mutexShared);
+ sqlite3_mutex_leave(mutexOpen);
+ sqlite3_free(zFullPathname);
+ sqlite3_free(p);
+ return SQLITE_CONSTRAINT;
+ }
+ }
p->pBt = pBt;
pBt->nRef++;
break;