edm_orm/model/
column.rs

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/// 数据库表中列的元数据字段模型
8#[derive(Debug, Clone, Serialize)]
9pub struct Column<'a> {
10    /// 列名
11    name: &'a str,
12    /// 列类型名称
13    type_name: &'a str,
14    /// 标记列是否为null的标志
15    not_null: bool,
16    /// 默认值
17    #[serde(skip_serializing_if = "Option::is_none")]
18    default_value: Option<&'a str>,
19    /// 索引类型
20    #[serde(skip_serializing_if = "Option::is_none")]
21    index_type: Option<&'a str>,
22    /// 外键列引用
23    #[serde(skip_serializing_if = "Option::is_none")]
24    reference: Option<Reference<'a>>,
25}
26
27impl<'a> Column<'a> {
28    /// 创建实例
29    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    /// 设置默认值.
41    #[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    /// 设置索引类型.
47    #[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    /// 设置外键引用.
53    #[inline]
54    pub fn set_reference(&mut self, reference: Reference<'a>) {
55        self.reference = Some(reference);
56    }
57
58    /// 返回列字段名称.
59    #[inline]
60    pub fn name(&self) -> &'a str {
61        self.name
62    }
63
64    /// 返回列字段类型.
65    #[inline]
66    pub fn type_name(&self) -> &'a str {
67        self.type_name
68    }
69
70    /// 返回字段值是否允许为null.
71    #[inline]
72    pub fn is_not_null(&self) -> bool {
73        self.not_null
74    }
75
76    /// 返回列字段的默认值.
77    #[inline]
78    pub fn default_value(&self) -> Option<&'a str> {
79        self.default_value()
80    }
81
82    /// 返回字段的索引类型.
83    #[inline]
84    pub fn index_type(&self) -> Option<&'a str> {
85        self.index_type
86    }
87
88    /// 返回列字段的引用 `reference`.
89    #[inline]
90    pub fn reference(&self) -> Option<&'a str> {
91        self.reference()
92    }
93
94    /// 如果列字段的默认值为 `auto_increment`,那么就返回 `true`
95    #[inline]
96    pub fn auto_increment(&self) -> bool {
97        self.default_value
98            .is_some_and(|value| value == "auto_increment")
99    }
100
101    /// 根据列的字段类型,返回 [Apache Avro Scheme](apache_avro::schema::Schema).
102    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(), // to_owned()转移所有权
119                    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    /// 根据 Apache Avro Schema 返回 Avro Schema 字段类型 RecordField
132    pub fn record_filed(&self) -> RecordField {
133        let schema = self.schema();
134        // 根据Schema重新定义字段数据的类型
135        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}