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.
162 lines
6.0 KiB
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!(),
|
|
}
|
|
}
|
|
}
|
|
|