My personal project and infrastructure archive
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
nomicon/development/libs/barrel/src/backend/mysql.rs

162 lines
6.0 KiB

//! MySQL implementation of a generator
//!
//! This module generates strings that are specific to MySQL
//! databases. They should be thoroughly tested via unit testing
use super::SqlGenerator;
use crate::types::{BaseType, Type};
/// A simple macro that will generate a schema prefix if it exists
macro_rules! prefix {
($schema:expr) => {
$schema
.map(|s| format!("`{}`.", s))
.unwrap_or_else(|| String::new())
};
}
/// MySQL generator backend
pub struct MySql;
impl SqlGenerator for MySql {
fn create_table(name: &str, schema: Option<&str>) -> String {
format!("CREATE TABLE {}`{}`", prefix!(schema), name)
}
fn create_table_if_not_exists(name: &str, schema: Option<&str>) -> String {
format!("CREATE TABLE {}`{}` IF NOT EXISTS", prefix!(schema), name)
}
fn drop_table(name: &str, schema: Option<&str>) -> String {
format!("DROP TABLE {}`{}`", prefix!(schema), name)
}
fn drop_table_if_exists(name: &str, schema: Option<&str>) -> String {
format!("DROP TABLE {}`{}` IF EXISTS", prefix!(schema), name)
}
fn rename_table(old: &str, new: &str, schema: Option<&str>) -> String {
let schema = prefix!(schema);
format!("RENAME TABLE {}`{}` TO {}`{}`", schema, old, schema, new)
}
fn alter_table(name: &str, schema: Option<&str>) -> String {
format!("ALTER TABLE {}`{}`", prefix!(schema), name)
}
fn add_column(ex: bool, schema: Option<&str>, name: &str, tt: &Type) -> String {
let bt: BaseType = tt.get_inner();
use self::BaseType::*;
let name = format!("`{}`", name);
#[cfg_attr(rustfmt, rustfmt_skip)] /* This shouldn't be formatted. It's too long */
format!(
"{}{}{}{}{}",
match bt {
Text => format!("{}{} {}", MySql::prefix(ex), name, MySql::print_type(bt, schema)),
Varchar(_) => format!("{}{} {}", MySql::prefix(ex), name, MySql::print_type(bt, schema)),
Primary => format!("{}{} {}", MySql::prefix(ex), name, MySql::print_type(bt, schema)),
Integer => format!("{}{} {}", MySql::prefix(ex), name, MySql::print_type(bt, schema)),
Float => format!("{}{} {}", MySql::prefix(ex), name, MySql::print_type(bt, schema)),
Double => format!("{}{} {}", MySql::prefix(ex), name, MySql::print_type(bt, schema)),
UUID => unimplemented!(),
Json => format!("{}{} {}", MySql::prefix(ex), name, MySql::print_type(bt, schema)),
Boolean => format!("{}{} {}", MySql::prefix(ex), name, MySql::print_type(bt, schema)),
Date => format!("{}{} {}", MySql::prefix(ex), name, MySql::print_type(bt, schema)),
Binary => format!("{}{} {}", MySql::prefix(ex), name, MySql::print_type(bt, schema)),
Foreign(_, _, _) => format!("{}{} {}", MySql::prefix(ex), name, MySql::print_type(bt, schema)),
Custom(_) => format!("{}{} {}", MySql::prefix(ex), name, MySql::print_type(bt, schema)),
Array(it) => format!("{}{} {}", MySql::prefix(ex), name, MySql::print_type(Array(Box::new(*it)), schema)),
Index(_) => unreachable!(),
},
match tt.primary {
true => " PRIMARY KEY",
false => "",
},
match (&tt.default).as_ref() {
Some(ref m) => format!(" DEFAULT '{}'", m),
_ => format!(""),
},
match tt.nullable {
true => "",
false => " NOT NULL",
},
match tt.unique {
true => " UNIQUE",
false => "",
},
)
}
fn drop_column(name: &str) -> String {
format!("DROP COLUMN `{}`", name)
}
fn rename_column(old: &str, new: &str) -> String {
format!("CHANGE COLUMN `{}` `{}`", old, new)
}
fn create_index(table: &str, schema: Option<&str>, name: &str, _type: &Type) -> String {
// FIXME: Implement Mysql specific index builder here
format!(
"CREATE {} INDEX `{}` ON {}`{}` ({})",
match _type.unique {
true => "UNIQUE",
false => "",
},
name,
prefix!(schema),
table,
match _type.inner {
BaseType::Index(ref cols) => cols
.iter()
.map(|col| format!("`{}`", col))
.collect::<Vec<_>>()
.join(", "),
_ => unreachable!(),
}
)
}
fn drop_index(name: &str) -> String {
format!("DROP INDEX `{}`", name)
}
}
impl MySql {
fn prefix(ex: bool) -> String {
match ex {
true => format!("ADD COLUMN "),
false => format!(""),
}
}
fn print_type(t: BaseType, schema: Option<&str>) -> String {
use self::BaseType::*;
match t {
Text => format!("TEXT"),
Varchar(l) => match l {
0 => format!("VARCHAR"), // For "0" remove the limit
_ => format!("VARCHAR({})", l),
},
/* "NOT NULL" is added here because normally primary keys are implicitly not-null */
Primary => format!("INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY"),
Integer => format!("INTEGER"),
Float => format!("FLOAT"),
Double => format!("DOUBLE"),
UUID => format!("CHAR(36)"),
Boolean => format!("BOOLEAN"),
Date => format!("DATE"),
Json => format!("JSON"),
Binary => format!("BYTEA"),
Foreign(s, t, refs) => format!(
"INTEGER REFERENCES {}{}({})",
prefix!(s),
t,
refs.0.join(",")
),
Custom(t) => format!("{}", t),
Array(meh) => format!("{}[]", MySql::print_type(*meh, schema)),
Index(_) => unreachable!(),
}
}
}