use serde::{Deserialize, Serialize};
use std::collections::HashMap;
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct Column {
pub name: String,
#[serde(rename = "type")]
pub sql_type: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub type_schema: Option<String>,
pub primary_key: bool,
pub not_null: bool,
#[serde(skip_serializing_if = "Option::is_none")]
pub default: Option<serde_json::Value>,
#[serde(skip_serializing_if = "Option::is_none")]
pub is_unique: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub unique_name: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub nulls_not_distinct: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub generated: Option<Generated>,
#[serde(skip_serializing_if = "Option::is_none")]
pub identity: Option<Identity>,
}
impl Column {
pub fn new(name: impl Into<String>, sql_type: impl Into<String>) -> Self {
Self {
name: name.into(),
sql_type: sql_type.into(),
type_schema: None,
primary_key: false,
not_null: false,
default: None,
is_unique: None,
unique_name: None,
nulls_not_distinct: None,
generated: None,
identity: None,
}
}
pub fn primary_key(mut self) -> Self {
self.primary_key = true;
self
}
pub fn not_null(mut self) -> Self {
self.not_null = true;
self
}
pub fn unique(mut self) -> Self {
self.is_unique = Some(true);
self
}
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
pub struct Generated {
#[serde(rename = "type")]
pub gen_type: String, #[serde(rename = "as")]
pub expression: String,
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct Identity {
#[serde(rename = "type")]
pub identity_type: String,
pub name: String,
pub schema: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub increment: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub min_value: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub max_value: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub start_with: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub cache: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub cycle: Option<bool>,
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct IndexColumn {
pub expression: String,
pub is_expression: bool,
pub asc: bool,
#[serde(skip_serializing_if = "Option::is_none")]
pub nulls: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub opclass: Option<String>,
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct Index {
pub name: String,
pub columns: Vec<IndexColumn>,
pub is_unique: bool,
#[serde(default = "default_method")]
pub method: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub with: Option<HashMap<String, serde_json::Value>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub r#where: Option<String>,
#[serde(default)]
pub concurrently: bool,
}
fn default_method() -> String {
"btree".to_string()
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct ForeignKey {
pub name: String,
pub table_from: String,
pub columns_from: Vec<String>,
pub table_to: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub schema_to: Option<String>,
pub columns_to: Vec<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub on_update: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub on_delete: Option<String>,
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
pub struct CheckConstraint {
pub name: String,
pub value: String,
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
pub struct UniqueConstraint {
pub name: String,
pub columns: Vec<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub nulls_not_distinct: Option<bool>,
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Default)]
pub struct CompositePK {
pub name: String,
pub columns: Vec<String>,
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
pub struct Enum {
pub name: String,
pub schema: String,
pub values: Vec<String>,
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct Sequence {
pub name: String,
pub schema: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub increment: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub min_value: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub max_value: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub start_with: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub cache: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub cycle: Option<bool>,
}
#[derive(Serialize, Deserialize, Clone, Debug, Default)]
#[serde(rename_all = "camelCase")]
pub struct Table {
pub name: String,
#[serde(default)]
pub schema: String,
pub columns: HashMap<String, Column>,
pub indexes: HashMap<String, Index>,
pub foreign_keys: HashMap<String, ForeignKey>,
pub composite_primary_keys: HashMap<String, CompositePK>,
#[serde(default)]
pub unique_constraints: HashMap<String, UniqueConstraint>,
#[serde(default)]
pub check_constraints: HashMap<String, CheckConstraint>,
}
impl Table {
pub fn new(name: impl Into<String>) -> Self {
Self {
name: name.into(),
schema: "public".to_string(),
columns: HashMap::new(),
indexes: HashMap::new(),
foreign_keys: HashMap::new(),
composite_primary_keys: HashMap::new(),
unique_constraints: HashMap::new(),
check_constraints: HashMap::new(),
}
}
pub fn with_schema(mut self, schema: impl Into<String>) -> Self {
self.schema = schema.into();
self
}
pub fn add_column(&mut self, column: Column) {
self.columns.insert(column.name.clone(), column);
}
}
#[derive(Serialize, Deserialize, Clone, Debug, Default)]
#[serde(rename_all = "camelCase")]
pub struct View {
pub name: String,
pub schema: String,
pub columns: HashMap<String, Column>,
#[serde(skip_serializing_if = "Option::is_none")]
pub definition: Option<String>,
pub is_existing: bool,
#[serde(skip_serializing_if = "Option::is_none")]
pub with: Option<HashMap<String, serde_json::Value>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub materialized: Option<bool>,
}