mithril_aggregator/database/query/single_signature/
update_single_signature.rs

1use sqlite::Value;
2
3use mithril_persistence::sqlite::{Query, SourceAlias, SqLiteEntity, WhereCondition};
4
5use crate::database::record::SingleSignatureRecord;
6
7/// Query to update [SingleSignatureRecord] in the sqlite database
8pub struct UpdateSingleSignatureRecordQuery {
9    condition: WhereCondition,
10}
11
12impl UpdateSingleSignatureRecordQuery {
13    pub fn one(single_signature_record: SingleSignatureRecord) -> Self {
14        let condition =
15        WhereCondition::new(
16            "(open_message_id, signer_id, registration_epoch_setting_id, lottery_indexes, signature, created_at) values (?*, ?*, ?*, ?*, ?*, ?*)",
17            vec![
18                Value::String(single_signature_record.open_message_id.to_string()),
19                Value::String(single_signature_record.signer_id),
20                Value::Integer(
21                    single_signature_record.registration_epoch_settings_id.try_into().unwrap(),
22                ),
23                Value::String(serde_json::to_string(&single_signature_record.lottery_indexes).unwrap()),
24                Value::String(single_signature_record.signature),
25                Value::String(single_signature_record.created_at.to_rfc3339()),
26            ],
27        );
28
29        Self { condition }
30    }
31}
32
33impl Query for UpdateSingleSignatureRecordQuery {
34    type Entity = SingleSignatureRecord;
35
36    fn filters(&self) -> WhereCondition {
37        self.condition.clone()
38    }
39
40    fn get_definition(&self, condition: &str) -> String {
41        // it is important to alias the fields with the same name as the table
42        // since the table cannot be aliased in a RETURNING statement in SQLite.
43        let projection = Self::Entity::get_projection().expand(SourceAlias::new(&[(
44            "{:single_signature:}",
45            "single_signature",
46        )]));
47
48        format!("insert or replace into single_signature {condition} returning {projection}")
49    }
50}
51
52#[cfg(test)]
53mod tests {
54    use crate::database::test_helper::{main_db_connection, setup_single_signature_records};
55    use mithril_persistence::sqlite::ConnectionExtensions;
56
57    use super::*;
58
59    #[test]
60    fn test_update_single_signature_record() {
61        let single_signature_records = setup_single_signature_records(2, 3, 4);
62
63        let connection = main_db_connection().unwrap();
64
65        for single_signature_record in single_signature_records.clone() {
66            let single_signature_record_saved = connection
67                .fetch_first(UpdateSingleSignatureRecordQuery::one(
68                    single_signature_record.clone(),
69                ))
70                .unwrap();
71            assert_eq!(Some(single_signature_record), single_signature_record_saved);
72        }
73
74        for mut single_signature_record in single_signature_records {
75            single_signature_record.lottery_indexes.push(5);
76            let single_signature_record_saved = connection
77                .fetch_first(UpdateSingleSignatureRecordQuery::one(
78                    single_signature_record.clone(),
79                ))
80                .unwrap();
81            assert_eq!(Some(single_signature_record), single_signature_record_saved);
82        }
83    }
84}