opensrv_clickhouse/types/column/
nullable.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::Either;
27use crate::types::SqlType;
28use crate::types::Value;
29use crate::types::ValueRef;
30
31pub struct NullableColumnData {
32 pub inner: ArcColumnData,
33 pub nulls: Vec<u8>,
34}
35
36impl NullableColumnData {
37 pub(crate) fn load<R: ReadEx>(
38 reader: &mut R,
39 type_name: &str,
40 size: usize,
41 tz: Tz,
42 ) -> Result<Self> {
43 let mut nulls = vec![0; size];
44 reader.read_bytes(nulls.as_mut())?;
45 let inner =
46 <dyn ColumnData>::load_data::<ArcColumnWrapper, _>(reader, type_name, size, tz)?;
47 Ok(NullableColumnData { inner, nulls })
48 }
49}
50
51impl ColumnData for NullableColumnData {
52 fn sql_type(&self) -> SqlType {
53 let inner_type = self.inner.sql_type();
54 SqlType::Nullable(inner_type.into())
55 }
56
57 fn save(&self, encoder: &mut Encoder, start: usize, end: usize) {
58 let nulls: &[u8] = self.nulls.as_ref();
59 encoder.write_bytes(&nulls[start..end]);
60 self.inner.save(encoder, start, end);
61 }
62
63 fn len(&self) -> usize {
64 assert_eq!(self.nulls.len(), self.inner.len());
65 self.inner.len()
66 }
67
68 fn push(&mut self, value: Value) {
69 let inner_column: &mut dyn ColumnData = Arc::get_mut(&mut self.inner).unwrap();
70
71 if let Value::Nullable(e) = value {
72 match e {
73 Either::Left(sql_type) => {
74 let default_value = Value::default(sql_type.clone());
75 inner_column.push(default_value);
76 self.nulls.push(true as u8);
77 }
78 Either::Right(inner) => {
79 inner_column.push(*inner);
80 self.nulls.push(false as u8);
81 }
82 }
83 } else {
84 inner_column.push(value);
85 self.nulls.push(false as u8);
86 }
87 }
88
89 fn at(&self, index: usize) -> ValueRef {
90 if self.nulls[index] == 1 {
91 let sql_type = self.inner.sql_type();
92 ValueRef::Nullable(Either::Left(sql_type.into()))
93 } else {
94 let inner_value = self.inner.at(index);
95 ValueRef::Nullable(Either::Right(Box::new(inner_value)))
96 }
97 }
98
99 fn clone_instance(&self) -> BoxColumnData {
100 Box::new(Self {
101 inner: self.inner.clone(),
102 nulls: self.nulls.clone(),
103 })
104 }
105
106 unsafe fn get_internal(&self, pointers: &[*mut *const u8], level: u8) -> Result<()> {
107 if level == self.sql_type().level() {
108 *pointers[0] = self.nulls.as_ptr();
109 *(pointers[1] as *mut usize) = self.len();
110 Ok(())
111 } else {
112 self.inner.get_internal(pointers, level)
113 }
114 }
115
116 fn cast_to(&self, _this: &ArcColumnData, target: &SqlType) -> Option<ArcColumnData> {
117 if let SqlType::Nullable(inner_target) = target {
118 if let Some(inner) = self.inner.cast_to(&self.inner, inner_target) {
119 return Some(Arc::new(NullableColumnData {
120 inner,
121 nulls: self.nulls.clone(),
122 }));
123 }
124 }
125 None
126 }
127}