use crate::{
Column, Dialect, ForeignKey, Index, PrimaryKey, SqlUp, Table, TableDefinition, TableName,
TableOptions,
};
use log::warn;
#[derive(Clone, Debug)]
pub enum Definition {
Table(Table),
Column(TableName, Column),
Index(TableName, Index),
ForeignKey(TableName, ForeignKey),
Statement(String),
}
impl Definition {
pub fn table(name: &str, definition: Vec<TableDefinition>) -> Self {
Definition::Table(Table {
name: TableName::new(name),
options: None,
definition,
})
}
pub fn table_no_timestamps(name: &str, definition: Vec<TableDefinition>) -> Self {
Definition::Table(Table {
name: TableName::new(name),
options: Some(TableOptions {
timestamps: None,
primary_key: PrimaryKey::default(),
if_not_exists: true,
}),
definition,
})
}
pub fn column(name: &str, column: Column) -> Self {
Definition::Column(TableName::new(name), column)
}
pub fn index(name: &str, index: Index) -> Self {
Definition::Index(TableName::new(name), index)
}
pub fn foreign_key(name: &str, foreign_key: ForeignKey) -> Self {
Definition::ForeignKey(TableName::new(name), foreign_key)
}
pub fn statement(sql: &str) -> Self {
Definition::Statement(sql.to_string())
}
}
impl SqlUp for core::slice::Iter<'_, Definition> {
fn sqlite_up(&self) -> Option<String> {
self.sql_up(Dialect::Sqlite)
}
fn sql_up(&self, dialect: Dialect) -> Option<String> {
let mut sql = String::new();
for (i, def) in self.clone().enumerate() {
if i > 0 {
sql.push_str("; ");
}
let def = def.sql_up(dialect);
if def.is_none() {
warn!("Failed to generate definition");
return None;
}
let def = def.unwrap();
sql.push_str(&def);
}
Some(sql)
}
}
impl SqlUp for Definition {
fn sqlite_up(&self) -> Option<String> {
match self {
Definition::Table(table) => if table.options.is_none() {
let mut t = table.clone();
t.options = Some(TableOptions::default());
t
} else {
table.clone()
}
.sqlite_up(),
Definition::Column(table_name, column) => {
let sql = column.sqlite_up();
sql.map(|sql| format!("ALTER TABLE {} ADD COLUMN {}", table_name, sql))
}
Definition::Index(table_name, index) => {
let mut index = index.clone();
index.table_name = Some(table_name.clone());
index.sqlite_up()
}
Definition::ForeignKey(table_name, foreign_key) => Some(format!(
"ALTER TABLE {} ADD FOREIGN KEY ({}) REFERENCES {} ({})",
table_name,
foreign_key.columns.join(", "),
foreign_key.foreign_table,
foreign_key.foreign_columns.join(", ")
)),
Definition::Statement(sql) => Some(sql.clone()),
}
}
}