aquarium_control/database/sql_interface_heating_stats_data_transfer.rs
1/* Copyright 2025 Uwe Martin
2
3Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
5The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
7THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
8*/
9
10//! Provides the concrete implementation for transferring heating statistics to a SQL database.
11//!
12//! This module acts as a bridge, fulfilling the `HeatingStatsDataTransferTrait` contract
13//! by using the `SqlInterfaceHeatingStats` component. Its primary purpose is to decouple
14//! the core heating logic from the specific details of the database implementation, adhering
15//! to the Dependency Inversion Principle.
16//!
17//! ## Key Components
18//!
19//! - **`HeatingStatsDataTransfer`**: A simple unit struct that serves as the concrete
20//! implementation of the `HeatingStatsDataTransferTrait`. It contains no data itself;
21//! its sole role is to provide the `transfer_heating_stats` method.
22//!
23//! ## Design and Purpose
24//!
25//! In a larger system, a high-level component (like a thermal controller) needs to persist
26//! statistics but should not be tightly coupled to the database code. Instead, it depends
27//! on an abstraction—the `HeatingStatsDataTransferTrait`.
28//!
29//! This module provides the "glue" that connects the abstraction to the concrete
30//! `SqlInterfaceHeatingStats` implementation allowing usage of mock-implementation of the trait
31//! to verify that statistics are being generated correctly without needing a real database
32//! connection.
33
34use crate::database::sql_interface_error::SqlInterfaceError;
35use crate::database::sql_interface_heating_stats::{HeatingStatsEntry, SqlInterfaceHeatingStats};
36use crate::thermal::heating::HeatingStatsDataTransferTrait;
37
38/// Implements the `HeatingStatsDataTransferTrait` for transferring heating statistics to the SQL database.
39///
40/// This struct serves as the concrete component for persisting daily heating statistics
41/// into the configured SQL database.
42pub struct HeatingStatsDataTransfer;
43
44impl HeatingStatsDataTransferTrait for HeatingStatsDataTransfer {
45 /// Persists a daily heating statistics entry to the SQL database.
46 ///
47 /// This implementation calls the underlying `insert_heating_stats_entry` method
48 /// to write the provided data. The operation is typically an "upsert" (insert or update).
49 ///
50 /// # Arguments
51 /// * `heating_stats_entry` - The `HeatingStatsEntry` containing the complete statistics for a single day.
52 /// * `sql_interface_heating` - A mutable reference to the `SqlInterfaceHeatingStats` instance,
53 /// used to perform the database write operation.
54 ///
55 /// # Returns
56 /// An empty `Result` (`Ok(())`) if the data was successfully inserted or updated in the database.
57 ///
58 /// # Errors
59 /// This function will return an `Err` variant of `SqlInterfaceError` if the underlying
60 /// database operation fails. This is typically `SqlInterfaceError::InsertHeatingStatsEntryFailure`,
61 /// which can be caused by:
62 /// - A lost or broken database connection.
63 /// - A violation of database constraints (e.g., a malformed date that violates the primary key).
64 /// - Insufficient permissions for the database user to perform `INSERT` or `UPDATE` operations.
65 /// - A malformed SQL query, which would indicate an internal logic error.
66 fn transfer_heating_stats(
67 &mut self,
68 heating_stats_entry: HeatingStatsEntry,
69 sql_interface_heating: &mut SqlInterfaceHeatingStats,
70 ) -> Result<(), SqlInterfaceError> {
71 sql_interface_heating.insert_heating_stats_entry(&heating_stats_entry)
72 }
73}