1use std::sync::Arc;
6
7use arrow_schema::{Field, Schema, SchemaRef};
8
9#[derive(Debug, Clone, Default)]
22pub struct SchemaMapper;
23
24impl SchemaMapper {
25 #[must_use]
27 pub const fn new() -> Self {
28 Self
29 }
30
31 #[must_use]
37 pub fn from_result_set(result_set: &hdbconnect::ResultSet) -> Schema {
38 let metadata = result_set.metadata();
40 let fields: Vec<Field> = metadata
41 .iter()
42 .map(super::super::types::arrow::FieldMetadataExt::to_arrow_field)
43 .collect();
44
45 Schema::new(fields)
46 }
47
48 #[must_use]
54 pub fn from_field_metadata(metadata: &[hdbconnect::FieldMetadata]) -> Schema {
55 let fields: Vec<Field> = metadata
56 .iter()
57 .map(super::super::types::arrow::FieldMetadataExt::to_arrow_field)
58 .collect();
59
60 Schema::new(fields)
61 }
62
63 #[must_use]
67 pub fn schema_ref_from_result_set(result_set: &hdbconnect::ResultSet) -> SchemaRef {
68 Arc::new(Self::from_result_set(result_set))
69 }
70
71 #[must_use]
75 pub fn schema_ref_from_field_metadata(metadata: &[hdbconnect::FieldMetadata]) -> SchemaRef {
76 Arc::new(Self::from_field_metadata(metadata))
77 }
78}
79
80pub trait SchemaFromHana {
82 fn from_hana_metadata(metadata: &[hdbconnect::FieldMetadata]) -> Schema;
84}
85
86impl SchemaFromHana for Schema {
87 fn from_hana_metadata(metadata: &[hdbconnect::FieldMetadata]) -> Schema {
88 SchemaMapper::from_field_metadata(metadata)
89 }
90}
91
92#[cfg(test)]
93mod tests {
94 use std::mem::{size_of, size_of_val};
95
96 use super::*;
97
98 #[test]
103 fn test_schema_mapper_new() {
104 let mapper = SchemaMapper::new();
105 assert!(size_of_val(&mapper) == 0);
106 }
107
108 #[test]
109 fn test_schema_mapper_default() {
110 let mapper = SchemaMapper::default();
111 assert!(size_of_val(&mapper) == 0);
112 }
113
114 #[test]
115 fn test_schema_mapper_is_zero_sized() {
116 assert_eq!(size_of::<SchemaMapper>(), 0);
117 }
118
119 #[test]
120 fn test_schema_mapper_clone() {
121 let mapper1 = SchemaMapper::new();
122 #[allow(clippy::clone_on_copy)]
123 let mapper2 = mapper1.clone();
124 assert!(size_of_val(&mapper2) == 0);
125 }
126
127 #[test]
128 fn test_schema_mapper_debug() {
129 let mapper = SchemaMapper::new();
130 let debug_str = format!("{:?}", mapper);
131 assert!(debug_str.contains("SchemaMapper"));
132 }
133
134 #[test]
139 fn test_schema_mapper_const_new() {
140 const _MAPPER: SchemaMapper = SchemaMapper::new();
141 }
142
143 #[test]
148 fn test_arrow_field_int32() {
149 use arrow_schema::DataType;
150 use hdbconnect::TypeId;
151
152 use crate::types::arrow::hana_field_to_arrow;
153
154 let field = hana_field_to_arrow("id", TypeId::INT, false, None, None);
155 assert_eq!(field.name(), "id");
156 assert!(!field.is_nullable());
157 assert_eq!(field.data_type(), &DataType::Int32);
158 }
159
160 #[test]
161 fn test_arrow_field_nullable() {
162 use arrow_schema::DataType;
163 use hdbconnect::TypeId;
164
165 use crate::types::arrow::hana_field_to_arrow;
166
167 let field = hana_field_to_arrow("value", TypeId::INT, true, None, None);
168 assert!(field.is_nullable());
169 assert_eq!(field.data_type(), &DataType::Int32);
170 }
171
172 #[test]
173 fn test_arrow_field_decimal() {
174 use arrow_schema::DataType;
175 use hdbconnect::TypeId;
176
177 use crate::types::arrow::hana_field_to_arrow;
178
179 let field = hana_field_to_arrow("amount", TypeId::DECIMAL, false, Some(18), Some(2));
180 assert_eq!(field.data_type(), &DataType::Decimal128(18, 2));
181 }
182
183 #[test]
184 fn test_arrow_field_varchar() {
185 use arrow_schema::DataType;
186 use hdbconnect::TypeId;
187
188 use crate::types::arrow::hana_field_to_arrow;
189
190 let field = hana_field_to_arrow("name", TypeId::VARCHAR, true, None, None);
191 assert_eq!(field.data_type(), &DataType::Utf8);
192 }
193
194 #[test]
195 fn test_arrow_field_clob() {
196 use arrow_schema::DataType;
197 use hdbconnect::TypeId;
198
199 use crate::types::arrow::hana_field_to_arrow;
200
201 let field = hana_field_to_arrow("content", TypeId::CLOB, true, None, None);
202 assert_eq!(field.data_type(), &DataType::LargeUtf8);
203 }
204
205 #[test]
206 fn test_arrow_field_blob() {
207 use arrow_schema::DataType;
208 use hdbconnect::TypeId;
209
210 use crate::types::arrow::hana_field_to_arrow;
211
212 let field = hana_field_to_arrow("data", TypeId::BLOB, true, None, None);
213 assert_eq!(field.data_type(), &DataType::LargeBinary);
214 }
215
216 #[test]
217 fn test_arrow_field_date() {
218 use arrow_schema::DataType;
219 use hdbconnect::TypeId;
220
221 use crate::types::arrow::hana_field_to_arrow;
222
223 let field = hana_field_to_arrow("created", TypeId::DAYDATE, true, None, None);
224 assert_eq!(field.data_type(), &DataType::Date32);
225 }
226
227 #[test]
228 fn test_arrow_field_timestamp() {
229 use arrow_schema::{DataType, TimeUnit};
230 use hdbconnect::TypeId;
231
232 use crate::types::arrow::hana_field_to_arrow;
233
234 let field = hana_field_to_arrow("updated", TypeId::LONGDATE, true, None, None);
235 assert_eq!(
236 field.data_type(),
237 &DataType::Timestamp(TimeUnit::Nanosecond, None)
238 );
239 }
240
241 #[test]
242 fn test_arrow_field_boolean() {
243 use arrow_schema::DataType;
244 use hdbconnect::TypeId;
245
246 use crate::types::arrow::hana_field_to_arrow;
247
248 let field = hana_field_to_arrow("active", TypeId::BOOLEAN, false, None, None);
249 assert_eq!(field.data_type(), &DataType::Boolean);
250 }
251
252 #[test]
253 fn test_arrow_field_tinyint() {
254 use arrow_schema::DataType;
255 use hdbconnect::TypeId;
256
257 use crate::types::arrow::hana_field_to_arrow;
258
259 let field = hana_field_to_arrow("tiny", TypeId::TINYINT, false, None, None);
260 assert_eq!(field.data_type(), &DataType::UInt8);
261 }
262
263 #[test]
264 fn test_arrow_field_smallint() {
265 use arrow_schema::DataType;
266 use hdbconnect::TypeId;
267
268 use crate::types::arrow::hana_field_to_arrow;
269
270 let field = hana_field_to_arrow("small", TypeId::SMALLINT, false, None, None);
271 assert_eq!(field.data_type(), &DataType::Int16);
272 }
273
274 #[test]
275 fn test_arrow_field_bigint() {
276 use arrow_schema::DataType;
277 use hdbconnect::TypeId;
278
279 use crate::types::arrow::hana_field_to_arrow;
280
281 let field = hana_field_to_arrow("big", TypeId::BIGINT, false, None, None);
282 assert_eq!(field.data_type(), &DataType::Int64);
283 }
284
285 #[test]
286 fn test_arrow_field_real() {
287 use arrow_schema::DataType;
288 use hdbconnect::TypeId;
289
290 use crate::types::arrow::hana_field_to_arrow;
291
292 let field = hana_field_to_arrow("real_val", TypeId::REAL, false, None, None);
293 assert_eq!(field.data_type(), &DataType::Float32);
294 }
295
296 #[test]
297 fn test_arrow_field_double() {
298 use arrow_schema::DataType;
299 use hdbconnect::TypeId;
300
301 use crate::types::arrow::hana_field_to_arrow;
302
303 let field = hana_field_to_arrow("double_val", TypeId::DOUBLE, false, None, None);
304 assert_eq!(field.data_type(), &DataType::Float64);
305 }
306
307 #[test]
308 fn test_arrow_field_binary() {
309 use arrow_schema::DataType;
310 use hdbconnect::TypeId;
311
312 use crate::types::arrow::hana_field_to_arrow;
313
314 let field = hana_field_to_arrow("bin", TypeId::BINARY, true, None, None);
315 assert_eq!(field.data_type(), &DataType::Binary);
316 }
317
318 #[test]
319 fn test_arrow_field_time() {
320 use arrow_schema::{DataType, TimeUnit};
321 use hdbconnect::TypeId;
322
323 use crate::types::arrow::hana_field_to_arrow;
324
325 let field = hana_field_to_arrow("time", TypeId::SECONDTIME, true, None, None);
326 assert_eq!(field.data_type(), &DataType::Time64(TimeUnit::Nanosecond));
327 }
328
329 #[test]
330 fn test_arrow_field_geometry() {
331 use arrow_schema::DataType;
332 use hdbconnect::TypeId;
333
334 use crate::types::arrow::hana_field_to_arrow;
335
336 let field = hana_field_to_arrow("geom", TypeId::GEOMETRY, true, None, None);
337 assert_eq!(field.data_type(), &DataType::Binary);
338 }
339
340 #[test]
341 fn test_arrow_field_point() {
342 use arrow_schema::DataType;
343 use hdbconnect::TypeId;
344
345 use crate::types::arrow::hana_field_to_arrow;
346
347 let field = hana_field_to_arrow("pt", TypeId::POINT, true, None, None);
348 assert_eq!(field.data_type(), &DataType::Binary);
349 }
350
351 #[test]
356 fn test_arrow_field_empty_name() {
357 use hdbconnect::TypeId;
358
359 use crate::types::arrow::hana_field_to_arrow;
360
361 let field = hana_field_to_arrow("", TypeId::INT, false, None, None);
362 assert_eq!(field.name(), "");
363 }
364
365 #[test]
366 fn test_arrow_field_special_chars_in_name() {
367 use hdbconnect::TypeId;
368
369 use crate::types::arrow::hana_field_to_arrow;
370
371 let field = hana_field_to_arrow("col-name_123", TypeId::INT, false, None, None);
372 assert_eq!(field.name(), "col-name_123");
373 }
374
375 #[test]
376 fn test_arrow_field_unicode_name() {
377 use hdbconnect::TypeId;
378
379 use crate::types::arrow::hana_field_to_arrow;
380
381 let field = hana_field_to_arrow("列名", TypeId::VARCHAR, true, None, None);
382 assert_eq!(field.name(), "列名");
383 }
384}