mithril_aggregator/database/query/epoch_settings/
update_epoch_settings.rs

1use sqlite::Value;
2
3use mithril_common::entities::Epoch;
4use mithril_persistence::sqlite::{Query, SourceAlias, SqLiteEntity, WhereCondition};
5
6use crate::database::record::EpochSettingsRecord;
7use crate::entities::AggregatorEpochSettings;
8
9/// Query to update [EpochSettingsRecord] in the sqlite database
10pub struct UpdateEpochSettingsQuery {
11    condition: WhereCondition,
12}
13
14impl UpdateEpochSettingsQuery {
15    pub fn one(epoch: Epoch, epoch_settings: AggregatorEpochSettings) -> Self {
16        let epoch_settings_id: i64 = epoch.try_into().unwrap();
17
18        Self {
19            condition: WhereCondition::new(
20                "(epoch_setting_id, protocol_parameters, cardano_transactions_signing_config) values (?1, ?2, ?3)",
21                vec![
22                    Value::Integer(epoch_settings_id),
23                    Value::String(
24                        serde_json::to_string(&epoch_settings.protocol_parameters).unwrap(),
25                    ),
26                    Value::String(
27                        serde_json::to_string(&epoch_settings.cardano_transactions_signing_config)
28                            .unwrap(),
29                    ),
30                ],
31            ),
32        }
33    }
34}
35
36impl Query for UpdateEpochSettingsQuery {
37    type Entity = EpochSettingsRecord;
38
39    fn filters(&self) -> WhereCondition {
40        self.condition.clone()
41    }
42
43    fn get_definition(&self, condition: &str) -> String {
44        // it is important to alias the fields with the same name as the table
45        // since the table cannot be aliased in a RETURNING statement in SQLite.
46        let projection = Self::Entity::get_projection()
47            .expand(SourceAlias::new(&[("{:epoch_setting:}", "epoch_setting")]));
48
49        format!("insert or replace into epoch_setting {condition} returning {projection}")
50    }
51}
52
53#[cfg(test)]
54mod tests {
55    use mithril_common::entities::{BlockNumber, CardanoTransactionsSigningConfig};
56    use mithril_common::test_utils::fake_data;
57    use mithril_persistence::sqlite::ConnectionExtensions;
58
59    use crate::database::query::GetEpochSettingsQuery;
60    use crate::database::test_helper::{insert_epoch_settings, main_db_connection};
61
62    use super::*;
63
64    #[test]
65    fn test_update_epoch_settings() {
66        let connection = main_db_connection().unwrap();
67        insert_epoch_settings(&connection, &[*Epoch(3)]).unwrap();
68
69        let epoch_settings_send_to_update = AggregatorEpochSettings {
70            protocol_parameters: fake_data::protocol_parameters(),
71            cardano_transactions_signing_config: CardanoTransactionsSigningConfig::new(
72                BlockNumber(24),
73                BlockNumber(62),
74            ),
75        };
76        let record_returned_by_update_query = connection
77            .fetch_first(UpdateEpochSettingsQuery::one(
78                Epoch(3),
79                epoch_settings_send_to_update.clone(),
80            ))
81            .unwrap()
82            .unwrap();
83
84        assert_eq!(Epoch(3), record_returned_by_update_query.epoch_settings_id);
85        assert_eq!(
86            epoch_settings_send_to_update.protocol_parameters,
87            record_returned_by_update_query.protocol_parameters
88        );
89        assert_eq!(
90            epoch_settings_send_to_update.cardano_transactions_signing_config,
91            record_returned_by_update_query.cardano_transactions_signing_config
92        );
93
94        let mut cursor = connection
95            .fetch(GetEpochSettingsQuery::by_epoch(Epoch(3)).unwrap())
96            .unwrap();
97        let epoch_settings_record =
98            cursor.next().expect("Should have an epoch settings for epoch 3.");
99
100        assert_eq!(record_returned_by_update_query, epoch_settings_record);
101        assert_eq!(0, cursor.count());
102    }
103}