clickhouse_native_client/column/mod.rs
1//! # Column Module
2//!
3//! This module provides implementations for all ClickHouse column types used
4//! in the native TCP protocol.
5//!
6//! ## ClickHouse Documentation
7//!
8//! - [Data Types Overview](https://clickhouse.com/docs/en/sql-reference/data-types)
9//! - [Nullable Type](https://clickhouse.com/docs/en/sql-reference/data-types/nullable)
10//! - [Array Type](https://clickhouse.com/docs/en/sql-reference/data-types/array)
11//! - [LowCardinality Type](https://clickhouse.com/docs/en/sql-reference/data-types/lowcardinality)
12//! - [Tuple Type](https://clickhouse.com/docs/en/sql-reference/data-types/tuple)
13//! - [Map Type](https://clickhouse.com/docs/en/sql-reference/data-types/map)
14//!
15//! ## Type Nesting Restrictions
16//!
17//! ClickHouse enforces strict rules about type nesting. The following
18//! combinations are **NOT allowed**:
19//!
20//! | Invalid Nesting | Error | Workaround |
21//! |----------------|-------|------------|
22//! | `Nullable(Array(...))` | "Nested type Array(...) cannot be inside Nullable type" (Error 43) | Use `Array(Nullable(...))` |
23//! | `Nullable(LowCardinality(...))` | "Nested type LowCardinality(...) cannot be inside Nullable type" | Use `LowCardinality(Nullable(...))` |
24//! | `Nullable(Array(LowCardinality(...)))` | Same as above | Use `Array(LowCardinality(Nullable(...)))` or `Array(Nullable(LowCardinality(...)))` |
25//!
26//! **Correct Nesting Order:**
27//! - ✅ `Array(Nullable(T))` - Array of nullable elements
28//! - ✅ `Array(LowCardinality(T))` - Array of low-cardinality elements
29//! - ✅ `Array(LowCardinality(Nullable(T)))` - Array of nullable
30//! low-cardinality elements
31//! - ✅ `LowCardinality(Nullable(T))` - Low-cardinality column with nullable
32//! values
33//!
34//! **References:**
35//! - [ClickHouse Issue #1062](https://github.com/ClickHouse/ClickHouse/issues/1062)
36//! - Arrays cannot be nullable
37//! - [ClickHouse Issue #42456](https://github.com/ClickHouse/ClickHouse/issues/42456)
38//! - LowCardinality cannot be inside Nullable
39
40/// Array column type (`Array(T)`).
41pub mod array;
42/// Column value extraction and insertion helpers.
43pub mod column_value;
44/// Date and DateTime column types.
45pub mod date;
46/// Decimal column types (`Decimal32`, `Decimal64`, `Decimal128`).
47pub mod decimal;
48/// Enum8 and Enum16 column types.
49pub mod enum_column;
50/// Geo type helpers (Point, Ring, Polygon, MultiPolygon).
51pub mod geo;
52/// IPv4 column type.
53pub mod ipv4;
54/// IPv6 column type.
55pub mod ipv6;
56/// LowCardinality column type (dictionary encoding).
57pub mod lowcardinality;
58/// Map column type (`Map(K, V)`).
59pub mod map;
60/// Nothing/Void column type.
61pub mod nothing;
62/// Nullable column type (`Nullable(T)`).
63pub mod nullable;
64/// Numeric column types (integers, floats, bool).
65pub mod numeric;
66/// String and FixedString column types.
67pub mod string;
68/// Tuple column type (`Tuple(T1, T2, ...)`).
69pub mod tuple;
70/// UUID column type.
71pub mod uuid;
72
73// Re-export column types for easier access
74pub use array::{
75 ColumnArray,
76 ColumnArrayT,
77};
78pub use date::{
79 ColumnDate,
80 ColumnDate32,
81 ColumnDateTime,
82 ColumnDateTime64,
83};
84pub use decimal::ColumnDecimal;
85pub use enum_column::{
86 ColumnEnum16,
87 ColumnEnum8,
88};
89pub use ipv4::ColumnIpv4;
90pub use ipv6::ColumnIpv6;
91pub use lowcardinality::ColumnLowCardinality;
92pub use map::ColumnMap;
93pub use nothing::ColumnNothing;
94pub use nullable::ColumnNullable;
95pub use numeric::*;
96pub use string::{
97 ColumnFixedString,
98 ColumnString,
99};
100pub use tuple::ColumnTuple;
101pub use uuid::{
102 ColumnUuid,
103 Uuid,
104};
105
106use crate::{
107 types::Type,
108 Result,
109};
110use bytes::BytesMut;
111use std::sync::Arc;
112
113/// Reference to a column (using Arc for cheap cloning)
114pub type ColumnRef = Arc<dyn Column>;
115
116/// Base trait for all column types
117/// Note: We use byte buffers instead of generic readers/writers to make the
118/// trait dyn-compatible
119pub trait Column: Send + Sync {
120 /// Get the type of this column
121 fn column_type(&self) -> &Type;
122
123 /// Get the number of rows in this column
124 fn size(&self) -> usize;
125
126 /// Clear all data from the column
127 fn clear(&mut self);
128
129 /// Reserve capacity for at least `new_cap` elements
130 fn reserve(&mut self, new_cap: usize);
131
132 /// Append another column's data to this column
133 fn append_column(&mut self, other: ColumnRef) -> Result<()>;
134
135 /// Load column prefix from byte buffer (for types that need prefix data)
136 /// Default implementation is a no-op. Override for types like
137 /// LowCardinality. This matches C++ clickhouse-cpp's LoadPrefix pattern.
138 fn load_prefix(
139 &mut self,
140 _buffer: &mut &[u8],
141 _rows: usize,
142 ) -> Result<()> {
143 // Default: no prefix data to read
144 Ok(())
145 }
146
147 /// Load column data from byte buffer
148 fn load_from_buffer(
149 &mut self,
150 buffer: &mut &[u8],
151 rows: usize,
152 ) -> Result<()>;
153
154 /// Save column prefix to byte buffer (for types that need prefix data)
155 /// Default implementation is a no-op. Override for types like
156 /// LowCardinality, Array with special nested types. This matches C++
157 /// clickhouse-cpp's SavePrefix pattern.
158 fn save_prefix(&self, _buffer: &mut BytesMut) -> Result<()> {
159 // Default: no prefix data to write
160 Ok(())
161 }
162
163 /// Save column data to byte buffer
164 fn save_to_buffer(&self, buffer: &mut BytesMut) -> Result<()>;
165
166 /// Create an empty clone of this column (same type, no data)
167 fn clone_empty(&self) -> ColumnRef;
168
169 /// Create a slice of this column
170 fn slice(&self, begin: usize, len: usize) -> Result<ColumnRef>;
171
172 /// Downcast to a concrete column type
173 fn as_any(&self) -> &dyn std::any::Any;
174
175 /// Downcast to a mutable concrete column type
176 fn as_any_mut(&mut self) -> &mut dyn std::any::Any;
177}
178
179/// Helper trait for column types that can be downcasted
180pub trait ColumnTyped<T>: Column {
181 /// Get value at index
182 fn get(&self, index: usize) -> Option<T>;
183
184 /// Append a value to the column
185 fn append(&mut self, value: T);
186}
187
188/// Trait for columns that support iteration over their values.
189pub trait ColumnIter<T> {
190 /// The iterator type returned by [`iter`](Self::iter).
191 type Iter<'a>: Iterator<Item = T>
192 where
193 Self: 'a;
194
195 /// Returns an iterator over the column values.
196 fn iter(&self) -> Self::Iter<'_>;
197}
198
199#[cfg(test)]
200#[cfg_attr(coverage_nightly, coverage(off))]
201mod tests {
202 // Tests will be in individual column implementations
203}