From 7a5f2b426bd33d9e05ed6a4013404529acee57d1 Mon Sep 17 00:00:00 2001 From: Peter Holloway Date: Tue, 20 Oct 2026 19:35:37 +0100 Subject: [PATCH 1/2] Clear tracker_file_extension when set to instrument name If the extension is not present the instrument name is used so setting the extension to the same value doesn't make sense and is skipped. Skipping the update entirely led to two issues: * if the extension had previously been set to a new value it couldn't be set back * if resetting the extension was the only update being made, it would lead to invalid SQL and an error. Instead of skipping the field entirely in the case that it matches the instrument, use None and reset the DB value to NULL to rely on the instrument being the default. --- src/db_service.rs | 36 +++++++++++++++++++++++++++++++----- 1 file changed, 31 insertions(+), 5 deletions(-) diff --git a/src/db_service.rs b/src/db_service.rs index c1eaa51..7975c78 100644 --- a/src/db_service.rs +++ b/src/db_service.rs @@ -160,11 +160,10 @@ impl InstrumentConfigurationUpdate { fields.push_bind_unseparated(detector.to_string()); } if let Some(ext) = &self.tracker_file_extension { - if ext != &self.name { - // extension defaults to instrument name - fields.push("tracker_file_extension="); - fields.push_bind_unseparated(ext); - } + fields.push("tracker_file_extension="); + // If value matches instrument, set back to NULL and rely on instrument being default + let value = (ext != &self.name).then_some(ext); + fields.push_bind_unseparated(value); } q.push(" WHERE name = "); q.push_bind(&self.name); @@ -678,4 +677,31 @@ mod db_tests { let upd = InstrumentConfigurationUpdate::empty("b21"); assert!(ok!(upd.update_instrument(&db)).is_none()); } + + #[tokio::test] + async fn reset_file_extension() { + let db = SqliteScanPathService::memory().await; + + // Insert new config without extension defaults to None + let initial = ok!(update("i22").insert_new(&db)); + assert_eq!(initial.tracker_file_extension(), None); + + // Updating to a new extension set it as expected + let upd = InstrumentConfigurationUpdate::empty("i22").with_extension("other"); + assert_eq!( + ok!(upd.update_instrument(&db)) + .unwrap() + .tracker_file_extension(), + Some("other") + ); + + // Setting the extension back to match instrument clears it + let upd = InstrumentConfigurationUpdate::empty("i22").with_extension("i22"); + assert_eq!( + ok!(upd.update_instrument(&db)) + .unwrap() + .tracker_file_extension(), + None + ); + } } From 5a03ef1c45717d7718f69b000890fc3093f0ef22 Mon Sep 17 00:00:00 2001 From: Peter Holloway Date: Tue, 20 Oct 2026 19:43:28 +0100 Subject: [PATCH 2/2] Ignore tracker extensions that match instrument As the instrument name is used as the extension by default it doesn't make sense to store the same value for both. When updating a configuration, the field is skipped or reset if it matches but when creating a new configuration, the matching extension would still be set. This makes the behaviour consistent between updating a configuration and creating a new one. --- src/db_service.rs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/db_service.rs b/src/db_service.rs index 7975c78..1d3560f 100644 --- a/src/db_service.rs +++ b/src/db_service.rs @@ -248,7 +248,7 @@ impl DbInstrumentConfig { self.directory, self.scan, self.detector, - self.tracker_file_extension + self.tracker_file_extension.filter(|ext| ext != &self.name), ) .fetch_one(&db.pool) .await?; @@ -678,6 +678,14 @@ mod db_tests { assert!(ok!(upd.update_instrument(&db)).is_none()); } + #[tokio::test] + async fn extension_matching_instrument() { + let db = SqliteScanPathService::memory().await; + + let cfg = ok!(update("i22").with_extension("i22").insert_new(&db)); + assert_eq!(cfg.tracker_file_extension(), None) + } + #[tokio::test] async fn reset_file_extension() { let db = SqliteScanPathService::memory().await;