use crate::model::reference::Reference;
use apache_avro::schema::{Name, RecordField, RecordFieldOrder};
use apache_avro::Schema;
use serde::Serialize;
use std::collections::BTreeMap;
#[derive(Debug, Clone, Serialize)]
pub struct Column<'a> {
name: &'a str,
type_name: &'a str,
not_null: bool,
#[serde(skip_serializing_if = "Option::is_none")]
default_value: Option<&'a str>,
#[serde(skip_serializing_if = "Option::is_none")]
index_type: Option<&'a str>,
#[serde(skip_serializing_if = "Option::is_none")]
reference: Option<Reference<'a>>,
}
impl<'a> Column<'a> {
pub fn new(name: &'a str, type_name: &'a str, not_null: bool) -> Self {
Self {
name,
type_name,
not_null,
default_value: None,
index_type: None,
reference: None,
}
}
#[inline]
pub fn set_default_value(&mut self, default_value: &'a str) {
self.default_value = (!default_value.is_empty()).then_some(default_value);
}
#[inline]
pub fn set_index_type(&mut self, index_type: &'a str) {
self.index_type = (!index_type.is_empty()).then_some(index_type);
}
#[inline]
pub fn set_reference(&mut self, reference: Reference<'a>) {
self.reference = Some(reference);
}
#[inline]
pub fn name(&self) -> &'a str {
self.name
}
#[inline]
pub fn type_name(&self) -> &'a str {
self.type_name
}
#[inline]
pub fn is_not_null(&self) -> bool {
self.not_null
}
#[inline]
pub fn default_value(&self) -> Option<&'a str> {
self.default_value()
}
#[inline]
pub fn index_type(&self) -> Option<&'a str> {
self.index_type
}
#[inline]
pub fn reference(&self) -> Option<&'a str> {
self.reference()
}
#[inline]
pub fn auto_increment(&self) -> bool {
self.default_value
.is_some_and(|value| value == "auto_increment")
}
pub fn schema(&self) -> Schema {
let type_name = self.type_name;
match type_name {
"bool" => Schema::Boolean,
"i32" | "u32" | "i16" | "u16" | "i8" | "u8" => Schema::Int,
"i64" | "u64" | "isize" | "usize" => Schema::Long,
"f32" => Schema::Float,
"f64" => Schema::Double,
"String" | "Option<String>" => Schema::String,
"Uuid" | "Option<Uuid>" => Schema::Uuid,
"DateTime" => Schema::TimeMicros,
"Vec<u8>" => Schema::Bytes,
"Vec<Uuid>" => Schema::Array(Box::new(Schema::Uuid)),
"Vec<String>" => Schema::Array(Box::new(Schema::String)),
"Map" => Schema::Map(Box::new(Schema::Ref {
name: Name {
name: "json".to_owned(), namespace: None,
},
})),
_ => Schema::Ref {
name: Name {
name: type_name.to_owned(),
namespace: None,
},
},
}
}
pub fn record_filed(&self) -> RecordField {
let schema = self.schema();
let default_value = self.default_value().and_then(|s| match schema {
Schema::Int => s.parse::<i32>().ok().map(|i| i.into()),
Schema::Long => s.parse::<i64>().ok().map(|i| i.into()),
_ => Some(s.into()),
});
RecordField {
name: self.name.to_owned(),
doc: None,
aliases: None,
default: default_value,
schema,
order: RecordFieldOrder::Ascending,
position: 0,
custom_attributes: BTreeMap::new(),
}
}
}