opensrv_clickhouse/types/column/
tuple.rs1use std::sync::Arc;
16
17use chrono_tz::Tz;
18
19use crate::binary::Encoder;
20use crate::binary::ReadEx;
21use crate::errors::Result;
22use crate::types::column::column_data::ArcColumnData;
23use crate::types::column::column_data::BoxColumnData;
24use crate::types::column::ArcColumnWrapper;
25use crate::types::column::ColumnData;
26use crate::types::column::ColumnFrom;
27use crate::types::column::ColumnWrapper;
28use crate::types::SqlType;
29use crate::types::Value;
30use crate::types::ValueRef;
31
32pub struct TupleColumnData {
33 pub inner: Vec<ArcColumnData>,
34}
35
36impl TupleColumnData {
37 pub(crate) fn load<R: ReadEx>(
38 reader: &mut R,
39 inner_types: Vec<&str>,
40 rows: usize,
41 tz: Tz,
42 ) -> Result<Self> {
43 let inner = inner_types
44 .into_iter()
45 .map(|type_name| {
46 <dyn ColumnData>::load_data::<ArcColumnWrapper, _>(reader, type_name, rows, tz)
47 .unwrap()
48 })
49 .collect();
50 Ok(Self { inner })
51 }
52}
53
54impl ColumnFrom for Vec<ArcColumnData> {
55 fn column_from<W: ColumnWrapper>(inner: Self) -> W::Wrapper {
56 W::wrap(TupleColumnData { inner })
57 }
58}
59
60impl ColumnData for TupleColumnData {
61 fn sql_type(&self) -> SqlType {
62 SqlType::Tuple(self.inner.iter().map(|c| c.sql_type().into()).collect())
63 }
64
65 fn save(&self, encoder: &mut Encoder, start: usize, end: usize) {
66 self.inner.iter().for_each(|c| c.save(encoder, start, end));
67 }
68
69 fn len(&self) -> usize {
70 self.inner[0].len()
71 }
72
73 fn push(&mut self, value: Value) {
74 if let Value::Tuple(vs) = value {
75 vs.iter().zip(self.inner.iter_mut()).for_each(|(v, c)| {
76 let inner_column = Arc::get_mut(c).unwrap();
77 inner_column.push(v.clone());
78 });
79 } else {
80 panic!("value should be a tuple");
81 }
82 }
83
84 fn at(&self, index: usize) -> ValueRef {
85 ValueRef::Tuple(Arc::new(self.inner.iter().map(|c| c.at(index)).collect()))
86 }
87
88 fn clone_instance(&self) -> BoxColumnData {
89 Box::new(Self {
90 inner: self.inner.clone(),
91 })
92 }
93
94 fn cast_to(&self, _this: &ArcColumnData, target: &SqlType) -> Option<ArcColumnData> {
95 if let SqlType::Tuple(target_types) = target {
96 if target_types.len() == self.inner.len() {
97 let mut new_inner = Vec::with_capacity(self.inner.len());
98 for (i, c) in self.inner.iter().enumerate() {
99 let target_type = target_types[i];
100 let new_c = c.cast_to(c, target_type);
101 if let Some(new_c) = new_c {
102 new_inner.push(new_c);
103 } else {
104 return None;
105 }
106 }
107 return Some(Arc::new(TupleColumnData { inner: new_inner }));
108 }
109 }
110 None
111 }
112}