1use rudb_common::{Error, LogicalType, Result};
4
5#[derive(Debug, Clone, PartialEq, Eq)]
11pub enum DataType {
12 Null,
14 Boolean,
16 Int8,
18 Int16,
20 Int32,
22 Int64,
24 UInt8,
26 UInt16,
28 UInt32,
30 UInt64,
32 Float32,
34 Float64,
36 Utf8,
38 Binary,
40 Date32,
42 Time64,
44 Timestamp(TimeUnit, Option<String>),
46 Interval,
48 Decimal128 {
50 precision: u8,
52 scale: u8,
54 },
55}
56
57#[derive(Debug, Clone, Copy, PartialEq, Eq)]
59pub enum TimeUnit {
60 Second,
62 Millisecond,
64 Microsecond,
66 Nanosecond,
68}
69
70impl TimeUnit {
71 fn letter(self) -> char {
73 match self {
74 Self::Second => 's',
75 Self::Millisecond => 'm',
76 Self::Microsecond => 'u',
77 Self::Nanosecond => 'n',
78 }
79 }
80}
81
82impl DataType {
83 pub fn of(ty: &LogicalType) -> Result<Self> {
93 Ok(match ty {
94 LogicalType::Null => Self::Null,
95 LogicalType::Boolean => Self::Boolean,
96 LogicalType::TinyInt => Self::Int8,
97 LogicalType::SmallInt => Self::Int16,
98 LogicalType::Integer => Self::Int32,
99 LogicalType::BigInt => Self::Int64,
100 LogicalType::HugeInt => Self::Decimal128 { precision: 38, scale: 0 },
101 LogicalType::UTinyInt => Self::UInt8,
102 LogicalType::USmallInt => Self::UInt16,
103 LogicalType::UInteger => Self::UInt32,
104 LogicalType::UBigInt => Self::UInt64,
105 LogicalType::Float => Self::Float32,
106 LogicalType::Double => Self::Float64,
107 LogicalType::Decimal { width, scale } => {
108 Self::Decimal128 { precision: *width, scale: *scale }
109 }
110 LogicalType::Varchar => Self::Utf8,
111 LogicalType::Blob => Self::Binary,
112 LogicalType::Date => Self::Date32,
113 LogicalType::Time => Self::Time64,
114 LogicalType::Timestamp => Self::Timestamp(TimeUnit::Microsecond, None),
115 LogicalType::TimestampS => Self::Timestamp(TimeUnit::Second, None),
116 LogicalType::TimestampMs => Self::Timestamp(TimeUnit::Millisecond, None),
117 LogicalType::TimestampNs => Self::Timestamp(TimeUnit::Nanosecond, None),
118 LogicalType::TimestampTz => {
119 Self::Timestamp(TimeUnit::Microsecond, Some("UTC".to_string()))
120 }
121 LogicalType::Interval => Self::Interval,
122 other => {
123 return Err(Error::not_implemented(format!("exporting {other} to Arrow")));
124 }
125 })
126 }
127
128 #[must_use]
134 pub fn format(&self) -> String {
135 match self {
136 Self::Null => "n".to_string(),
137 Self::Boolean => "b".to_string(),
138 Self::Int8 => "c".to_string(),
139 Self::Int16 => "s".to_string(),
140 Self::Int32 => "i".to_string(),
141 Self::Int64 => "l".to_string(),
142 Self::UInt8 => "C".to_string(),
143 Self::UInt16 => "S".to_string(),
144 Self::UInt32 => "I".to_string(),
145 Self::UInt64 => "L".to_string(),
146 Self::Float32 => "f".to_string(),
147 Self::Float64 => "g".to_string(),
148 Self::Utf8 => "u".to_string(),
149 Self::Binary => "z".to_string(),
150 Self::Date32 => "tdD".to_string(),
151 Self::Time64 => "ttu".to_string(),
152 Self::Timestamp(unit, zone) => {
153 format!("ts{}:{}", unit.letter(), zone.clone().unwrap_or_default())
154 }
155 Self::Interval => "tin".to_string(),
156 Self::Decimal128 { precision, scale } => format!("d:{precision},{scale}"),
157 }
158 }
159
160 #[must_use]
166 pub fn buffer_count(&self) -> usize {
167 match self {
168 Self::Null => 0,
169 Self::Utf8 | Self::Binary => 3,
170 _ => 2,
171 }
172 }
173
174 #[must_use]
176 pub fn width(&self) -> Option<usize> {
177 Some(match self {
178 Self::Null | Self::Utf8 | Self::Binary => return None,
179 Self::Boolean => return None,
182 Self::Int8 | Self::UInt8 => 1,
183 Self::Int16 | Self::UInt16 => 2,
184 Self::Int32 | Self::UInt32 | Self::Float32 | Self::Date32 => 4,
185 Self::Int64 | Self::UInt64 | Self::Float64 | Self::Time64 | Self::Timestamp(_, _) => 8,
186 Self::Interval | Self::Decimal128 { .. } => 16,
187 })
188 }
189}
190
191#[derive(Debug, Clone, PartialEq, Eq)]
193pub struct Field {
194 pub name: String,
196 pub data_type: DataType,
198 pub nullable: bool,
201}
202
203impl Field {
204 #[must_use]
206 pub fn new(name: impl Into<String>, data_type: DataType) -> Self {
207 Self { name: name.into(), data_type, nullable: true }
208 }
209}
210
211#[derive(Debug, Clone, Default, PartialEq, Eq)]
213pub struct Schema {
214 pub fields: Vec<Field>,
216}
217
218impl Schema {
219 #[must_use]
221 pub fn new(fields: Vec<Field>) -> Self {
222 Self { fields }
223 }
224
225 #[must_use]
227 pub fn len(&self) -> usize {
228 self.fields.len()
229 }
230
231 #[must_use]
233 pub fn is_empty(&self) -> bool {
234 self.fields.is_empty()
235 }
236}