use super::{MssqlColumn, TableName};
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)]
pub struct CreateTableOptions;
pub fn create_table_sql(
table: &TableName,
columns: &[MssqlColumn],
_options: CreateTableOptions,
) -> String {
let mut sql = format!("CREATE TABLE {} (", table.quoted_sql());
if columns.is_empty() {
sql.push_str("\n);");
return sql;
}
for (index, column) in columns.iter().enumerate() {
let suffix = if index + 1 == columns.len() { "" } else { "," };
sql.push_str("\n ");
sql.push_str(&column.to_sql());
sql.push_str(suffix);
}
sql.push_str("\n);");
sql
}
#[cfg(test)]
mod tests {
use crate::{
CreateTableOptions, Identifier, MssqlColumn, MssqlTimePrecision, MssqlType,
MssqlTypeLength, TableName, create_table_sql,
};
#[test]
fn renders_create_table_with_deterministic_formatting() {
let table = TableName::new("dbo", "target").unwrap();
let columns = vec![
MssqlColumn::new(Identifier::new("id").unwrap(), MssqlType::Int, false),
MssqlColumn::new(
Identifier::new("name").unwrap(),
MssqlType::NVarChar(MssqlTypeLength::Max),
true,
),
];
let sql = create_table_sql(&table, &columns, CreateTableOptions);
assert_eq!(
sql,
"CREATE TABLE [dbo].[target] (\n [id] int NOT NULL,\n [name] nvarchar(max) NULL\n);"
);
}
#[test]
fn quotes_table_and_column_identifiers() {
let table = TableName::new("dbo.part", "target]part").unwrap();
let columns = vec![MssqlColumn::new(
Identifier::new("select]from").unwrap(),
MssqlType::Bit,
false,
)];
let sql = create_table_sql(&table, &columns, CreateTableOptions);
assert_eq!(
sql,
"CREATE TABLE [dbo.part].[target]]part] (\n [select]]from] bit NOT NULL\n);"
);
}
#[test]
fn renders_empty_column_list_without_panicking() {
let table = TableName::unqualified("empty").unwrap();
let sql = create_table_sql(&table, &[], CreateTableOptions);
assert_eq!(sql, "CREATE TABLE [empty] (\n);");
}
#[test]
fn renders_decimal_and_temporal_columns() {
let table = TableName::new("dbo", "events").unwrap();
let columns = vec![
MssqlColumn::new(
Identifier::new("amount").unwrap(),
MssqlType::Decimal {
precision: 38,
scale: 9,
},
false,
),
MssqlColumn::new(
Identifier::new("event_date").unwrap(),
MssqlType::Date,
true,
),
MssqlColumn::new(
Identifier::new("event_time").unwrap(),
MssqlType::Time(MssqlTimePrecision::SEVEN),
true,
),
MssqlColumn::new(
Identifier::new("created_at").unwrap(),
MssqlType::DateTime2 { precision: 7 },
false,
),
MssqlColumn::new(
Identifier::new("source_offset").unwrap(),
MssqlType::DateTimeOffset { precision: 7 },
true,
),
];
let sql = create_table_sql(&table, &columns, CreateTableOptions);
assert_eq!(
sql,
"CREATE TABLE [dbo].[events] (\n [amount] decimal(38,9) NOT NULL,\n [event_date] date NULL,\n [event_time] time(7) NULL,\n [created_at] datetime2(7) NOT NULL,\n [source_offset] datetimeoffset(7) NULL\n);"
);
}
#[test]
fn renders_fixed_binary_columns() {
let table = TableName::new("dbo", "binary_values").unwrap();
let columns = vec![MssqlColumn::new(
Identifier::new("digest").unwrap(),
MssqlType::Binary(32),
false,
)];
let sql = create_table_sql(&table, &columns, CreateTableOptions);
assert_eq!(
sql,
"CREATE TABLE [dbo].[binary_values] (\n [digest] binary(32) NOT NULL\n);"
);
}
}