1use std::fmt::Write;
2
3use crate::create_column::{CreateColumn, CreateColumnImpl};
4use crate::error::Error;
5use crate::Value;
6
7#[derive(Debug)]
11pub enum AlterTableOperation<'until_build, 'post_build> {
12 RenameTo {
14 name: String,
16 },
17 RenameColumnTo {
19 column_name: String,
21 new_column_name: String,
23 },
24 AddColumn {
26 operation: CreateColumnImpl<'until_build, 'post_build>,
28 },
29 DropColumn {
31 name: String,
33 },
34}
35
36pub trait AlterTable<'post_build> {
40 fn build(self) -> Result<Vec<(String, Vec<Value<'post_build>>)>, Error>;
44}
45
46#[derive(Debug)]
50pub struct AlterTableData<'until_build, 'post_build> {
51 pub(crate) name: &'until_build str,
53 pub(crate) operation: AlterTableOperation<'until_build, 'post_build>,
55 pub(crate) lookup: Vec<Value<'post_build>>,
56 pub(crate) statements: Vec<(String, Vec<Value<'post_build>>)>,
57}
58
59#[derive(Debug)]
65pub enum AlterTableImpl<'until_build, 'post_build> {
66 #[cfg(feature = "sqlite")]
70 SQLite(AlterTableData<'until_build, 'post_build>),
71 #[cfg(feature = "mysql")]
75 MySQL(AlterTableData<'until_build, 'post_build>),
76 #[cfg(feature = "postgres")]
80 Postgres(AlterTableData<'until_build, 'post_build>),
81}
82
83impl<'post_build> AlterTable<'post_build> for AlterTableImpl<'_, 'post_build> {
84 fn build(self) -> Result<Vec<(String, Vec<Value<'post_build>>)>, Error> {
85 match self {
86 #[cfg(feature = "sqlite")]
87 AlterTableImpl::SQLite(mut d) => {
88 let mut s = format!("ALTER TABLE \"{}\" ", d.name);
89
90 match d.operation {
91 AlterTableOperation::RenameTo { name } => {
92 write!(s, "RENAME TO \"{name}\"").unwrap();
93 }
94 AlterTableOperation::RenameColumnTo {
95 column_name,
96 new_column_name,
97 } => write!(
98 s,
99 "RENAME COLUMN \"{column_name}\" TO \"{new_column_name}\""
100 )
101 .unwrap(),
102 AlterTableOperation::AddColumn { mut operation } => {
103 write!(s, "ADD COLUMN ").unwrap();
104
105 #[cfg(any(feature = "mysql", feature = "postgres"))]
106 if let CreateColumnImpl::SQLite(ref mut ccd) = operation {
107 ccd.statements = Some(&mut d.statements);
108 ccd.lookup = Some(&mut d.lookup);
109 }
110 #[cfg(not(any(feature = "mysql", feature = "postgres")))]
111 {
112 let CreateColumnImpl::SQLite(ref mut ccd) = operation;
113 ccd.statements = Some(&mut d.statements);
114 ccd.lookup = Some(&mut d.lookup);
115 }
116
117 operation.build(&mut s)?;
118 }
119 AlterTableOperation::DropColumn { name } => {
120 write!(s, "DROP COLUMN \"{name}\"").unwrap()
121 }
122 };
123
124 write!(s, ";").unwrap();
125
126 let mut statements = vec![(s, d.lookup)];
127 statements.extend(d.statements);
128
129 Ok(statements)
130 }
131 #[cfg(feature = "mysql")]
132 AlterTableImpl::MySQL(mut d) => {
133 let mut s = format!("ALTER TABLE `{}` ", d.name);
134
135 match d.operation {
136 AlterTableOperation::RenameTo { name } => {
137 write!(s, "RENAME TO `{name}`").unwrap();
138 }
139 AlterTableOperation::RenameColumnTo {
140 column_name,
141 new_column_name,
142 } => write!(s, "RENAME COLUMN `{column_name}` TO `{new_column_name}`").unwrap(),
143 AlterTableOperation::AddColumn { mut operation } => {
144 write!(s, "ADD COLUMN ").unwrap();
145
146 #[cfg(any(feature = "sqlite", feature = "postgres"))]
147 if let CreateColumnImpl::MySQL(ref mut ccd) = operation {
148 ccd.statements = Some(&mut d.statements);
149 ccd.lookup = Some(&mut d.lookup);
150 }
151 #[cfg(not(any(feature = "sqlite", feature = "postgres")))]
152 {
153 let CreateColumnImpl::MySQL(ref mut ccd) = operation;
154 ccd.statements = Some(&mut d.statements);
155 ccd.lookup = Some(&mut d.lookup);
156 }
157
158 operation.build(&mut s)?;
159 }
160 AlterTableOperation::DropColumn { name } => {
161 write!(s, "DROP COLUMN `{name}`").unwrap()
162 }
163 };
164
165 write!(s, ";").unwrap();
166
167 let mut statements = vec![(s, d.lookup)];
168 statements.extend(d.statements);
169
170 Ok(statements)
171 }
172 #[cfg(feature = "postgres")]
173 AlterTableImpl::Postgres(mut d) => {
174 let mut s = format!("ALTER TABLE \"{}\" ", d.name);
175
176 match d.operation {
177 AlterTableOperation::RenameTo { name } => {
178 write!(s, "RENAME TO \"{name}\"").unwrap();
179 }
180
181 AlterTableOperation::RenameColumnTo {
182 column_name,
183 new_column_name,
184 } => {
185 write!(
186 s,
187 "RENAME COLUMN \"{column_name}\" TO \"{new_column_name}\""
188 )
189 .unwrap();
190 }
191 AlterTableOperation::AddColumn { mut operation } => {
192 write!(s, "ADD COLUMN ").unwrap();
193
194 #[cfg(any(feature = "sqlite", feature = "mysql"))]
195 if let CreateColumnImpl::Postgres(ref mut ccd) = operation {
196 ccd.statements = Some(&mut d.statements);
197 }
198 #[cfg(not(any(feature = "sqlite", feature = "mysql")))]
199 {
200 let CreateColumnImpl::Postgres(ref mut ccd) = operation;
201 ccd.statements = Some(&mut d.statements);
202 }
203
204 operation.build(&mut s)?;
205 }
206 AlterTableOperation::DropColumn { name } => {
207 write!(s, "DROP COLUMN \"{name}\"").unwrap()
208 }
209 };
210
211 write!(s, ";").unwrap();
212
213 let mut statements = vec![(s, d.lookup)];
214 statements.extend(d.statements);
215
216 Ok(statements)
217 }
218 }
219 }
220}