1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
use std::ops::Deref;
use super::types::{BaseSqlTypes, SqlTypeDefinition};
use thiserror::Error;
#[derive(Clone, Debug, PartialEq)]
pub struct SqlTuple(pub Vec<Option<BaseSqlTypes>>);
impl SqlTuple {
pub fn filter_map(
self,
source: &SqlTypeDefinition,
target: &SqlTypeDefinition,
) -> Result<SqlTuple, SqlTupleError> {
if self.0.len() != source.len() {
return Err(SqlTupleError::SourceLenMismatch(self.0.len(), source.len()));
}
let mut output = Vec::with_capacity(target.len());
'outer: for (t_name, t) in target.iter() {
for s in 0..source.len() {
if *t_name == source[s].0 {
output.push(self.0[s].clone());
continue 'outer;
}
}
return Err(SqlTupleError::InvalidColumn(t_name.to_string()));
}
Ok(SqlTuple(output))
}
pub fn merge(left: &SqlTuple, right: &SqlTuple) -> SqlTuple {
SqlTuple(
left.0
.iter()
.cloned()
.chain(right.0.iter().cloned())
.collect(),
)
}
}
impl Deref for SqlTuple {
type Target = Vec<Option<BaseSqlTypes>>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
#[derive(Debug, Error)]
pub enum SqlTupleError {
#[error("Tuple length {0} does not match source length {1}")]
SourceLenMismatch(usize, usize),
#[error("Requested Column Name: {0} doesn't exist")]
InvalidColumn(String),
}
#[cfg(test)]
mod tests {
use super::*;
use crate::engine::objects::types::BaseSqlTypesMapper;
fn get_src_type() -> SqlTypeDefinition {
SqlTypeDefinition(vec![
("foo".to_string(), BaseSqlTypesMapper::Integer),
("bar".to_string(), BaseSqlTypesMapper::Text),
("baz".to_string(), BaseSqlTypesMapper::Text),
])
}
#[test]
fn test_sql_tuple_filter() -> Result<(), Box<dyn std::error::Error>> {
let source = get_src_type();
let target = SqlTypeDefinition(vec![source[2].clone(), source[1].clone()]);
let src_cols = SqlTuple(vec![
None,
Some(BaseSqlTypes::Text("Test".to_string())),
Some(BaseSqlTypes::Text("Test2".to_string())),
]);
let filtered = src_cols.filter_map(&source, &target)?;
let expected = SqlTuple(vec![
Some(BaseSqlTypes::Text("Test2".to_string())),
Some(BaseSqlTypes::Text("Test".to_string())),
]);
assert_eq!(filtered, expected);
Ok(())
}
#[test]
fn test_sql_tuple_merge() -> Result<(), Box<dyn std::error::Error>> {
let left = SqlTuple(vec![
None,
Some(BaseSqlTypes::Text("Test".to_string())),
Some(BaseSqlTypes::Text("Test2".to_string())),
]);
let right = SqlTuple(vec![
Some(BaseSqlTypes::Text("Test2".to_string())),
Some(BaseSqlTypes::Text("Test".to_string())),
]);
let expected = SqlTuple(vec![
None,
Some(BaseSqlTypes::Text("Test".to_string())),
Some(BaseSqlTypes::Text("Test2".to_string())),
Some(BaseSqlTypes::Text("Test2".to_string())),
Some(BaseSqlTypes::Text("Test".to_string())),
]);
let merged = SqlTuple::merge(&left, &right);
assert_eq!(merged, expected);
Ok(())
}
}