| | @@ -740,17 +740,25 @@ |
| 740 | 740 | /* |
| 741 | 741 | ** zDbName is the name of a database file. If no other database |
| 742 | 742 | ** file is open, then open this one. If another database file is |
| 743 | 743 | ** already open, then attach zDbName using the name zLabel. |
| 744 | 744 | */ |
| 745 | | -void db_open_or_attach(const char *zDbName, const char *zLabel){ |
| 745 | +void db_open_or_attach( |
| 746 | + const char *zDbName, |
| 747 | + const char *zLabel, |
| 748 | + int *pWasAttached |
| 749 | +){ |
| 746 | 750 | if( !g.db ){ |
| 751 | + assert( g.zMainDbType==0 ); |
| 747 | 752 | g.db = openDatabase(zDbName); |
| 748 | 753 | g.zMainDbType = zLabel; |
| 749 | 754 | db_connection_init(); |
| 755 | + if ( pWasAttached ) *pWasAttached = 0; |
| 750 | 756 | }else{ |
| 757 | + assert( g.zMainDbType!=0 ); |
| 751 | 758 | db_attach(zDbName, zLabel); |
| 759 | + if ( pWasAttached ) *pWasAttached = 1; |
| 752 | 760 | } |
| 753 | 761 | } |
| 754 | 762 | |
| 755 | 763 | /* |
| 756 | 764 | ** Open the user database in "~/.fossil". Create the database anew if |
| | @@ -806,16 +814,18 @@ |
| 806 | 814 | zDbName = mprintf("%s/.fossil", zHome); |
| 807 | 815 | #endif |
| 808 | 816 | if( file_size(zDbName)<1024*3 ){ |
| 809 | 817 | db_init_database(zDbName, zConfigSchema, (char*)0); |
| 810 | 818 | } |
| 811 | | - g.useAttach = useAttach; |
| 812 | 819 | if( useAttach ){ |
| 813 | | - db_open_or_attach(zDbName, "configdb"); |
| 820 | + db_open_or_attach(zDbName, "configdb", &g.useAttach); |
| 814 | 821 | g.dbConfig = 0; |
| 822 | + g.zConfigDbType = 0; |
| 815 | 823 | }else{ |
| 824 | + g.useAttach = 0; |
| 816 | 825 | g.dbConfig = openDatabase(zDbName); |
| 826 | + g.zConfigDbType = "configdb"; |
| 817 | 827 | } |
| 818 | 828 | g.configOpen = 1; |
| 819 | 829 | free(zDbName); |
| 820 | 830 | } |
| 821 | 831 | |
| | @@ -850,11 +860,11 @@ |
| 850 | 860 | char *zVFileDef; |
| 851 | 861 | |
| 852 | 862 | if( file_access(zDbName, F_OK) ) return 0; |
| 853 | 863 | lsize = file_size(zDbName); |
| 854 | 864 | if( lsize%1024!=0 || lsize<4096 ) return 0; |
| 855 | | - db_open_or_attach(zDbName, "localdb"); |
| 865 | + db_open_or_attach(zDbName, "localdb", 0); |
| 856 | 866 | zVFileDef = db_text(0, "SELECT sql FROM %s.sqlite_master" |
| 857 | 867 | " WHERE name=='vfile'", db_name("localdb")); |
| 858 | 868 | |
| 859 | 869 | /* If the "isexe" column is missing from the vfile table, then |
| 860 | 870 | ** add it now. This code added on 2010-03-06. After all users have |
| | @@ -986,11 +996,11 @@ |
| 986 | 996 | g.json.resultCode = FSL_JSON_E_DB_NOT_VALID; |
| 987 | 997 | #endif |
| 988 | 998 | fossil_panic("not a valid repository: %s", zDbName); |
| 989 | 999 | } |
| 990 | 1000 | } |
| 991 | | - db_open_or_attach(zDbName, "repository"); |
| 1001 | + db_open_or_attach(zDbName, "repository", 0); |
| 992 | 1002 | g.repositoryOpen = 1; |
| 993 | 1003 | g.zRepositoryName = mprintf("%s", zDbName); |
| 994 | 1004 | /* Cache "allow-symlinks" option, because we'll need it on every stat call */ |
| 995 | 1005 | g.allowSymlinks = db_get_boolean("allow-symlinks", 0); |
| 996 | 1006 | } |
| | @@ -1109,11 +1119,11 @@ |
| 1109 | 1119 | file_canonical_name(g.argv[2], &repo, 0); |
| 1110 | 1120 | zRepo = blob_str(&repo); |
| 1111 | 1121 | if( file_access(zRepo, 0) ){ |
| 1112 | 1122 | fossil_fatal("no such file: %s", zRepo); |
| 1113 | 1123 | } |
| 1114 | | - db_open_or_attach(zRepo, "test_repo"); |
| 1124 | + db_open_or_attach(zRepo, "test_repo", 0); |
| 1115 | 1125 | db_lset("repository", blob_str(&repo)); |
| 1116 | 1126 | db_close(1); |
| 1117 | 1127 | } |
| 1118 | 1128 | |
| 1119 | 1129 | |
| | @@ -1177,13 +1187,15 @@ |
| 1177 | 1187 | g.localOpen = 0; |
| 1178 | 1188 | g.configOpen = 0; |
| 1179 | 1189 | sqlite3_wal_checkpoint(g.db, 0); |
| 1180 | 1190 | sqlite3_close(g.db); |
| 1181 | 1191 | g.db = 0; |
| 1192 | + g.zMainDbType = 0; |
| 1182 | 1193 | if( g.dbConfig ){ |
| 1183 | 1194 | sqlite3_close(g.dbConfig); |
| 1184 | 1195 | g.dbConfig = 0; |
| 1196 | + g.zConfigDbType = 0; |
| 1185 | 1197 | } |
| 1186 | 1198 | } |
| 1187 | 1199 | |
| 1188 | 1200 | |
| 1189 | 1201 | /* |
| | @@ -1630,19 +1642,32 @@ |
| 1630 | 1642 | /* |
| 1631 | 1643 | ** Swap the g.db and g.dbConfig connections so that the various db_* routines |
| 1632 | 1644 | ** work on the ~/.fossil database instead of on the repository database. |
| 1633 | 1645 | ** Be sure to swap them back after doing the operation. |
| 1634 | 1646 | ** |
| 1635 | | -** If g.useAttach that means the ~/.fossil database was opened with |
| 1636 | | -** the useAttach flag set to 1. In that case no connection swap is required |
| 1637 | | -** so this routine is a no-op. |
| 1647 | +** If the ~/.fossil database has already been opened as the main database or |
| 1648 | +** is attached to the main database, no connection swaps are required so this |
| 1649 | +** routine is a no-op. |
| 1638 | 1650 | */ |
| 1639 | 1651 | void db_swap_connections(void){ |
| 1640 | | - if( !g.useAttach ){ |
| 1652 | + /* |
| 1653 | + ** When swapping the main database connection with the config database |
| 1654 | + ** connection, the config database connection must be open (not simply |
| 1655 | + ** attached); otherwise, the swap would end up leaving the main database |
| 1656 | + ** connection invalid, defeating the very purpose of this routine. This |
| 1657 | + ** same constraint also holds true when restoring the previously swapped |
| 1658 | + ** database connection; otherwise, it means that no swap was performed |
| 1659 | + ** because the main database connection was already pointing to the config |
| 1660 | + ** database. |
| 1661 | + */ |
| 1662 | + if( g.dbConfig ){ |
| 1641 | 1663 | sqlite3 *dbTemp = g.db; |
| 1664 | + const char *zTempDbType = g.zMainDbType; |
| 1642 | 1665 | g.db = g.dbConfig; |
| 1666 | + g.zMainDbType = g.zConfigDbType; |
| 1643 | 1667 | g.dbConfig = dbTemp; |
| 1668 | + g.zConfigDbType = zTempDbType; |
| 1644 | 1669 | } |
| 1645 | 1670 | } |
| 1646 | 1671 | |
| 1647 | 1672 | /* |
| 1648 | 1673 | ** Logic for reading potentially versioned settings from |
| 1649 | 1674 | |