exarrow_rs/types/
schema.rs1use crate::error::ConversionError;
4use crate::types::{ExasolType, TypeMapper};
5use arrow::datatypes::{Field, Schema};
6
7#[derive(Debug, Clone)]
9pub struct ColumnMetadata {
10 pub name: String,
12 pub data_type: ExasolType,
14 pub nullable: bool,
16}
17
18pub struct SchemaBuilder {
20 columns: Vec<ColumnMetadata>,
21}
22
23impl SchemaBuilder {
24 pub fn new() -> Self {
26 Self {
27 columns: Vec::new(),
28 }
29 }
30
31 pub fn add_column(mut self, column: ColumnMetadata) -> Self {
33 self.columns.push(column);
34 self
35 }
36
37 pub fn add_columns(mut self, columns: Vec<ColumnMetadata>) -> Self {
39 self.columns.extend(columns);
40 self
41 }
42
43 pub fn build(self) -> Result<Schema, ConversionError> {
51 let fields: Result<Vec<Field>, ConversionError> = self
52 .columns
53 .iter()
54 .map(|col| {
55 let arrow_type = TypeMapper::exasol_to_arrow(&col.data_type, col.nullable)?;
56 let metadata = TypeMapper::create_field_metadata(&col.data_type);
57
58 Ok(Field::new(&col.name, arrow_type, col.nullable).with_metadata(metadata))
59 })
60 .collect();
61
62 Ok(Schema::new(fields?))
63 }
64
65 pub fn build_with_metadata(
67 self,
68 metadata: std::collections::HashMap<String, String>,
69 ) -> Result<Schema, ConversionError> {
70 let schema = self.build()?;
71 Ok(schema.with_metadata(metadata))
72 }
73}
74
75impl Default for SchemaBuilder {
76 fn default() -> Self {
77 Self::new()
78 }
79}
80
81#[cfg(test)]
82mod tests {
83 use super::*;
84
85 #[test]
86 fn test_schema_builder() {
87 let schema = SchemaBuilder::new()
88 .add_column(ColumnMetadata {
89 name: "id".to_string(),
90 data_type: ExasolType::Decimal {
91 precision: 18,
92 scale: 0,
93 },
94 nullable: false,
95 })
96 .add_column(ColumnMetadata {
97 name: "name".to_string(),
98 data_type: ExasolType::Varchar { size: 100 },
99 nullable: true,
100 })
101 .add_column(ColumnMetadata {
102 name: "price".to_string(),
103 data_type: ExasolType::Decimal {
104 precision: 10,
105 scale: 2,
106 },
107 nullable: true,
108 })
109 .build()
110 .unwrap();
111
112 assert_eq!(schema.fields().len(), 3);
113 assert_eq!(schema.field(0).name(), "id");
114 assert_eq!(schema.field(1).name(), "name");
115 assert_eq!(schema.field(2).name(), "price");
116
117 assert!(!schema.field(0).is_nullable());
118 assert!(schema.field(1).is_nullable());
119 }
120
121 #[test]
122 fn test_schema_with_metadata() {
123 let mut metadata = std::collections::HashMap::new();
124 metadata.insert("source".to_string(), "exasol".to_string());
125
126 let schema = SchemaBuilder::new()
127 .add_column(ColumnMetadata {
128 name: "id".to_string(),
129 data_type: ExasolType::Decimal {
130 precision: 18,
131 scale: 0,
132 },
133 nullable: false,
134 })
135 .build_with_metadata(metadata.clone())
136 .unwrap();
137
138 assert_eq!(schema.metadata().get("source"), Some(&"exasol".to_string()));
139 }
140}