1use crate::model::reference::Reference;
2use apache_avro::schema::{Name, RecordField, RecordFieldOrder};
3use apache_avro::Schema;
4use serde::Serialize;
5use std::collections::BTreeMap;
6
7#[derive(Debug, Clone, Serialize)]
9pub struct Column<'a> {
10 name: &'a str,
12 type_name: &'a str,
14 not_null: bool,
16 #[serde(skip_serializing_if = "Option::is_none")]
18 default_value: Option<&'a str>,
19 #[serde(skip_serializing_if = "Option::is_none")]
21 index_type: Option<&'a str>,
22 #[serde(skip_serializing_if = "Option::is_none")]
24 reference: Option<Reference<'a>>,
25}
26
27impl<'a> Column<'a> {
28 pub fn new(name: &'a str, type_name: &'a str, not_null: bool) -> Self {
30 Self {
31 name,
32 type_name,
33 not_null,
34 default_value: None,
35 index_type: None,
36 reference: None,
37 }
38 }
39
40 #[inline]
42 pub fn set_default_value(&mut self, default_value: &'a str) {
43 self.default_value = (!default_value.is_empty()).then_some(default_value);
44 }
45
46 #[inline]
48 pub fn set_index_type(&mut self, index_type: &'a str) {
49 self.index_type = (!index_type.is_empty()).then_some(index_type);
50 }
51
52 #[inline]
54 pub fn set_reference(&mut self, reference: Reference<'a>) {
55 self.reference = Some(reference);
56 }
57
58 #[inline]
60 pub fn name(&self) -> &'a str {
61 self.name
62 }
63
64 #[inline]
66 pub fn type_name(&self) -> &'a str {
67 self.type_name
68 }
69
70 #[inline]
72 pub fn is_not_null(&self) -> bool {
73 self.not_null
74 }
75
76 #[inline]
78 pub fn default_value(&self) -> Option<&'a str> {
79 self.default_value()
80 }
81
82 #[inline]
84 pub fn index_type(&self) -> Option<&'a str> {
85 self.index_type
86 }
87
88 #[inline]
90 pub fn reference(&self) -> Option<&'a str> {
91 self.reference()
92 }
93
94 #[inline]
96 pub fn auto_increment(&self) -> bool {
97 self.default_value
98 .is_some_and(|value| value == "auto_increment")
99 }
100
101 pub fn schema(&self) -> Schema {
103 let type_name = self.type_name;
104 match type_name {
105 "bool" => Schema::Boolean,
106 "i32" | "u32" | "i16" | "u16" | "i8" | "u8" => Schema::Int,
107 "i64" | "u64" | "isize" | "usize" => Schema::Long,
108 "f32" => Schema::Float,
109 "f64" => Schema::Double,
110 "String" | "Option<String>" => Schema::String,
111 "Uuid" | "Option<Uuid>" => Schema::Uuid,
112 "DateTime" => Schema::TimeMicros,
113 "Vec<u8>" => Schema::Bytes,
114 "Vec<Uuid>" => Schema::Array(Box::new(Schema::Uuid)),
115 "Vec<String>" => Schema::Array(Box::new(Schema::String)),
116 "Map" => Schema::Map(Box::new(Schema::Ref {
117 name: Name {
118 name: "json".to_owned(), namespace: None,
120 },
121 })),
122 _ => Schema::Ref {
123 name: Name {
124 name: type_name.to_owned(),
125 namespace: None,
126 },
127 },
128 }
129 }
130
131 pub fn record_filed(&self) -> RecordField {
133 let schema = self.schema();
134 let default_value = self.default_value().and_then(|s| match schema {
136 Schema::Int => s.parse::<i32>().ok().map(|i| i.into()),
137 Schema::Long => s.parse::<i64>().ok().map(|i| i.into()),
138 _ => Some(s.into()),
139 });
140
141 RecordField {
142 name: self.name.to_owned(),
143 doc: None,
144 aliases: None,
145 default: default_value,
146 schema,
147 order: RecordFieldOrder::Ascending,
148 position: 0,
149 custom_attributes: BTreeMap::new(),
150 }
151 }
152}