Index: src/db.c
==================================================================
--- src/db.c
+++ src/db.c
@@ -740,17 +740,25 @@
 /*
 ** zDbName is the name of a database file.  If no other database
 ** file is open, then open this one.  If another database file is
 ** already open, then attach zDbName using the name zLabel.
 */
-void db_open_or_attach(const char *zDbName, const char *zLabel){
+void db_open_or_attach(
+  const char *zDbName,
+  const char *zLabel,
+  int *pWasAttached
+){
   if( !g.db ){
+    assert( g.zMainDbType==0 );
     g.db = openDatabase(zDbName);
     g.zMainDbType = zLabel;
     db_connection_init();
+    if ( pWasAttached ) *pWasAttached = 0;
   }else{
+    assert( g.zMainDbType!=0 );
     db_attach(zDbName, zLabel);
+    if ( pWasAttached ) *pWasAttached = 1;
   }
 }
 
 /*
 ** Open the user database in "~/.fossil".  Create the database anew if
@@ -806,16 +814,18 @@
   zDbName = mprintf("%s/.fossil", zHome);
 #endif
   if( file_size(zDbName)<1024*3 ){
     db_init_database(zDbName, zConfigSchema, (char*)0);
   }
-  g.useAttach = useAttach;
   if( useAttach ){
-    db_open_or_attach(zDbName, "configdb");
+    db_open_or_attach(zDbName, "configdb", &g.useAttach);
     g.dbConfig = 0;
+    g.zConfigDbType = 0;
   }else{
+    g.useAttach = 0;
     g.dbConfig = openDatabase(zDbName);
+    g.zConfigDbType = "configdb";
   }
   g.configOpen = 1;
   free(zDbName);
 }
 
@@ -850,11 +860,11 @@
   char *zVFileDef;
 
   if( file_access(zDbName, F_OK) ) return 0;
   lsize = file_size(zDbName);
   if( lsize%1024!=0 || lsize<4096 ) return 0;
-  db_open_or_attach(zDbName, "localdb");
+  db_open_or_attach(zDbName, "localdb", 0);
   zVFileDef = db_text(0, "SELECT sql FROM %s.sqlite_master"
                          " WHERE name=='vfile'", db_name("localdb"));
 
   /* If the "isexe" column is missing from the vfile table, then
   ** add it now.   This code added on 2010-03-06.  After all users have
@@ -986,11 +996,11 @@
       g.json.resultCode = FSL_JSON_E_DB_NOT_VALID;
 #endif
       fossil_panic("not a valid repository: %s", zDbName);
     }
   }
-  db_open_or_attach(zDbName, "repository");
+  db_open_or_attach(zDbName, "repository", 0);
   g.repositoryOpen = 1;
   g.zRepositoryName = mprintf("%s", zDbName);
   /* Cache "allow-symlinks" option, because we'll need it on every stat call */
   g.allowSymlinks = db_get_boolean("allow-symlinks", 0);
 }
@@ -1109,11 +1119,11 @@
   file_canonical_name(g.argv[2], &repo, 0);
   zRepo = blob_str(&repo);
   if( file_access(zRepo, 0) ){
     fossil_fatal("no such file: %s", zRepo);
   }
-  db_open_or_attach(zRepo, "test_repo");
+  db_open_or_attach(zRepo, "test_repo", 0);
   db_lset("repository", blob_str(&repo));
   db_close(1);
 }
 
 
@@ -1177,13 +1187,15 @@
   g.localOpen = 0;
   g.configOpen = 0;
   sqlite3_wal_checkpoint(g.db, 0);
   sqlite3_close(g.db);
   g.db = 0;
+  g.zMainDbType = 0;
   if( g.dbConfig ){
     sqlite3_close(g.dbConfig);
     g.dbConfig = 0;
+    g.zConfigDbType = 0;
   }
 }
 
 
 /*
@@ -1630,19 +1642,32 @@
 /*
 ** Swap the g.db and g.dbConfig connections so that the various db_* routines
 ** work on the ~/.fossil database instead of on the repository database.
 ** Be sure to swap them back after doing the operation.
 **
-** If g.useAttach that means the ~/.fossil database was opened with
-** the useAttach flag set to 1.  In that case no connection swap is required
-** so this routine is a no-op.
+** If the ~/.fossil database has already been opened as the main database or
+** is attached to the main database, no connection swaps are required so this
+** routine is a no-op.
 */
 void db_swap_connections(void){
-  if( !g.useAttach ){
+  /*
+  ** When swapping the main database connection with the config database
+  ** connection, the config database connection must be open (not simply
+  ** attached); otherwise, the swap would end up leaving the main database
+  ** connection invalid, defeating the very purpose of this routine.  This
+  ** same constraint also holds true when restoring the previously swapped
+  ** database connection; otherwise, it means that no swap was performed
+  ** because the main database connection was already pointing to the config
+  ** database.
+  */
+  if( g.dbConfig ){
     sqlite3 *dbTemp = g.db;
+    const char *zTempDbType = g.zMainDbType;
     g.db = g.dbConfig;
+    g.zMainDbType = g.zConfigDbType;
     g.dbConfig = dbTemp;
+    g.zConfigDbType = zTempDbType;
   }
 }
 
 /*
 ** Logic for reading potentially versioned settings from

Index: src/file.c
==================================================================
--- src/file.c
+++ src/file.c
@@ -425,11 +425,11 @@
   char *zDate;
   i64 iMTime;
   if( g.argc!=4 ){
     usage("test-set-mtime FILENAME DATE/TIME");
   }
-  db_open_or_attach(":memory:", "mem");
+  db_open_or_attach(":memory:", "mem", 0);
   iMTime = db_int64(0, "SELECT strftime('%%s',%Q)", g.argv[3]);
   zFile = g.argv[2];
   file_set_mtime(zFile, iMTime);
   iMTime = file_wd_mtime(zFile);
   zDate = db_text(0, "SELECT datetime(%lld, 'unixepoch')", iMTime);

Index: src/json.c
==================================================================
--- src/json.c
+++ src/json.c
@@ -1409,10 +1409,11 @@
   INT(g, isHome);
   INT(g, nAux);
   INT(g, allowSymlinks);
 
   CSTR(g, zMainDbType);
+  CSTR(g, zConfigDbType);
   CSTR(g, zHome);
   CSTR(g, zLocalRoot);
   CSTR(g, zPath);
   CSTR(g, zExtra);
   CSTR(g, zBaseURL);

Index: src/main.c
==================================================================
--- src/main.c
+++ src/main.c
@@ -119,10 +119,11 @@
   int configOpen;         /* True if the config database is open */
   sqlite3_int64 now;      /* Seconds since 1970 */
   int repositoryOpen;     /* True if the main repository database is open */
   char *zRepositoryName;  /* Name of the repository database */
   const char *zMainDbType;/* "configdb", "localdb", or "repository" */
+  const char *zConfigDbType;  /* "configdb", "localdb", or "repository" */
   const char *zHome;      /* Name of user home directory */
   int localOpen;          /* True if the local database is open */
   char *zLocalRoot;       /* The directory holding the  local database */
   int minPrefix;          /* Number of digits needed for a distinct UUID */
   int fSqlTrace;          /* True if --sqltrace flag is present */