Skip to content

Commit 74c2848

Browse files
committed
adds alter table builder
1 parent 786175e commit 74c2848

File tree

13 files changed

+1215
-35
lines changed

13 files changed

+1215
-35
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ description = "Write SQL queries in a simple and composable way"
44
documentation = "https://docs.rs/sql_query_builder"
55
repository = "https://github.com/belchior/sql_query_builder"
66
authors = ["Belchior Oliveira <[email protected]>"]
7-
version = "2.2.0"
7+
version = "2.3.0"
88
edition = "2021"
99
rust-version = "1.62"
1010
license = "MIT"

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ sql_query_builder = { version = "2.x.x", features = ["postgresql"] }
4949

5050
## How it's works
5151

52-
In a simplified way, it has an API that allows you to write dynamic queries in a style
52+
In a simplified way, the lib has an API to allows you to write dynamic queries in a style
5353
similar to queries written in pure SQL and the result is a code idiomatic to both Rust and SQL.
5454
Additionally, the library will not try to understand what you write in the parameters and in some
5555
ways this is good as it removes a lot of verbosity to generate a SQL query, in contrast,

scripts/watch_test.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,5 +19,6 @@ esac
1919

2020
[ ! -z "$features" ] && features="--features $features"
2121

22+
# cargo watch -w ./src -w ./tests -x 'test --test command_alter_table_spec'
2223
# cargo watch -w ./src -w ./tests -x 'test --features postgresql -- --nocapture --color always'
2324
cargo watch -w ./src -w ./tests -x "test $features"

src/alter_table/alter_table.rs

