Repository: duckdb/duckdb
File: src/main/database_manager.cpp (C++)

Code before:
	auto &transaction = DuckTransaction::Get(context, *system);
	auto &transaction_manager = DuckTransactionManager::Get(*system);
	transaction_manager.PushAttach(transaction, db_ref);
	return db_ref;
}

void DatabaseManager::DetachDatabase(ClientContext &context, const string &name, OnEntryNotFound if_not_found) {
	if (GetDefaultDatabase(context) == name) {
		throw BinderException("Cannot detach database \"%s\" because it is the default database. Select a different "
		                      "database using `USE` to allow detaching this database",
		                      name);
	}

	auto attached_db = DetachInternal(name);
	if (!attached_db) {
		if (if_not_found == OnEntryNotFound::THROW_EXCEPTION) {
			throw BinderException("Failed to detach database with name \"%s\": database not found", name);
		}
		return;
	}

	attached_db->OnDetach(context);

	// DetachInternal removes the AttachedDatabase from the list of databases that can be referenced.
	// Thus, if the use count is 1, then we know it will be destroyed after the function is over.
	if (attached_db.use_count() == 1) {
		try {
			attached_db->Checkpoint();
		} catch (std::exception &ex) {
			attached_db->Cleanup();
			ErrorData data(ex);
			data.Throw("Detached database '" + attached_db->name + "', but CHECKPOINT during DETACH failed. \n");
		} catch (...) { // NOLINT
		}

		// Successful CHECKPOINT. We still need to clean up.
		attached_db->Cleanup();
	}
}

void DatabaseManager::Alter(ClientContext &context, AlterInfo &info) {
	auto &db_info = info.Cast<AlterDatabaseInfo>();

	switch (db_info.alter_database_type) {
	case AlterDatabaseType::RENAME_DATABASE: {
		auto &rename_info = db_info.Cast<RenameDatabaseInfo>();
		RenameDatabase(context, db_info.catalog, rename_info.new_name, db_info.if_not_found);
		break;
	}
	default:
		throw InternalException("Unsupported ALTER DATABASE operation");

Review comment (refactor):
This pattern seems to happen in at least two places and is reasonably complex - can we move this to a separate function? e.g. `AttachedDatabase::DestroyIfLastReference(attached_db);` (or a better name :) )

Code after:
	return db_ref;
}

void DatabaseManager::DetachDatabase(ClientContext &context, const string &name, OnEntryNotFound if_not_found) {
	if (GetDefaultDatabase(context) == name) {
		throw BinderException("Cannot detach database \"%s\" because it is the default database. Select a different "
		                      "database using `USE` to allow detaching this database",
		                      name);
	}

	auto attached_db = DetachInternal(name);
	if (!attached_db) {
		if (if_not_found == OnEntryNotFound::THROW_EXCEPTION) {
			throw BinderException("Failed to detach database with name \"%s\": database not found", name);
		}
		return;
	}

	attached_db->OnDetach(context);

	// DetachInternal removes the AttachedDatabase from the list of databases that can be referenced.
	AttachedDatabase::InvokeCloseIfLastReference(attached_db);
}

void DatabaseManager::Alter(ClientContext &context, AlterInfo &info) {
	auto &db_info = info.Cast<AlterDatabaseInfo>();

	switch (db_info.alter_database_type) {
	case AlterDatabaseType::RENAME_DATABASE: {
		auto &rename_info = db_info.Cast<RenameDatabaseInfo>();
		RenameDatabase(context, db_info.catalog, rename_info.new_name, db_info.if_not_found);
		break;
	}
	default:
		throw InternalException("Unsupported ALTER DATABASE operation");
	}
}

void DatabaseManager::RenameDatabase(ClientContext &context, const string &old_name, const string &new_name,
                                     OnEntryNotFound if_not_found) {
	if (AttachedDatabase::NameIsReserved(new_name)) {
		throw BinderException("Database name \"%s\" cannot be used because it is a reserved name", new_name);
	}

	shared_ptr<AttachedDatabase> attached_db;
	{
		lock_guard<mutex> guard(databases_lock);
		auto old_entry = databases.find(old_name);
		if (old_entry == databases.end()) {
			if (if_not_found == OnEntryNotFound::THROW_EXCEPTION) {
				throw BinderException("Failed to rename database \"%s\": database not found", old_name);