mithril_signer/database/query/signed_beacon/
get_signed_beacon.rs1use sqlite::Value;
2
3use mithril_common::StdResult;
4use mithril_common::entities::SignedEntityType;
5use mithril_persistence::sqlite::{Query, SourceAlias, SqLiteEntity, WhereCondition};
6
7use crate::database::record::SignedBeaconRecord;
8
9pub struct GetSignedBeaconQuery {
11 condition: WhereCondition,
12}
13
14impl GetSignedBeaconQuery {
15 pub fn all() -> Self {
17 Self {
18 condition: WhereCondition::default(),
19 }
20 }
21
22 pub fn by_signed_entities(signed_entity_types: &[SignedEntityType]) -> StdResult<Self> {
24 fn signed_entity_condition(entity: &SignedEntityType) -> StdResult<WhereCondition> {
25 Ok(WhereCondition::new(
26 "signed_entity_type_id = ?* and beacon = ?*",
27 vec![
28 Value::Integer(entity.index() as i64),
29 Value::String(entity.get_json_beacon()?),
30 ],
31 ))
32 }
33
34 let condition = match signed_entity_types {
35 [] => WhereCondition::new("false", vec![]),
36 [first, rest @ ..] => {
37 rest.iter()
38 .try_fold(signed_entity_condition(first)?, |condition, entity| {
39 StdResult::Ok(condition.or_where(signed_entity_condition(entity)?))
40 })?
41 }
42 };
43
44 Ok(Self { condition })
45 }
46}
47
48impl Query for GetSignedBeaconQuery {
49 type Entity = SignedBeaconRecord;
50
51 fn filters(&self) -> WhereCondition {
52 self.condition.clone()
53 }
54
55 fn get_definition(&self, condition: &str) -> String {
56 let aliases = SourceAlias::new(&[("{:signed_beacon:}", "signed_beacon")]);
57 let projection = Self::Entity::get_projection().expand(aliases);
58 format!("select {projection} from signed_beacon where {condition} order by rowid desc")
59 }
60}
61
62#[cfg(test)]
63mod tests {
64 use mithril_common::entities::{BlockNumber, Epoch};
65 use mithril_persistence::sqlite::ConnectionExtensions;
66
67 use crate::database::test_helper::{insert_signed_beacons, main_db_connection};
68
69 use super::*;
70
71 #[test]
72 fn test_get_all() {
73 let connection = main_db_connection().unwrap();
74 let records = SignedBeaconRecord::fakes(&[
75 (
76 Epoch(3),
77 vec![SignedEntityType::MithrilStakeDistribution(Epoch(3))],
78 ),
79 (
80 Epoch(4),
81 vec![
82 SignedEntityType::CardanoStakeDistribution(Epoch(4)),
83 SignedEntityType::CardanoTransactions(Epoch(4), BlockNumber(124)),
84 ],
85 ),
86 ]);
87 insert_signed_beacons(&connection, records.clone());
88
89 let stored_records: Vec<SignedBeaconRecord> =
90 connection.fetch_collect(GetSignedBeaconQuery::all()).unwrap();
91
92 assert_eq!(
93 records.into_iter().rev().collect::<Vec<_>>(),
94 stored_records
95 );
96 }
97
98 mod get_by_signed_entities {
99 use super::*;
100
101 #[test]
102 fn with_empty_db() {
103 let connection = main_db_connection().unwrap();
104
105 let stored_records: Vec<SignedBeaconRecord> = connection
106 .fetch_collect(
107 GetSignedBeaconQuery::by_signed_entities(&[
108 SignedEntityType::MithrilStakeDistribution(Epoch(3)),
109 SignedEntityType::CardanoTransactions(Epoch(4), BlockNumber(124)),
110 ])
111 .unwrap(),
112 )
113 .unwrap();
114
115 assert_eq!(Vec::<SignedBeaconRecord>::new(), stored_records);
116 }
117
118 #[test]
119 fn with_empty_list() {
120 let connection = main_db_connection().unwrap();
121 let records = SignedBeaconRecord::fakes(&[
122 (
123 Epoch(3),
124 vec![SignedEntityType::MithrilStakeDistribution(Epoch(3))],
125 ),
126 (
127 Epoch(4),
128 vec![SignedEntityType::CardanoStakeDistribution(Epoch(4))],
129 ),
130 ]);
131 insert_signed_beacons(&connection, records.clone());
132
133 let stored_records: Vec<SignedBeaconRecord> = connection
134 .fetch_collect(GetSignedBeaconQuery::by_signed_entities(&[]).unwrap())
135 .unwrap();
136
137 assert_eq!(Vec::<SignedBeaconRecord>::new(), stored_records);
138 }
139
140 #[test]
141 fn with_one_matching() {
142 let connection = main_db_connection().unwrap();
143 let records = SignedBeaconRecord::fakes(&[
144 (
145 Epoch(974),
146 vec![SignedEntityType::MithrilStakeDistribution(Epoch(3))],
147 ),
148 (
149 Epoch(975),
150 vec![SignedEntityType::CardanoStakeDistribution(Epoch(4))],
151 ),
152 ]);
153 insert_signed_beacons(&connection, records.clone());
154
155 let stored_records: Vec<SignedBeaconRecord> = connection
156 .fetch_collect(
157 GetSignedBeaconQuery::by_signed_entities(&[
158 SignedEntityType::MithrilStakeDistribution(Epoch(3)),
159 ])
160 .unwrap(),
161 )
162 .unwrap();
163
164 assert_eq!(
165 vec![SignedBeaconRecord::fake(
166 Epoch(974),
167 SignedEntityType::MithrilStakeDistribution(Epoch(3))
168 )],
169 stored_records
170 );
171 }
172
173 #[test]
174 fn with_multiple_matching_over_several_epochs() {
175 let connection = main_db_connection().unwrap();
176 let records = SignedBeaconRecord::fakes(&[
177 (
178 Epoch(329),
179 vec![
180 SignedEntityType::MithrilStakeDistribution(Epoch(3)),
181 SignedEntityType::CardanoStakeDistribution(Epoch(3)),
182 ],
183 ),
184 (
185 Epoch(330),
186 vec![
187 SignedEntityType::CardanoStakeDistribution(Epoch(4)),
188 SignedEntityType::MithrilStakeDistribution(Epoch(4)),
189 SignedEntityType::CardanoTransactions(Epoch(4), BlockNumber(109)),
190 ],
191 ),
192 (
193 Epoch(331),
194 vec![
195 SignedEntityType::CardanoTransactions(Epoch(5), BlockNumber(124)),
196 SignedEntityType::CardanoTransactions(Epoch(5), BlockNumber(133)),
197 ],
198 ),
199 ]);
200 insert_signed_beacons(&connection, records.clone());
201
202 let stored_records: Vec<SignedBeaconRecord> = connection
203 .fetch_collect(
204 GetSignedBeaconQuery::by_signed_entities(&[
205 SignedEntityType::MithrilStakeDistribution(Epoch(3)),
206 SignedEntityType::MithrilStakeDistribution(Epoch(4)),
207 SignedEntityType::CardanoTransactions(Epoch(4), BlockNumber(109)),
208 SignedEntityType::CardanoTransactions(Epoch(5), BlockNumber(133)),
209 ])
210 .unwrap(),
211 )
212 .unwrap();
213
214 assert_eq!(
215 SignedBeaconRecord::fakes(&[
216 (
217 Epoch(331),
218 vec![SignedEntityType::CardanoTransactions(Epoch(5), BlockNumber(133)),],
219 ),
220 (
221 Epoch(330),
222 vec![
223 SignedEntityType::CardanoTransactions(Epoch(4), BlockNumber(109)),
224 SignedEntityType::MithrilStakeDistribution(Epoch(4)),
225 ],
226 ),
227 (
228 Epoch(329),
229 vec![SignedEntityType::MithrilStakeDistribution(Epoch(3)),],
230 ),
231 ]),
232 stored_records
233 );
234 }
235
236 #[test]
237 fn duplicate_entities_in_parameter_should_not_yield_duplicate_matching() {
238 let connection = main_db_connection().unwrap();
239 let records = SignedBeaconRecord::fakes(&[(
240 Epoch(242),
241 vec![SignedEntityType::MithrilStakeDistribution(Epoch(3))],
242 )]);
243 insert_signed_beacons(&connection, records.clone());
244
245 let stored_records: Vec<SignedBeaconRecord> = connection
246 .fetch_collect(
247 GetSignedBeaconQuery::by_signed_entities(&[
248 SignedEntityType::MithrilStakeDistribution(Epoch(3)),
249 SignedEntityType::MithrilStakeDistribution(Epoch(3)),
250 ])
251 .unwrap(),
252 )
253 .unwrap();
254
255 assert_eq!(
256 vec![SignedBeaconRecord::fake(
257 Epoch(242),
258 SignedEntityType::MithrilStakeDistribution(Epoch(3))
259 )],
260 stored_records
261 );
262 }
263 }
264}