#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum OnDelete {
Cascade,
SetNull,
Restrict,
NoAction,
}
impl OnDelete {
pub(crate) fn as_sql(self) -> &'static str {
match self {
OnDelete::Cascade => "CASCADE",
OnDelete::SetNull => "SET NULL",
OnDelete::Restrict => "RESTRICT",
OnDelete::NoAction => "NO ACTION",
}
}
}
#[derive(Clone, Debug)]
pub enum ColType {
Integer,
Real,
Text,
}
impl ColType {
pub(crate) fn as_sql(&self) -> &'static str {
match self {
ColType::Integer => "INTEGER",
ColType::Real => "REAL",
ColType::Text => "TEXT",
}
}
}
#[derive(Clone, Debug)]
pub struct Column {
pub name: &'static str,
pub col_type: ColType,
pub not_null: bool,
pub default: Option<&'static str>,
pub references: Option<(&'static str, &'static str)>,
pub on_delete: Option<OnDelete>,
}
impl Column {
pub const fn new(name: &'static str, col_type: ColType) -> Self {
Self {
name,
col_type,
not_null: false,
default: None,
references: None,
on_delete: None,
}
}
pub const fn not_null(mut self) -> Self {
self.not_null = true;
self
}
pub const fn default(mut self, expr: &'static str) -> Self {
self.default = Some(expr);
self
}
pub const fn references(mut self, table: &'static str, col: &'static str) -> Self {
self.references = Some((table, col));
self
}
pub const fn on_delete(mut self, action: OnDelete) -> Self {
self.on_delete = Some(action);
self
}
pub(crate) fn to_sql_fragment(&self) -> String {
let type_sql: &str = self.col_type.as_sql();
let not_null: &str = if self.not_null { " NOT NULL" } else { "" };
let default: String = self
.default
.map(|d| format!(" DEFAULT {d}"))
.unwrap_or_default();
let references: String = match self.references {
None => String::new(),
Some((tbl, col)) => {
let on_del: String = self
.on_delete
.map(|a| format!(" ON DELETE {}", a.as_sql()))
.unwrap_or_default();
format!(
r#" REFERENCES "{}"("{}"){}"#,
tbl.replace('"', r#""""#),
col.replace('"', r#""""#),
on_del
)
}
};
format!(
r#""{}" {}{}{}{}"#,
self.name.replace('"', r#""""#),
type_sql,
not_null,
default,
references,
)
}
}
#[derive(Clone, Debug)]
pub struct IndexDef {
pub columns: &'static [&'static str],
pub unique: bool,
}
impl IndexDef {
pub const fn new(columns: &'static [&'static str]) -> Self {
Self {
columns,
unique: false,
}
}
pub const fn unique(mut self) -> Self {
self.unique = true;
self
}
}