feophantlib/engine/objects/
sql_tuple.rs1use std::ops::Deref;
3
4use crate::engine::io::SelfEncodedSize;
5
6use super::types::{BaseSqlTypes, SqlTypeDefinition};
7use bytes::BufMut;
8use thiserror::Error;
9
10#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
11pub struct SqlTuple(pub Vec<Option<BaseSqlTypes>>);
12
13impl SqlTuple {
14 pub fn filter_map(
16 self,
17 source: &SqlTypeDefinition,
18 target: &SqlTypeDefinition,
19 ) -> Result<SqlTuple, SqlTupleError> {
20 if self.len() != source.len() {
21 return Err(SqlTupleError::SourceLenMismatch(self.len(), source.len()));
22 }
23
24 let mut output = Vec::with_capacity(target.len());
25
26 'outer: for (t_name, _) in target.iter() {
28 for s in 0..source.len() {
29 if *t_name == source[s].0 {
30 output.push(self.0[s].clone()); continue 'outer;
32 }
33 }
34 return Err(SqlTupleError::InvalidColumn(t_name.to_string()));
35 }
36
37 Ok(SqlTuple(output))
38 }
39
40 pub fn merge(left: &SqlTuple, right: &SqlTuple) -> SqlTuple {
41 SqlTuple(left.iter().cloned().chain(right.iter().cloned()).collect())
43 }
44
45 pub fn serialize(&self, buffer: &mut impl BufMut) {
46 for data in &self.0 {
47 match data {
48 Some(d) => d.serialize(buffer),
49 None => {}
50 }
51 }
52 }
53}
54
55impl Deref for SqlTuple {
56 type Target = Vec<Option<BaseSqlTypes>>;
57
58 fn deref(&self) -> &Self::Target {
59 &self.0
60 }
61}
62
63impl SelfEncodedSize for SqlTuple {
64 fn encoded_size(&self) -> usize {
65 self.iter().fold(0, |acc, col| match col {
66 Some(col_s) => acc + col_s.encoded_size(),
67 None => acc,
68 })
69 }
70}
71
72#[derive(Debug, Error)]
73pub enum SqlTupleError {
74 #[error("Tuple length {0} does not match source length {1}")]
75 SourceLenMismatch(usize, usize),
76 #[error("Requested Column Name: {0} doesn't exist")]
77 InvalidColumn(String),
78}
79
80#[cfg(test)]
81mod tests {
82 use bytes::BytesMut;
83
84 use super::*;
85 use crate::engine::objects::types::BaseSqlTypesMapper;
86
87 fn get_src_type() -> SqlTypeDefinition {
88 SqlTypeDefinition(vec![
89 ("foo".to_string(), BaseSqlTypesMapper::Integer),
90 ("bar".to_string(), BaseSqlTypesMapper::Text),
91 ("baz".to_string(), BaseSqlTypesMapper::Text),
92 ])
93 }
94
95 #[test]
96 fn sizes_match() -> Result<(), Box<dyn std::error::Error>> {
97 let test = SqlTuple(vec![
98 Some(BaseSqlTypes::Text("test".to_string())),
99 Some(BaseSqlTypes::Integer(0)),
100 ]);
101 let calc_len = test.encoded_size();
102
103 let mut buffer = BytesMut::new();
104 test.serialize(&mut buffer);
105
106 assert_eq!(calc_len, buffer.freeze().len());
107 Ok(())
108 }
109
110 #[test]
111 fn test_sql_tuple_filter() -> Result<(), Box<dyn std::error::Error>> {
112 let source = get_src_type();
113
114 let target = SqlTypeDefinition(vec![source[2].clone(), source[1].clone()]);
115
116 let src_cols = SqlTuple(vec![
117 None,
118 Some(BaseSqlTypes::Text("Test".to_string())),
119 Some(BaseSqlTypes::Text("Test2".to_string())),
120 ]);
121
122 let filtered = src_cols.filter_map(&source, &target)?;
123
124 let expected = SqlTuple(vec![
125 Some(BaseSqlTypes::Text("Test2".to_string())),
126 Some(BaseSqlTypes::Text("Test".to_string())),
127 ]);
128
129 assert_eq!(filtered, expected);
130
131 Ok(())
132 }
133
134 #[test]
135 fn test_sql_tuple_merge() -> Result<(), Box<dyn std::error::Error>> {
136 let left = SqlTuple(vec![
137 None,
138 Some(BaseSqlTypes::Text("Test".to_string())),
139 Some(BaseSqlTypes::Text("Test2".to_string())),
140 ]);
141
142 let right = SqlTuple(vec![
143 Some(BaseSqlTypes::Text("Test2".to_string())),
144 Some(BaseSqlTypes::Text("Test".to_string())),
145 ]);
146
147 let expected = SqlTuple(vec![
148 None,
149 Some(BaseSqlTypes::Text("Test".to_string())),
150 Some(BaseSqlTypes::Text("Test2".to_string())),
151 Some(BaseSqlTypes::Text("Test2".to_string())),
152 Some(BaseSqlTypes::Text("Test".to_string())),
153 ]);
154
155 let merged = SqlTuple::merge(&left, &right);
156
157 assert_eq!(merged, expected);
158
159 Ok(())
160 }
161
162 #[test]
163 fn test_encoded_size() {
164 let tuple = SqlTuple(vec![Some(BaseSqlTypes::Uuid(uuid::Uuid::new_v4())), None]);
165
166 let mut buffer = BytesMut::new();
167 tuple.serialize(&mut buffer);
168 let buffer = buffer.freeze();
169
170 assert_eq!(tuple.encoded_size(), buffer.len());
171 }
172}