mithril_aggregator/database/query/signed_entity/
get_signed_entity.rs1use sqlite::Value;
2
3use mithril_common::StdResult;
4use mithril_common::entities::{Epoch, SignedEntityTypeDiscriminants};
5use mithril_persistence::sqlite::{Query, SourceAlias, SqLiteEntity, WhereCondition};
6
7use crate::database::record::SignedEntityRecord;
8
9pub struct GetSignedEntityRecordQuery {
11 condition: WhereCondition,
12}
13
14impl GetSignedEntityRecordQuery {
15 #[cfg(test)]
16 pub fn all() -> Self {
17 Self {
18 condition: WhereCondition::default(),
19 }
20 }
21
22 pub fn by_signed_entity_id(signed_entity_id: &str) -> Self {
23 Self {
24 condition: WhereCondition::new(
25 "signed_entity_id = ?*",
26 vec![Value::String(signed_entity_id.to_owned())],
27 ),
28 }
29 }
30
31 pub fn by_certificate_id(certificate_id: &str) -> Self {
32 Self {
33 condition: WhereCondition::new(
34 "certificate_id = ?*",
35 vec![Value::String(certificate_id.to_owned())],
36 ),
37 }
38 }
39
40 pub fn by_certificates_ids(certificates_ids: &[&str]) -> Self {
41 let ids_values = certificates_ids
42 .iter()
43 .map(|id| Value::String(id.to_string()))
44 .collect();
45
46 Self {
47 condition: WhereCondition::where_in("certificate_id", ids_values),
48 }
49 }
50
51 pub fn by_signed_entity_type(
52 signed_entity_type: &SignedEntityTypeDiscriminants,
53 ) -> StdResult<Self> {
54 let signed_entity_type_id: i64 = signed_entity_type.index() as i64;
55
56 Ok(Self {
57 condition: WhereCondition::new(
58 "signed_entity_type_id = ?*",
59 vec![Value::Integer(signed_entity_type_id)],
60 ),
61 })
62 }
63
64 pub fn by_signed_entity_type_and_epoch(
65 signed_entity_type: &SignedEntityTypeDiscriminants,
66 epoch: Epoch,
67 ) -> Self {
68 let signed_entity_type_id = signed_entity_type.index() as i64;
69 let epoch = *epoch as i64;
70
71 Self {
72 condition: WhereCondition::new(
73 "signed_entity_type_id = ?* and epoch = ?*",
74 vec![Value::Integer(signed_entity_type_id), Value::Integer(epoch)],
75 ),
76 }
77 }
78}
79
80impl Query for GetSignedEntityRecordQuery {
81 type Entity = SignedEntityRecord;
82
83 fn filters(&self) -> WhereCondition {
84 self.condition.clone()
85 }
86
87 fn get_definition(&self, condition: &str) -> String {
88 let aliases = SourceAlias::new(&[("{:signed_entity:}", "se")]);
89 let projection = Self::Entity::get_projection().expand(aliases);
90 format!(
91 "select {projection} from signed_entity as se where {condition} order by ROWID desc"
92 )
93 }
94}
95
96#[cfg(test)]
97mod tests {
98 use mithril_common::entities::{BlockNumber, CardanoDbBeacon, SignedEntityType};
99 use mithril_persistence::sqlite::ConnectionExtensions;
100 use sqlite::ConnectionThreadSafe;
101
102 use crate::database::test_helper::{insert_signed_entities, main_db_connection};
103
104 use super::*;
105
106 fn create_database(records: &[SignedEntityRecord]) -> ConnectionThreadSafe {
107 let connection = main_db_connection().unwrap();
108 insert_signed_entities(&connection, records.to_vec()).unwrap();
109
110 connection
111 }
112
113 #[test]
114 fn by_signed_entity_and_epoch_returns_records_filtered_by_epoch() {
115 let records = vec![
116 SignedEntityRecord::fake_with_signed_entity(
117 SignedEntityType::CardanoStakeDistribution(Epoch(3)),
118 ),
119 SignedEntityRecord::fake_with_signed_entity(
120 SignedEntityType::CardanoStakeDistribution(Epoch(4)),
121 ),
122 SignedEntityRecord::fake_with_signed_entity(
123 SignedEntityType::CardanoStakeDistribution(Epoch(5)),
124 ),
125 ];
126
127 let connection = create_database(&records);
128
129 let records_retrieved: Vec<SignedEntityRecord> = connection
130 .fetch_collect(GetSignedEntityRecordQuery::by_signed_entity_type_and_epoch(
131 &SignedEntityTypeDiscriminants::CardanoStakeDistribution,
132 Epoch(4),
133 ))
134 .unwrap();
135
136 assert_eq!(vec![records[1].clone()], records_retrieved);
137 }
138
139 #[test]
140 fn by_signed_entity_and_epoch_returns_records_filtered_by_discriminant() {
141 let records = vec![
142 SignedEntityRecord::fake_with_signed_entity(
143 SignedEntityType::CardanoStakeDistribution(Epoch(3)),
144 ),
145 SignedEntityRecord::fake_with_signed_entity(
146 SignedEntityType::MithrilStakeDistribution(Epoch(3)),
147 ),
148 SignedEntityRecord::fake_with_signed_entity(SignedEntityType::CardanoDatabase(
149 CardanoDbBeacon::new(3, 98),
150 )),
151 ];
152
153 let connection = create_database(&records);
154
155 let fetched_msd_records: Vec<SignedEntityRecord> = connection
156 .fetch_collect(GetSignedEntityRecordQuery::by_signed_entity_type_and_epoch(
157 &SignedEntityTypeDiscriminants::MithrilStakeDistribution,
158 Epoch(3),
159 ))
160 .unwrap();
161 assert_eq!(vec![records[1].clone()], fetched_msd_records);
162
163 let fetched_cdb_records: Vec<SignedEntityRecord> = connection
164 .fetch_collect(GetSignedEntityRecordQuery::by_signed_entity_type_and_epoch(
165 &SignedEntityTypeDiscriminants::CardanoDatabase,
166 Epoch(3),
167 ))
168 .unwrap();
169 assert_eq!(vec![records[2].clone()], fetched_cdb_records);
170 }
171
172 #[test]
173 fn test_get_record_by_id() {
174 let signed_entity_records = vec![
175 SignedEntityRecord::fake_with_signed_entity(
176 SignedEntityType::CardanoStakeDistribution(Epoch(3)),
177 ),
178 SignedEntityRecord::fake_with_signed_entity(SignedEntityType::CardanoTransactions(
179 Epoch(4),
180 BlockNumber(5),
181 )),
182 ];
183
184 let connection = main_db_connection().unwrap();
185 insert_signed_entities(&connection, signed_entity_records.clone()).unwrap();
186
187 let first_signed_entity_type = signed_entity_records[0].clone();
188 let fetched_record = connection
189 .fetch_first(GetSignedEntityRecordQuery::by_signed_entity_id(
190 &first_signed_entity_type.signed_entity_id,
191 ))
192 .unwrap();
193 assert_eq!(Some(first_signed_entity_type), fetched_record);
194 }
195
196 #[test]
197 fn test_get_record_by_signed_entity_type() {
198 let signed_entity_records = vec![
199 SignedEntityRecord::fake_with_signed_entity(
200 SignedEntityType::MithrilStakeDistribution(Epoch(2)),
201 ),
202 SignedEntityRecord::fake_with_signed_entity(SignedEntityType::CardanoTransactions(
203 Epoch(4),
204 BlockNumber(5),
205 )),
206 SignedEntityRecord::fake_with_signed_entity(SignedEntityType::CardanoTransactions(
207 Epoch(5),
208 BlockNumber(9),
209 )),
210 ];
211
212 let connection = main_db_connection().unwrap();
213 insert_signed_entities(&connection, signed_entity_records.clone()).unwrap();
214
215 let fetched_tx_records: Vec<SignedEntityRecord> = connection
216 .fetch_collect(
217 GetSignedEntityRecordQuery::by_signed_entity_type(
218 &SignedEntityTypeDiscriminants::CardanoTransactions,
219 )
220 .unwrap(),
221 )
222 .unwrap();
223 let expected_tx_records: Vec<SignedEntityRecord> =
224 vec![signed_entity_records[2].clone(), signed_entity_records[1].clone()];
225 assert_eq!(expected_tx_records, fetched_tx_records);
226 }
227
228 #[test]
229 fn test_get_all_records() {
230 let signed_entity_records = SignedEntityRecord::fake_records(5);
231
232 let connection = main_db_connection().unwrap();
233 insert_signed_entities(&connection, signed_entity_records.clone()).unwrap();
234
235 let fetched_records: Vec<SignedEntityRecord> =
236 connection.fetch_collect(GetSignedEntityRecordQuery::all()).unwrap();
237 let expected_signed_entity_records: Vec<_> =
238 signed_entity_records.into_iter().rev().collect();
239 assert_eq!(expected_signed_entity_records, fetched_records);
240 }
241}