1use std::fmt::Write;
2
3use crate::create_column::{CreateColumn, CreateColumnImpl};
4use crate::error::Error;
5use crate::Value;
6
7pub trait CreateTable<'until_build, 'post_build> {
11 fn add_column(self, column: CreateColumnImpl<'until_build, 'post_build>) -> Self;
15
16 fn if_not_exists(self) -> Self;
20
21 fn build(self) -> Result<Vec<(String, Vec<Value<'post_build>>)>, Error>;
28}
29
30pub struct CreateTableData<'until_build, 'post_build> {
34 pub(crate) name: &'until_build str,
35 pub(crate) columns: Vec<CreateColumnImpl<'until_build, 'post_build>>,
36 pub(crate) if_not_exists: bool,
37 pub(crate) lookup: Vec<Value<'post_build>>,
38 pub(crate) pre_statements: Vec<(String, Vec<Value<'post_build>>)>,
39 pub(crate) statements: Vec<(String, Vec<Value<'post_build>>)>,
40}
41
42pub enum CreateTableImpl<'until_build, 'post_build> {
48 #[cfg(feature = "sqlite")]
52 SQLite(CreateTableData<'until_build, 'post_build>),
53 #[cfg(feature = "mysql")]
57 MySQL(CreateTableData<'until_build, 'post_build>),
58 #[cfg(feature = "postgres")]
62 Postgres(CreateTableData<'until_build, 'post_build>),
63}
64
65impl<'until_build, 'post_build> CreateTable<'until_build, 'post_build>
66 for CreateTableImpl<'until_build, 'post_build>
67{
68 fn add_column(mut self, column: CreateColumnImpl<'until_build, 'post_build>) -> Self {
69 match self {
70 #[cfg(feature = "sqlite")]
71 CreateTableImpl::SQLite(ref mut d) => d.columns.push(column),
72 #[cfg(feature = "mysql")]
73 CreateTableImpl::MySQL(ref mut d) => d.columns.push(column),
74 #[cfg(feature = "postgres")]
75 CreateTableImpl::Postgres(ref mut d) => d.columns.push(column),
76 }
77 self
78 }
79
80 fn if_not_exists(mut self) -> Self {
81 match self {
82 #[cfg(feature = "sqlite")]
83 CreateTableImpl::SQLite(ref mut d) => d.if_not_exists = true,
84 #[cfg(feature = "mysql")]
85 CreateTableImpl::MySQL(ref mut d) => d.if_not_exists = true,
86 #[cfg(feature = "postgres")]
87 CreateTableImpl::Postgres(ref mut d) => d.if_not_exists = true,
88 }
89 self
90 }
91
92 fn build(self) -> Result<Vec<(String, Vec<Value<'post_build>>)>, Error> {
93 match self {
94 #[cfg(feature = "sqlite")]
95 CreateTableImpl::SQLite(mut d) => {
96 let mut s = format!(
97 "CREATE TABLE{} \"{}\" (",
98 if d.if_not_exists {
99 " IF NOT EXISTS"
100 } else {
101 ""
102 },
103 d.name
104 );
105
106 let columns_len = d.columns.len() - 1;
107 for (idx, mut x) in d.columns.into_iter().enumerate() {
108 #[cfg(any(feature = "mysql", feature = "postgres"))]
109 if let CreateColumnImpl::SQLite(ref mut cci) = x {
110 cci.statements = Some(&mut d.statements)
111 }
112 #[cfg(not(any(feature = "mysql", feature = "postgres")))]
113 {
114 let CreateColumnImpl::SQLite(ref mut cci) = x;
115 cci.statements = Some(&mut d.statements);
116 }
117
118 x.build(&mut s)?;
119
120 if idx != columns_len {
121 write!(s, ", ").unwrap();
122 }
123 }
124
125 write!(s, ") STRICT; ").unwrap();
126
127 let mut statements = vec![(s, d.lookup)];
128 statements.extend(d.statements);
129
130 Ok(statements)
131 }
132 #[cfg(feature = "mysql")]
133 CreateTableImpl::MySQL(mut d) => {
134 let mut s = format!(
135 "CREATE TABLE{} `{}` (",
136 if d.if_not_exists {
137 " IF NOT EXISTS"
138 } else {
139 ""
140 },
141 d.name
142 );
143
144 let columns_len = d.columns.len() - 1;
145 for (idx, mut x) in d.columns.into_iter().enumerate() {
146 #[cfg(any(feature = "postgres", feature = "sqlite"))]
147 if let CreateColumnImpl::MySQL(ref mut cci) = x {
148 cci.statements = Some(&mut d.statements);
149 }
150 #[cfg(not(any(feature = "postgres", feature = "sqlite")))]
151 {
152 let CreateColumnImpl::MySQL(ref mut cci) = x;
153 cci.statements = Some(&mut d.statements);
154 }
155
156 x.build(&mut s)?;
157
158 if idx != columns_len {
159 write!(s, ", ").unwrap();
160 }
161 }
162
163 write!(s, "); ").unwrap();
164
165 let mut statements = vec![(s, d.lookup)];
166 statements.extend(d.statements);
167
168 Ok(statements)
169 }
170 #[cfg(feature = "postgres")]
171 CreateTableImpl::Postgres(mut d) => {
172 let mut s = format!(
173 "CREATE TABLE{} \"{}\" (",
174 if d.if_not_exists {
175 " IF NOT EXISTS"
176 } else {
177 ""
178 },
179 d.name
180 );
181
182 let columns_len = d.columns.len() - 1;
183 for (idx, mut x) in d.columns.into_iter().enumerate() {
184 #[cfg(any(feature = "sqlite", feature = "mysql"))]
185 if let CreateColumnImpl::Postgres(ref mut cci) = x {
186 cci.pre_statements = Some(&mut d.pre_statements);
187 cci.statements = Some(&mut d.statements);
188 }
189 #[cfg(not(any(feature = "sqlite", feature = "mysql")))]
190 {
191 let CreateColumnImpl::Postgres(ref mut cci) = x;
192 cci.pre_statements = Some(&mut d.pre_statements);
193 cci.statements = Some(&mut d.statements);
194 }
195
196 x.build(&mut s)?;
197
198 if idx != columns_len {
199 write!(s, ", ").unwrap();
200 }
201 }
202
203 write!(s, "); ").unwrap();
204
205 let mut statements = d.pre_statements;
206 statements.push((s, d.lookup));
207 statements.extend(d.statements);
208
209 Ok(statements)
210 }
211 }
212 }
213}