Lines changed: 351 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,351 @@
1+
use crate::{
2+
behavior::{push_unique, Concat, TransactionQuery},
3+
fmt,
4+
structure::{AlterTable, AlterTableAction, AlterTableActionItem, AlterTableOrderedAction},
5+
};
6+
7+
impl TransactionQuery for AlterTable {}
8+
9+
impl AlterTable {
10+
/// Adds columns or table constraints.
11+
/// Multiples call of this method will build the SQL respecting the order of the calls
12+
///
13+
/// ### Example
14+
///
15+
/// ```
16+
/// # use sql_query_builder as sql;
17+
/// let query = sql::AlterTable::new()
18+
/// .add("COLUMN age int not null")
19+
/// .add("CONSTRAINT age check(age >= 0)")
20+
/// .as_string();
21+
///
22+
/// # let expected = "\
23+
/// # ADD COLUMN age int not null, \
24+
/// # ADD CONSTRAINT age check(age >= 0)\
25+
/// # ";
26+
/// # assert_eq!(expected, query);
27+
/// ```
28+
///
29+
/// Outputs
30+
///
31+
/// ```sql
32+
/// ADD COLUMN age int not null,
33+
/// ADD CONSTRAINT age check(age >= 0)
34+
/// ```
35+
pub fn add(mut self, add_exp: &str) -> Self {
36+
let action = AlterTableActionItem(AlterTableOrderedAction::Add, add_exp.trim().to_string());
37+
push_unique(&mut self._ordered_actions, action);
38+
self
39+
}
40+
41+
/// Defines the name of the table to be altered, this method overrides the previous value
42+
///
43+
/// ### Example
44+
///
45+
/// ```
46+
/// # use sql_query_builder as sql;
47+
/// let query = sql::AlterTable::new()
48+
/// .alter_table("users")
49+
/// .as_string();
50+
///
51+
/// # let expected = "ALTER TABLE users";
52+
/// # assert_eq!(expected, query);
53+
/// ```
54+
///
55+
/// Outputs
56+
///
57+
/// ```sql
58+
/// ALTER TABLE users
59+
/// ```
60+
pub fn alter_table(mut self, table_name: &str) -> Self {
61+
self._alter_table = table_name.trim().to_string();
62+
self
63+
}
64+
65+
/// Gets the current state of the [AlterTable] and returns it as string
66+
///
67+
/// ### Example
68+
///
69+
/// ```
70+
/// # #[cfg(any(feature = "postgresql", feature = "sqlite"))]
71+
/// # {
72+
/// # use sql_query_builder as sql;
73+
/// let query = sql::AlterTable::new()
74+
/// .alter_table("users")
75+
/// .rename_to("users_old")
76+
/// .as_string();
77+
///
78+
/// # let expected = "ALTER TABLE users RENAME TO users_old";
79+
/// # assert_eq!(expected, query);
80+
/// # }
81+
/// ```
82+
///
83+
/// Output
84+
///
85+
/// ```sql
86+
/// ALTER TABLE users RENAME TO users_old
87+
/// ```
88+
pub fn as_string(&self) -> String {
89+
let fmts = fmt::one_line();
90+
self.concat(&fmts)
91+
}
92+
93+
/// Prints the current state of the [AlterTable] to the standard output in a more ease to read version.
94+
/// This method is useful to debug complex queries or just print the generated SQL while you type
95+
///
96+
/// ### Example
97+
///
98+
/// ```
99+
/// # use sql_query_builder as sql;
100+
/// let query = sql::AlterTable::new()
101+
/// .alter_table("users")
102+
/// .add("name varchar(100) not null")
103+
/// .add("login varchar(40) not null")
104+
/// .add("constraint users_login_key unique(login)")
105+
/// .debug()
106+
/// .as_string();
107+
/// ```
108+
///
109+
/// Prints to the standard output
110+
///
111+
/// ```sql
112+
/// -- ------------------------------------------------------------------------------
113+
/// ALTER TABLE users
114+
/// ADD name varchar(100) not null,
115+
/// ADD login varchar(40) not null,
116+
/// ADD constraint users_login_key unique(login)
117+
/// -- ------------------------------------------------------------------------------
118+
/// ```
119+
pub fn debug(self) -> Self {
120+
let fmts = fmt::multiline();
121+
println!("{}", fmt::format(self.concat(&fmts), &fmts));
122+
self
123+
}
124+
125+
/// Drops columns or table constraints.
126+
/// Multiples call of this method will build the SQL respecting the order of the calls
127+
///
128+
/// ### Example
129+
///
130+
/// ```
131+
/// # use sql_query_builder as sql;
132+
/// let query = sql::AlterTable::new()
133+
/// .drop("column login")
134+
/// .as_string();
135+
///
136+
/// # let expected = "DROP column login";
137+
/// # assert_eq!(expected, query);
138+
/// ```
139+
///
140+
/// Outputs
141+
///
142+
/// ```sql
143+
/// DROP column login
144+
/// ```
145+
pub fn drop(mut self, drop_exp: &str) -> Self {
146+
let action = AlterTableActionItem(AlterTableOrderedAction::Drop, drop_exp.trim().to_string());
147+
push_unique(&mut self._ordered_actions, action);
148+
self
149+
}
150+
151+
/// Creates instance of the [AlterTable] command
152+
pub fn new() -> Self {
153+
Self::default()
154+
}
155+
156+
/// Prints the current state of the [AlterTable] to the standard output similar to debug method,
157+
/// the difference is that this method prints in one line.
158+
pub fn print(self) -> Self {
159+
let fmts = fmt::one_line();
160+
println!("{}", fmt::format(self.concat(&fmts), &fmts));
161+
self
162+
}
163+
164+
/// Adds at the beginning a raw SQL query. Is useful to create a more complex alter table signature like the example below.
165+
///
166+
/// ### Example
167+
///
168+
/// ```
169+
/// # use sql_query_builder as sql;
170+
/// let create_table_query = sql::AlterTable::new()
171+
/// .raw("ALTER TABLE IF EXISTS users")
172+
/// .drop("legacy_column")
173+
/// .as_string();
174+
///
175+
/// # let expected = "ALTER TABLE IF EXISTS users DROP legacy_column";
176+
/// # assert_eq!(expected, create_table_query);
177+
/// ```
178+
///
179+
/// Output
180+
///
181+
/// ```sql
182+
/// ALTER TABLE IF EXISTS users DROP legacy_column
183+
/// ```
184+
pub fn raw(mut self, raw_sql: &str) -> Self {
185+
push_unique(&mut self._raw, raw_sql.trim().to_string());
186+
self
187+
}
188+
189+
/// Adds a raw SQL query after a specified parameter.
190+
///
191+
/// ### Example
192+
///
193+
/// ```
194+
/// # use sql_query_builder as sql;
195+
/// let raw = "ADD COLUMN name varchar(100) not null";
196+
///
197+
/// let query = sql::AlterTable::new()
198+
/// .alter_table("users")
199+
/// .raw_after(sql::AlterTableAction::AlterTable, raw)
200+
/// .as_string();
201+
///
202+
/// # let expected = "ALTER TABLE users ADD COLUMN name varchar(100) not null";
203+
/// # assert_eq!(expected, query);
204+
/// ```
205+
///
206+
/// Output
207+
///
208+
/// ```sql
209+
/// ALTER TABLE users ADD COLUMN name varchar(100) not null
210+
/// ```
211+
pub fn raw_after(mut self, param: AlterTableAction, raw_sql: &str) -> Self {
212+
self._raw_after.push((param, raw_sql.trim().to_string()));
213+
self
214+
}
215+
216+
/// Adds a raw SQL query before a specified parameter.
217+
///
218+
/// ### Example
219+
///
220+
/// ```
221+
/// # use sql_query_builder as sql;
222+
/// let raw = "ALTER TABLE users";
223+
///
224+
/// let query = sql::AlterTable::new()
225+
/// .raw_before(sql::AlterTableAction::AlterTable, raw)
226+
/// .add("COLUMN id")
227+
/// .as_string();
228+
///
229+
/// # let expected = "ALTER TABLE users ADD COLUMN id";
230+
/// # assert_eq!(expected, query);
231+
/// ```
232+
///
233+
/// Output
234+
///
235+
/// ```sql
236+
/// ALTER TABLE users RENAME TO users_old
237+
/// ```
238+
pub fn raw_before(mut self, action: AlterTableAction, raw_sql: &str) -> Self {
239+
self._raw_before.push((action, raw_sql.trim().to_string()));
240+
self
241+
}
242+
}
243+
244+
#[cfg(any(doc, feature = "postgresql", feature = "sqlite"))]
245+
#[cfg_attr(docsrs, doc(cfg(feature = "postgresql")))]
246+
#[cfg_attr(docsrs, doc(cfg(feature = "sqlite")))]
247+
impl AlterTable {
248+
/// Changes the column names or table constraints.
249+
/// Multiples call of this method will build the SQL respecting the order of the calls
250+
///
251+
/// ### Example
252+
///
253+
///```
254+
/// # #[cfg(any(feature = "postgresql", feature = "sqlite"))]
255+
/// # {
256+
/// # use sql_query_builder as sql;
257+
/// let query = sql::AlterTable::new()
258+
/// .alter_table("users")
259+
/// .rename("COLUMN address TO city")
260+
/// .to_string();
261+
///
262+
/// # let expected = "ALTER TABLE users RENAME COLUMN address TO city";
263+
/// # assert_eq!(expected, query);
264+
/// # }
265+
/// ```
266+
///
267+
/// Outputs
268+
///
269+
/// ```sql
270+
/// ALTER TABLE users RENAME COLUMN address TO city
271+
/// ```
272+
pub fn rename(mut self, rename_exp: &str) -> Self {
273+
let action = AlterTableActionItem(AlterTableOrderedAction::Rename, rename_exp.trim().to_string());
274+
push_unique(&mut self._ordered_actions, action);
275+
self
276+
}
277+
278+
/// Changes the name of the table
279+
///
280+
/// ### Example
281+
///
282+
/// ```
283+
/// # #[cfg(any(feature = "postgresql", feature = "sqlite"))]
284+
/// # {
285+
/// # use sql_query_builder as sql;
286+
/// let query = sql::AlterTable::new()
287+
/// .alter_table("users")
288+
/// .rename_to("users_old")
289+
/// .to_string();
290+
///
291+
/// # let expected = "ALTER TABLE users RENAME TO users_old";
292+
/// # assert_eq!(expected, query);
293+
/// # }
294+
/// ```
295+
///
296+
/// Outputs
297+
///
298+
/// ```sql
299+
/// ALTER TABLE users RENAME TO users_old
300+
/// ```
301+
pub fn rename_to(mut self, table_name: &str) -> Self {
302+
self._rename_to = table_name.trim().to_string();
303+
self
304+
}
305+
}
306+
307+
#[cfg(any(doc, feature = "postgresql"))]
308+
#[cfg_attr(docsrs, doc(cfg(feature = "postgresql")))]
309+
impl AlterTable {
310+
/// Alter columns or table constraints.
311+
/// Multiples call of this method will build the SQL respecting the order of the calls
312+
///
313+
/// ### Example
314+
///
315+
///```
316+
/// # #[cfg(any(feature = "postgresql"))]
317+
/// # {
318+
/// # use sql_query_builder as sql;
319+
/// let query = sql::AlterTable::new()
320+
/// .alter("COLUMN created_at SET DEFAULT now()")
321+
/// .to_string();
322+
///
323+
/// # let expected = "ALTER COLUMN created_at SET DEFAULT now()";
324+
/// # assert_eq!(expected, query);
325+
/// # }
326+
/// ```
327+
///
328+
/// Outputs
329+
///
330+
/// ```sql
331+
/// ALTER COLUMN created_at SET DEFAULT now()
332+
/// ```
333+
pub fn alter(mut self, alter_exp: &str) -> Self {
334+
let action = AlterTableActionItem(AlterTableOrderedAction::Alter, alter_exp.trim().to_string());
335+
push_unique(&mut self._ordered_actions, action);
336+
self
337+
}
338+
}
339+
340+
impl std::fmt::Display for AlterTable {
341+
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
342+
write!(f, "{}", self.as_string())
343+
}
344+
}
345+
346+
impl std::fmt::Debug for AlterTable {
347+
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
348+
let fmts = fmt::multiline();
349+
write!(f, "{}", fmt::format(self.concat(&fmts), &fmts))
350+
}
351+
}

0 commit comments

Comments
 (0)