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 */