diff --git a/crates/paimon/src/spec/schema.rs b/crates/paimon/src/spec/schema.rs index 60b3923..12d3b9d 100644 --- a/crates/paimon/src/spec/schema.rs +++ b/crates/paimon/src/spec/schema.rs @@ -18,7 +18,7 @@ use crate::spec::types::DataType; use serde::{Deserialize, Serialize}; use serde_with::{serde_as, DisplayFromStr}; -use std::collections::HashMap; +use std::{collections::HashMap, fmt::Display}; /// The table schema for paimon table. /// @@ -51,3 +51,133 @@ pub struct DataField { typ: DataType, description: Option, } + +impl DataField { + pub fn new(id: i32, name: String, typ: DataType) -> Self { + Self { + id, + name, + typ, + description: None, + } + } + + pub fn id(&self) -> i32 { + self.id + } + + pub fn name(&self) -> &str { + &self.name + } + + pub fn data_type(&self) -> &DataType { + &self.typ + } + + pub fn description(&self) -> Option<&String> { + self.description.as_ref() + } + + pub fn with_id(mut self, new_id: i32) -> Self { + self.id = new_id; + self + } + + pub fn with_name(mut self, new_name: String) -> Self { + self.name = new_name; + self + } + + pub fn with_description(mut self, new_description: String) -> Self { + self.description = Some(new_description); + self + } +} + +impl Display for DataField { + fn fmt(&self, _f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + todo!() + } +} + +pub fn escape_identifier(identifier: &str) -> String { + identifier.replace('"', "\"\"") +} + +pub fn escape_single_quotes(text: &str) -> String { + text.replace('\'', "''") +} + +#[cfg(test)] +mod tests { + use crate::spec::IntType; + + use super::*; + + #[test] + fn test_create_data_field() { + let id = 1; + let name = "field1".to_string(); + let typ = DataType::Int(IntType::new()); + let description = "test description".to_string(); + + let data_field = + DataField::new(id, name.clone(), typ.clone()).with_description(description.clone()); + + assert_eq!(data_field.id(), id); + assert_eq!(data_field.name(), name); + assert_eq!(data_field.data_type(), &typ); + assert_eq!(data_field.description(), Some(description).as_ref()); + } + + #[test] + fn test_new_id() { + let d_type = DataType::Int(IntType::new()); + let new_data_field = DataField::new(1, "field1".to_string(), d_type.clone()).with_id(2); + + assert_eq!(new_data_field.id(), 2); + assert_eq!(new_data_field.name(), "field1"); + assert_eq!(new_data_field.data_type(), &d_type); + assert_eq!(new_data_field.description(), None); + } + + #[test] + fn test_new_name() { + let d_type = DataType::Int(IntType::new()); + let new_data_field = + DataField::new(1, "field1".to_string(), d_type.clone()).with_name("field2".to_string()); + + assert_eq!(new_data_field.id(), 1); + assert_eq!(new_data_field.name(), "field2"); + assert_eq!(new_data_field.data_type(), &d_type); + assert_eq!(new_data_field.description(), None); + } + + #[test] + fn test_new_description() { + let d_type = DataType::Int(IntType::new()); + let new_data_field = DataField::new(1, "field1".to_string(), d_type.clone()) + .with_description("new description".to_string()); + + assert_eq!(new_data_field.id(), 1); + assert_eq!(new_data_field.name(), "field1"); + assert_eq!(new_data_field.data_type(), &d_type); + assert_eq!( + new_data_field.description(), + Some(&"new description".to_string()) + ); + } + + #[test] + fn test_escape_identifier() { + let escaped_identifier = escape_identifier("\"identifier\""); + assert_eq!(escaped_identifier, "\"\"identifier\"\""); + } + + #[test] + fn test_escape_single_quotes() { + let escaped_text = escape_single_quotes("text with 'single' quotes"); + assert_eq!(escaped_text, "text with ''single'' quotes"); + } +} +