vespertide_core/schema/table/
mod.rs1mod normalize;
2#[cfg(all(test, feature = "arbitrary"))]
3mod normalize_proptest;
4#[cfg(test)]
5mod tests;
6mod validation;
7
8use serde::{Deserialize, Serialize};
9
10use crate::schema::{column::ColumnDef, constraint::TableConstraint, names::TableName};
11
12pub use validation::TableValidationError;
13
14#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
15#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
16#[serde(rename_all = "snake_case")]
17pub struct TableDef {
18 pub name: TableName,
19 #[serde(skip_serializing_if = "Option::is_none")]
20 pub description: Option<String>,
21 pub columns: Vec<ColumnDef>,
22 #[serde(default, skip_serializing_if = "Vec::is_empty")]
23 pub constraints: Vec<TableConstraint>,
24}
25
26impl TableDef {
27 pub fn normalize(&self) -> Result<Self, TableValidationError> {
35 normalize::normalize(self)
36 }
37
38 pub fn validate_unique_column_names(&self) -> Result<(), TableValidationError> {
44 let mut seen: std::collections::BTreeSet<&str> = std::collections::BTreeSet::new();
45 for col in &self.columns {
46 if !seen.insert(col.name.as_str()) {
47 return Err(TableValidationError::DuplicateColumnName {
48 table: self.name.clone(),
49 column: col.name.clone(),
50 });
51 }
52 }
53 Ok(())
54 }
55}