]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Disallow attaching the same database multiple times to the same db connection
authordrh <drh@noemail.net>
Thu, 30 Apr 2009 13:30:32 +0000 (13:30 +0000)
committerdrh <drh@noemail.net>
Thu, 30 Apr 2009 13:30:32 +0000 (13:30 +0000)
in shared cache mode, since doing so leads to deadlock. (CVS 6578)

FossilOrigin-Name: 715f14f1dcaf604d4794bf3e18e245d4f8c5d5a9

manifest
manifest.uuid
src/attach.c
src/btree.c
test/shared7.test [new file with mode: 0644]

index 720da8b4345e36846aa36e0132c653e7eea49800..ab50a61e109848d3ff1c0679442ed39b87fe0d7a 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Fix\sapparent\stypo\son\sexclusive.test\sin\sthe\s(6575)\scheck-in.\s(CVS\s6577)
-D 2009-04-30T12:25:59
+C Disallow\sattaching\sthe\ssame\sdatabase\smultiple\stimes\sto\sthe\ssame\sdb\sconnection\nin\sshared\scache\smode,\ssince\sdoing\sso\sleads\sto\sdeadlock.\s(CVS\s6578)
+D 2009-04-30T13:30:33
 F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
 F Makefile.in 583e87706abc3026960ed759aff6371faf84c211
 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
@@ -101,12 +101,12 @@ F sqlite3.1 6be1ad09113570e1fc8dcaff84c9b0b337db5ffc
 F sqlite3.pc.in ae6f59a76e862f5c561eb32a380228a02afc3cad
 F src/alter.c 8ab5824bde0a03dae5829f61557ab7c72757000a
 F src/analyze.c e239496cfb5394ac8867f1c112905ddab8d01cd9
-F src/attach.c 2acdbf4bbca681405a3fd3b1c75356be10becb62
+F src/attach.c 5e4c387144503013963bac9c7b2f07e22bcbb3ee
 F src/auth.c c8b2ab5c8bad4bd90ed7c294694f48269162c627
 F src/backup.c 0082d0e5a63f04e88faee0dff0a7d63d3e92a78d
 F src/bitvec.c ef370407e03440b0852d05024fb016b14a471d3d
 F src/btmutex.c 9b899c0d8df3bd68f527b0afe03088321b696d3c
-F src/btree.c 2b89d1f578c417d68befd801a1291836c923bd1e
+F src/btree.c 2165bfef1b4bb90a84565c63ae06cad2954d1d3c
 F src/btree.h 99fcc7e8c4a1e35afe271bcb38de1a698dfc904e
 F src/btreeInt.h df64030d632f8c8ac217ed52e8b6b3eacacb33a5
 F src/build.c dca0ad77c88cb00f6a11cc080a4f3285672cfa37
@@ -539,6 +539,7 @@ F test/shared2.test 8973e41e008acbbd8d1b191b91a23cd472f058e8
 F test/shared3.test 9c880afc081d797da514ef64bccf36f3fce2f09c
 F test/shared4.test d0fadacb50bb6981b2fb9dc6d1da30fa1edddf83
 F test/shared6.test db3906045175debea4a0d57cb94c6ffe2d85413d
+F test/shared7.test 8114027cb5e8c376e467115703d46e5ac4e77739
 F test/shared_err.test 91e26ec4f3fbe07951967955585137e2f18993de
 F test/shortread1.test bb591ef20f0fd9ed26d0d12e80eee6d7ac8897a3
 F test/sidedelete.test f0ad71abe6233e3b153100f3b8d679b19a488329
@@ -725,7 +726,7 @@ F tool/speedtest16.c c8a9c793df96db7e4933f0852abb7a03d48f2e81
 F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
 F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
-P aa29a14ca040db25dadbca787aa75be3b7588415
-R e5ecfcd2438204c7aa2bbe68cbf44244
+P 95d22405e096355ce815cdb0908c4ef04107b490
+R 8d3121c371bc6b3d2bb493dbba26f385
 U drh
-Z 7902f9496a68bca062f4a84f7c5dfe66
+Z a41c8b6fc921420eb6f0176ff357b69b
index 72931028d976cebe0ce80ea788464816f33e9382..516e33d4546bc97fe24da8b42a85ccab978283ae 100644 (file)
@@ -1 +1 @@
-95d22405e096355ce815cdb0908c4ef04107b490
\ No newline at end of file
+715f14f1dcaf604d4794bf3e18e245d4f8c5d5a9
\ No newline at end of file
index d5495361b6b1de488e7caefa118eae7f678029f8..d0f81766bc50161cdbbb843f7de67ad7adc0bd76 100644 (file)
@@ -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 ){
index 315991eb57e4a5d2e9d5d659ef08728b7db971db..acc4aaadd2230fe93fdfe0b8341afa120ce36865 100644 (file)
@@ -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;
diff --git a/test/shared7.test b/test/shared7.test
new file mode 100644 (file)
index 0000000..d003f0a
--- /dev/null
@@ -0,0 +1,55 @@
+# 2009 April 30
+#
+# The author disclaims copyright to this source code.  In place of
+# a legal notice, here is a blessing:
+#
+#    May you do good and not evil.
+#    May you find forgiveness for yourself and forgive others.
+#    May you share freely, never taking more than you give.
+#
+#***********************************************************************
+#
+# Make sure that attaching the same database multiple times in
+# shared cache mode fails.
+#
+# $Id: shared7.test,v 1.1 2009/04/30 13:30:33 drh Exp $
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+ifcapable !shared_cache { finish_test ; return }
+
+do_test shared7-1.1 {
+  set ::enable_shared_cache [sqlite3_enable_shared_cache 1]
+  sqlite3_enable_shared_cache
+} {1}
+
+do_test shared7-1.2 {
+  db close
+  sqlite3 db test.db
+  db eval {
+    CREATE TABLE t1(x);
+  }
+  catchsql {
+    ATTACH 'test.db' AS err1;
+  }
+} {1 {database is already attached}}
+
+do_test shared7-1.3 {
+  file delete -force test2.db test2.db-journal
+  db eval {
+    ATTACH 'test2.db' AS test2;
+    CREATE TABLE test2.t2(y);
+  }
+  catchsql {
+    ATTACH 'test2.db' AS err2;
+  }
+} {1 {database is already attached}}
+do_test shared7-1.4 {
+  catchsql {
+    ATTACH 'test.db' AS err1;
+  }
+} {1 {database is already attached}}
+
+
+sqlite3_enable_shared_cache $::enable_shared_cache
+finish_test