opensrv_clickhouse/types/column/
nullable.rs

1// Copyright 2021 Datafuse Labs.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use 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}