use crate::{DataType, SqlUp};
use log::warn;
use serde_value::Value;
#[derive(Clone, Debug, Default)]
pub struct Column {
pub name: String,
pub data_type: Option<DataType>,
pub options: Option<ColumnOptions>,
}
#[derive(Clone, Debug, Default)]
pub enum ColumnDefault {
#[default]
Value,
Raw,
}
impl Column {
pub fn new(name: &str) -> Self {
Column {
name: name.to_string(),
data_type: Some(DataType::default()),
options: None,
}
}
pub fn name(&mut self, name: &str) -> &mut Self {
self.name = name.to_string();
self
}
pub fn default(&mut self, default: Value) -> &mut Self {
self.options = Some(ColumnOptions {
default: Some(default),
default_format: Some(ColumnDefault::Value),
..self.options.clone().unwrap_or_default()
});
self
}
pub fn default_raw(&mut self, default: String) -> &mut Self {
self.options(ColumnOptions {
default: Some(Value::String(default)),
default_format: Some(ColumnDefault::Raw),
..self.options.clone().unwrap_or_default()
})
}
pub fn not_null(&mut self) -> &mut Self {
let options = self.options.clone().unwrap_or_default();
self.options = Some(ColumnOptions {
not_null: true,
..options
});
self
}
pub fn options(&mut self, options: ColumnOptions) -> &mut Self {
self.options = Some(options);
self
}
}
impl SqlUp for Column {
fn sqlite_up(&self) -> Option<String> {
let data_type = if self.data_type.is_none() {
DataType::default()
} else {
self.data_type.clone().unwrap()
};
let datatype_sql = data_type.clone().sqlite_up();
datatype_sql.as_ref()?;
let mut sql = format!("{} {}", self.name, data_type.sqlite_up().unwrap());
if let Some(options) = &self.options {
let options = options.sqlite_up();
if let Some(options) = options {
sql.push_str(&options);
} else {
warn!("Failed to generate column options");
return None;
}
}
Some(sql)
}
}
#[derive(Clone, Debug, Default)]
pub struct ColumnOptions {
pub not_null: bool,
pub unique: bool,
pub default: Option<Value>,
pub default_format: Option<ColumnDefault>,
}
fn value_to_default(value: &Value) -> String {
match value {
Value::Bool(b) => if *b { "TRUE" } else { "FALSE" }.to_string(),
Value::U8(u) => u.to_string(),
Value::U16(u) => u.to_string(),
Value::U32(u) => u.to_string(),
Value::U64(u) => u.to_string(),
Value::I8(u) => u.to_string(),
Value::I16(u) => u.to_string(),
Value::I32(u) => u.to_string(),
Value::I64(u) => u.to_string(),
Value::F32(u) => u.to_string(),
Value::F64(u) => u.to_string(),
Value::Char(c) => {
let mut s = String::new();
s.push('\'');
s.push(*c);
s.push('\'');
s
}
Value::String(str) => {
let mut s = String::new();
s.push('\'');
s.push_str(str);
s.push('\'');
s
}
Value::Unit => "".to_string(),
Value::Option(o) => {
if let Some(o) = o {
value_to_default(o)
} else {
"".to_string()
}
}
Value::Newtype(n) => {
let mut s = String::new();
s.push('\'');
s.push_str(&serde_json::to_string(n).unwrap());
s.push('\'');
s
}
Value::Seq(seq) => {
let mut s = String::new();
s.push('\'');
s.push_str(&serde_json::to_string(seq).unwrap());
s.push('\'');
s
}
Value::Map(m) => {
let mut s = String::new();
s.push('\'');
s.push_str(&serde_json::to_string(m).unwrap());
s.push('\'');
s
}
Value::Bytes(b) => {
let mut s = String::new();
s.push('\'');
s.push_str(&String::from_utf8_lossy(b));
s.push('\'');
s
}
}
}
impl SqlUp for ColumnOptions {
fn sqlite_up(&self) -> Option<String> {
let mut sql = String::new();
if self.not_null {
sql.push_str(" NOT NULL");
}
if self.unique {
sql.push_str(" UNIQUE");
}
if let Some(default) = &self.default {
let default_format = self.default_format.clone().unwrap_or(ColumnDefault::Value);
let default = match default_format {
ColumnDefault::Value => value_to_default(default),
ColumnDefault::Raw => {
let default = default.clone();
if let Value::String(s) = default {
s
} else {
serde_json::to_string(&default).unwrap()
}
}
};
sql.push_str(&format!(" DEFAULT {}", default));
}
Some(sql)
}
}