arrow_tiberius/mssql/
ddl.rs1use super::{MssqlColumn, TableName};
4
5#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)]
7pub struct CreateTableOptions;
8
9pub fn create_table_sql(
11 table: &TableName,
12 columns: &[MssqlColumn],
13 _options: CreateTableOptions,
14) -> String {
15 let mut sql = format!("CREATE TABLE {} (", table.quoted_sql());
16
17 if columns.is_empty() {
18 sql.push_str("\n);");
19 return sql;
20 }
21
22 for (index, column) in columns.iter().enumerate() {
23 let suffix = if index + 1 == columns.len() { "" } else { "," };
24 sql.push_str("\n ");
25 sql.push_str(&column.to_sql());
26 sql.push_str(suffix);
27 }
28
29 sql.push_str("\n);");
30 sql
31}
32
33#[cfg(test)]
34mod tests {
35 use crate::{
36 CreateTableOptions, Identifier, MssqlColumn, MssqlTimePrecision, MssqlType,
37 MssqlTypeLength, TableName, create_table_sql,
38 };
39
40 #[test]
41 fn renders_create_table_with_deterministic_formatting() {
42 let table = TableName::new("dbo", "target").unwrap();
43 let columns = vec![
44 MssqlColumn::new(Identifier::new("id").unwrap(), MssqlType::Int, false),
45 MssqlColumn::new(
46 Identifier::new("name").unwrap(),
47 MssqlType::NVarChar(MssqlTypeLength::Max),
48 true,
49 ),
50 ];
51
52 let sql = create_table_sql(&table, &columns, CreateTableOptions);
53
54 assert_eq!(
55 sql,
56 "CREATE TABLE [dbo].[target] (\n [id] int NOT NULL,\n [name] nvarchar(max) NULL\n);"
57 );
58 }
59
60 #[test]
61 fn quotes_table_and_column_identifiers() {
62 let table = TableName::new("dbo.part", "target]part").unwrap();
63 let columns = vec![MssqlColumn::new(
64 Identifier::new("select]from").unwrap(),
65 MssqlType::Bit,
66 false,
67 )];
68
69 let sql = create_table_sql(&table, &columns, CreateTableOptions);
70
71 assert_eq!(
72 sql,
73 "CREATE TABLE [dbo.part].[target]]part] (\n [select]]from] bit NOT NULL\n);"
74 );
75 }
76
77 #[test]
78 fn renders_empty_column_list_without_panicking() {
79 let table = TableName::unqualified("empty").unwrap();
80
81 let sql = create_table_sql(&table, &[], CreateTableOptions);
82
83 assert_eq!(sql, "CREATE TABLE [empty] (\n);");
84 }
85
86 #[test]
87 fn renders_decimal_and_temporal_columns() {
88 let table = TableName::new("dbo", "events").unwrap();
89 let columns = vec![
90 MssqlColumn::new(
91 Identifier::new("amount").unwrap(),
92 MssqlType::Decimal {
93 precision: 38,
94 scale: 9,
95 },
96 false,
97 ),
98 MssqlColumn::new(
99 Identifier::new("event_date").unwrap(),
100 MssqlType::Date,
101 true,
102 ),
103 MssqlColumn::new(
104 Identifier::new("event_time").unwrap(),
105 MssqlType::Time(MssqlTimePrecision::SEVEN),
106 true,
107 ),
108 MssqlColumn::new(
109 Identifier::new("created_at").unwrap(),
110 MssqlType::DateTime2 { precision: 7 },
111 false,
112 ),
113 MssqlColumn::new(
114 Identifier::new("source_offset").unwrap(),
115 MssqlType::DateTimeOffset { precision: 7 },
116 true,
117 ),
118 ];
119
120 let sql = create_table_sql(&table, &columns, CreateTableOptions);
121
122 assert_eq!(
123 sql,
124 "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);"
125 );
126 }
127
128 #[test]
129 fn renders_fixed_binary_columns() {
130 let table = TableName::new("dbo", "binary_values").unwrap();
131 let columns = vec![MssqlColumn::new(
132 Identifier::new("digest").unwrap(),
133 MssqlType::Binary(32),
134 false,
135 )];
136
137 let sql = create_table_sql(&table, &columns, CreateTableOptions);
138
139 assert_eq!(
140 sql,
141 "CREATE TABLE [dbo].[binary_values] (\n [digest] binary(32) NOT NULL\n);"
142 );
143 }
144}