mithril_aggregator/database/query/certificate/
insert_certificate.rs1use std::iter::repeat_n;
2
3use sqlite::Value;
4
5use mithril_persistence::sqlite::{Query, SourceAlias, SqLiteEntity, WhereCondition};
6
7use crate::database::record::CertificateRecord;
8
9pub struct InsertCertificateRecordQuery {
11 condition: WhereCondition,
12}
13
14impl InsertCertificateRecordQuery {
15 pub fn one(certificate_record: CertificateRecord) -> Self {
16 Self::many(vec![certificate_record])
17 }
18
19 pub fn many(certificates_records: Vec<CertificateRecord>) -> Self {
20 let columns = "(\
21 certificate_id, \
22 parent_certificate_id, \
23 message, \
24 signature, \
25 aggregate_verification_key, \
26 epoch, \
27 network, \
28 signed_entity_type_id, \
29 signed_entity_beacon, \
30 protocol_version, \
31 protocol_parameters, \
32 protocol_message, \
33 signers, \
34 initiated_at, \
35 sealed_at)";
36 let values_columns: Vec<&str> = repeat_n(
37 "(?*, ?*, ?*, ?*, ?*, ?*, ?*, ?*, ?*, ?*, ?*, ?*, ?*, ?*, ?*)",
38 certificates_records.len(),
39 )
40 .collect();
41
42 let values: Vec<Value> = certificates_records
43 .into_iter()
44 .flat_map(|certificate_record| {
45 vec![
46 Value::String(certificate_record.certificate_id),
47 match certificate_record.parent_certificate_id {
48 Some(parent_certificate_id) => Value::String(parent_certificate_id),
49 None => Value::Null,
50 },
51 Value::String(certificate_record.message),
52 Value::String(certificate_record.signature),
53 Value::String(certificate_record.aggregate_verification_key),
54 Value::Integer(certificate_record.epoch.try_into().unwrap()),
55 Value::String(certificate_record.network),
56 Value::Integer(certificate_record.signed_entity_type.index() as i64),
57 Value::String(
58 certificate_record
59 .signed_entity_type
60 .get_json_beacon()
61 .unwrap(),
62 ),
63 Value::String(certificate_record.protocol_version),
64 Value::String(
65 serde_json::to_string(&certificate_record.protocol_parameters).unwrap(),
66 ),
67 Value::String(
68 serde_json::to_string(&certificate_record.protocol_message).unwrap(),
69 ),
70 Value::String(serde_json::to_string(&certificate_record.signers).unwrap()),
71 Value::String(certificate_record.initiated_at.to_rfc3339()),
72 Value::String(certificate_record.sealed_at.to_rfc3339()),
73 ]
74 })
75 .collect();
76
77 let condition = WhereCondition::new(
78 format!("{columns} values {}", values_columns.join(", ")).as_str(),
79 values,
80 );
81
82 Self { condition }
83 }
84}
85
86impl Query for InsertCertificateRecordQuery {
87 type Entity = CertificateRecord;
88
89 fn filters(&self) -> WhereCondition {
90 self.condition.clone()
91 }
92
93 fn get_definition(&self, condition: &str) -> String {
94 let projection = Self::Entity::get_projection()
97 .expand(SourceAlias::new(&[("{:certificate:}", "certificate")]));
98
99 format!("insert into certificate {condition} returning {projection}")
100 }
101}
102
103#[cfg(test)]
104mod tests {
105 use mithril_common::crypto_helper::tests_setup::setup_certificate_chain;
106 use mithril_persistence::sqlite::ConnectionExtensions;
107
108 use crate::database::test_helper::main_db_connection;
109
110 use super::*;
111
112 #[test]
113 fn test_insert_certificate_record() {
114 let (certificates, _) = setup_certificate_chain(5, 2);
115
116 let connection = main_db_connection().unwrap();
117
118 for certificate in certificates {
119 let certificate_record: CertificateRecord = certificate.into();
120 let certificate_record_saved = connection
121 .fetch_first(InsertCertificateRecordQuery::one(
122 certificate_record.clone(),
123 ))
124 .unwrap();
125 assert_eq!(Some(certificate_record), certificate_record_saved);
126 }
127 }
128
129 #[test]
130 fn test_insert_many_certificates_records() {
131 let (certificates, _) = setup_certificate_chain(5, 2);
132 let certificates_records: Vec<CertificateRecord> =
133 certificates.into_iter().map(|cert| cert.into()).collect();
134
135 let connection = main_db_connection().unwrap();
136
137 let certificates_records_saved: Vec<CertificateRecord> = connection
138 .fetch_collect(InsertCertificateRecordQuery::many(
139 certificates_records.clone(),
140 ))
141 .expect("saving many records should not fail");
142
143 assert_eq!(certificates_records, certificates_records_saved);
144 }
145}