mithril_persistence/database/query/block_range_root/
get_block_range_root.rs1use sqlite::Value;
2
3use mithril_common::entities::BlockNumber;
4
5use crate::database::record::BlockRangeRootRecord;
6use crate::sqlite::{Query, SourceAlias, SqLiteEntity, WhereCondition};
7
8pub struct GetBlockRangeRootQuery {
10 condition: WhereCondition,
11}
12
13impl GetBlockRangeRootQuery {
14 pub fn all() -> Self {
15 Self {
16 condition: WhereCondition::default(),
17 }
18 }
19
20 pub fn contains_or_below_block_number(block_number: BlockNumber) -> Self {
21 Self {
22 condition: WhereCondition::new(
23 "start < ?*",
24 vec![Value::Integer(*block_number as i64)],
25 ),
26 }
27 }
28
29 pub fn highest() -> Self {
30 Self {
31 condition: WhereCondition::new("end = (select max(end) from block_range_root)", vec![]),
32 }
33 }
34}
35
36impl Query for GetBlockRangeRootQuery {
37 type Entity = BlockRangeRootRecord;
38
39 fn filters(&self) -> WhereCondition {
40 self.condition.clone()
41 }
42
43 fn get_definition(&self, condition: &str) -> String {
44 let aliases = SourceAlias::new(&[("{:block_range_root:}", "block_range_root")]);
45 let projection = Self::Entity::get_projection().expand(aliases);
46
47 format!("select {projection} from block_range_root where {condition} order by start, end")
48 }
49}
50
51#[cfg(test)]
52mod tests {
53 use mithril_common::crypto_helper::MKTreeNode;
54 use mithril_common::entities::BlockRange;
55
56 use crate::database::query::block_range_root::test_helper::insert_block_range_roots;
57 use crate::database::query::GetBlockRangeRootQuery;
58 use crate::database::test_helper::cardano_tx_db_connection;
59 use crate::sqlite::ConnectionExtensions;
60
61 use super::*;
62
63 fn block_range_root_dataset() -> Vec<BlockRangeRootRecord> {
64 [
65 (
66 BlockRange::from_block_number(BlockNumber(15)),
67 MKTreeNode::from_hex("AAAA").unwrap(),
68 ),
69 (
70 BlockRange::from_block_number(BlockNumber(30)),
71 MKTreeNode::from_hex("BBBB").unwrap(),
72 ),
73 (
74 BlockRange::from_block_number(BlockNumber(45)),
75 MKTreeNode::from_hex("CCCC").unwrap(),
76 ),
77 ]
78 .into_iter()
79 .map(BlockRangeRootRecord::from)
80 .collect()
81 }
82
83 #[test]
84 fn test_get_contains_or_below_block_number_with_empty_db() {
85 let connection = cardano_tx_db_connection().unwrap();
86
87 let cursor: Vec<BlockRangeRootRecord> = connection
88 .fetch_collect(GetBlockRangeRootQuery::contains_or_below_block_number(
89 BlockNumber(100),
90 ))
91 .unwrap();
92 assert_eq!(Vec::<BlockRangeRootRecord>::new(), cursor);
93 }
94
95 #[test]
96 fn test_get_contains_or_below_block_number_higher_than_the_highest_stored_block_range() {
97 let connection = cardano_tx_db_connection().unwrap();
98 let dataset = block_range_root_dataset();
99 insert_block_range_roots(&connection, dataset.clone());
100
101 let cursor: Vec<BlockRangeRootRecord> = connection
102 .fetch_collect(GetBlockRangeRootQuery::contains_or_below_block_number(
103 BlockNumber(10_000),
104 ))
105 .unwrap();
106
107 assert_eq!(dataset, cursor);
108 }
109
110 #[test]
111 fn test_get_contains_or_below_block_number_below_end_of_the_third_block_range() {
112 let connection = cardano_tx_db_connection().unwrap();
113 let dataset = block_range_root_dataset();
114 insert_block_range_roots(&connection, dataset.clone());
115
116 let cursor: Vec<BlockRangeRootRecord> = connection
117 .fetch_collect(GetBlockRangeRootQuery::contains_or_below_block_number(
118 BlockNumber(44),
119 ))
120 .unwrap();
121
122 assert_eq!(&dataset[0..2], &cursor);
123 }
124
125 #[test]
126 fn test_get_contains_or_below_block_number_equal_to_end_of_the_third_block_range() {
127 let connection = cardano_tx_db_connection().unwrap();
128 let dataset = block_range_root_dataset();
129 insert_block_range_roots(&connection, dataset.clone());
130
131 let cursor: Vec<BlockRangeRootRecord> = connection
132 .fetch_collect(GetBlockRangeRootQuery::contains_or_below_block_number(
133 BlockNumber(45),
134 ))
135 .unwrap();
136
137 assert_eq!(&dataset[0..2], &cursor);
138 }
139
140 #[test]
141 fn test_get_contains_or_below_block_number_after_end_of_the_third_block_range() {
142 let connection = cardano_tx_db_connection().unwrap();
143 let dataset = block_range_root_dataset();
144 insert_block_range_roots(&connection, dataset.clone());
145
146 let cursor: Vec<BlockRangeRootRecord> = connection
147 .fetch_collect(GetBlockRangeRootQuery::contains_or_below_block_number(
148 BlockNumber(46),
149 ))
150 .unwrap();
151
152 assert_eq!(dataset, cursor);
153 }
154
155 #[test]
156 fn test_get_highest_with_empty_db() {
157 let connection = cardano_tx_db_connection().unwrap();
158
159 let cursor: Option<BlockRangeRootRecord> = connection
160 .fetch_first(GetBlockRangeRootQuery::highest())
161 .unwrap();
162 assert_eq!(None, cursor);
163 }
164
165 #[test]
166 fn test_get_highest() {
167 let connection = cardano_tx_db_connection().unwrap();
168 let dataset = block_range_root_dataset();
169 insert_block_range_roots(&connection, dataset.clone());
170
171 let cursor: Option<BlockRangeRootRecord> = connection
172 .fetch_first(GetBlockRangeRootQuery::highest())
173 .unwrap();
174 assert_eq!(dataset.last().cloned(), cursor);
175 }
176}