Skip to main content

clickhouse_native_client/column/
nothing.rs

1//! Nothing/Void column implementation.
2//!
3//! This is a dummy column that tracks size without storing actual data.
4//! Used for `NULL`-only columns or as a placeholder.
5
6use super::{
7    Column,
8    ColumnRef,
9};
10use crate::{
11    types::Type,
12    Error,
13    Result,
14};
15use bytes::BytesMut;
16use std::sync::Arc;
17
18/// Column for Nothing/Void type. Tracks row count without storing data.
19pub struct ColumnNothing {
20    type_: Type,
21    size: usize,
22}
23
24impl ColumnNothing {
25    /// Create a new empty Nothing column.
26    pub fn new(type_: Type) -> Self {
27        Self { type_, size: 0 }
28    }
29
30    /// Set the initial size (number of nothing/null entries).
31    pub fn with_size(mut self, size: usize) -> Self {
32        self.size = size;
33        self
34    }
35
36    /// Append a NULL/nothing value (just increments size)
37    pub fn append(&mut self) {
38        self.size += 1;
39    }
40
41    /// Get value at index (always returns None)
42    pub fn at(&self, _index: usize) -> Option<()> {
43        None
44    }
45
46    /// Returns the number of entries in this column.
47    pub fn len(&self) -> usize {
48        self.size
49    }
50
51    /// Returns `true` if the column contains no entries.
52    pub fn is_empty(&self) -> bool {
53        self.size == 0
54    }
55}
56
57impl Column for ColumnNothing {
58    fn column_type(&self) -> &Type {
59        &self.type_
60    }
61
62    fn size(&self) -> usize {
63        self.size
64    }
65
66    fn clear(&mut self) {
67        self.size = 0;
68    }
69
70    fn reserve(&mut self, _new_cap: usize) {
71        // Nothing to reserve
72    }
73
74    fn append_column(&mut self, other: ColumnRef) -> Result<()> {
75        let other = other
76            .as_any()
77            .downcast_ref::<ColumnNothing>()
78            .ok_or_else(|| Error::TypeMismatch {
79                expected: self.type_.name(),
80                actual: other.column_type().name(),
81            })?;
82
83        self.size += other.size;
84        Ok(())
85    }
86
87    fn load_from_buffer(
88        &mut self,
89        buffer: &mut &[u8],
90        rows: usize,
91    ) -> Result<()> {
92        // Nothing type doesn't actually consume any data
93        // But we need to skip the appropriate bytes (1 byte per row of
94        // "nothing")
95        if buffer.len() < rows {
96            return Err(Error::Protocol(
97                "Not enough data for Nothing".to_string(),
98            ));
99        }
100        *buffer = &buffer[rows..];
101        self.size += rows;
102        Ok(())
103    }
104
105    fn save_to_buffer(&self, _buffer: &mut BytesMut) -> Result<()> {
106        // Nothing type doesn't serialize any data
107        // According to C++ implementation, SaveBody should not be supported
108        Err(Error::Protocol(
109            "SaveBody is not supported for Nothing column".to_string(),
110        ))
111    }
112
113    fn clone_empty(&self) -> ColumnRef {
114        Arc::new(ColumnNothing::new(self.type_.clone()))
115    }
116
117    fn slice(&self, _begin: usize, len: usize) -> Result<ColumnRef> {
118        // Slice just creates a new Nothing column with the specified length
119        Ok(Arc::new(ColumnNothing::new(self.type_.clone()).with_size(len)))
120    }
121
122    fn as_any(&self) -> &dyn std::any::Any {
123        self
124    }
125
126    fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
127        self
128    }
129}
130
131#[cfg(test)]
132#[cfg_attr(coverage_nightly, coverage(off))]
133mod tests {
134    use super::*;
135    use crate::types::TypeCode;
136
137    fn void_type() -> Type {
138        Type::Simple(TypeCode::Void)
139    }
140
141    #[test]
142    fn test_nothing_append() {
143        let mut col = ColumnNothing::new(void_type());
144        col.append();
145        col.append();
146        col.append();
147
148        assert_eq!(col.len(), 3);
149        assert_eq!(col.at(0), None);
150        assert_eq!(col.at(1), None);
151        assert_eq!(col.at(2), None);
152    }
153
154    #[test]
155    fn test_nothing_with_size() {
156        let col = ColumnNothing::new(void_type()).with_size(10);
157        assert_eq!(col.len(), 10);
158    }
159
160    #[test]
161    fn test_nothing_slice() {
162        let col = ColumnNothing::new(void_type()).with_size(10);
163        let sliced = col.slice(2, 5).unwrap();
164        let sliced_col =
165            sliced.as_any().downcast_ref::<ColumnNothing>().unwrap();
166
167        assert_eq!(sliced_col.len(), 5);
168    }
169
170    #[test]
171    fn test_nothing_append_column() {
172        let mut col1 = ColumnNothing::new(void_type()).with_size(5);
173        let col2 = Arc::new(ColumnNothing::new(void_type()).with_size(3));
174
175        col1.append_column(col2).unwrap();
176        assert_eq!(col1.len(), 8);
177    }
178
179    #[test]
180    fn test_nothing_clear() {
181        let mut col = ColumnNothing::new(void_type()).with_size(10);
182        assert_eq!(col.len(), 10);
183
184        col.clear();
185        assert_eq!(col.len(), 0);
186        assert!(col.is_empty());
187    }
188}