fix: do not overwrite databases (#644)

* fix: do not overwrite databases

Do not overwrite an existing database when attempting to create a DB with an
existing name.

This should probably update the existing database config, but for the time being
this prevents the existing database from being silently dropped.

Fixes #643

* test: ensure duplicate DB names returns an error

Covers #643 with a test case.
pull/24376/head
Dom 2021-01-12 13:55:29 +00:00 committed by GitHub
parent fd28d8a01b
commit e38df076b4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 42 additions and 1 deletions

View File

@ -135,6 +135,8 @@ pub enum Error {
ErrorDeserializing { source: serde_json::Error },
#[snafu(display("store error: {}", source))]
StoreError { source: object_store::Error },
#[snafu(display("database already exists"))]
DatabaseAlreadyExists { db_name: String },
}
pub type Result<T, E = Error> = std::result::Result<T, E>;
@ -209,7 +211,16 @@ impl<M: ConnectionManager> Server<M> {
let db = Db::new(rules, mutable_buffer, read_buffer, wal_buffer, sequence);
let mut config = self.config.write().await;
config.databases.insert(db_name, Arc::new(db));
// If the database already exists, do not overwrite it.
if config.databases.contains_key(&db_name) {
// TODO: update database configuration
return Err(Error::DatabaseAlreadyExists {
db_name: db_name.to_string(),
});
}
assert!(config.databases.insert(db_name, Arc::new(db)).is_none());
Ok(())
}
@ -530,6 +541,36 @@ mod tests {
Ok(())
}
#[tokio::test]
async fn duplicate_database_name_rejected() -> Result {
// Covers #643
let manager = TestConnectionManager::new();
let store = Arc::new(ObjectStore::new_in_memory(InMemory::new()));
let server = Server::new(manager, store);
server.set_id(1).await;
let name = "bananas";
// Create a database
server
.create_database(name, DatabaseRules::default())
.await
.expect("failed to create database");
// Then try and create another with the same name
let got = server
.create_database(name, DatabaseRules::default())
.await
.unwrap_err();
if !matches!(got, Error::DatabaseAlreadyExists {..}) {
panic!("expected already exists error");
}
Ok(())
}
#[tokio::test]
async fn database_name_validation() -> Result {
let manager = TestConnectionManager::new();