Skip to content

Commit fb14c80

Browse files
authored
Merge pull request #20 from belchior/adds-methods-window-and-where_and
adds methods window and where_and
2 parents f344ada + 9b98689 commit fb14c80

File tree

11 files changed

+286
-16
lines changed

11 files changed

+286
-16
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.0.0"
7+
version = "2.1.0"
88
edition = "2021"
99
rust-version = "1.62"
1010
license = "MIT"

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ SQL Query Builder comes with the following optional features:
4141
You can enable features like
4242

4343
```toml
44-
## Cargo.toml
44+
# Cargo.toml
4545

4646
sql_query_builder = { version = "2.x.x", features = ["postgresql"] }
4747
```
@@ -125,7 +125,7 @@ Composition is very welcome to write complex queries, this feature makes the lib
125125
use sql_query_builder as sql;
126126

127127
fn project(select: sql::Select) -> sql::Select {
128-
select
128+
select
129129
.select("u.id, u.name as user_name, u.login")
130130
.select("a.name as addresses_name")
131131
.select("o.name as product_name")

src/delete/delete.rs

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ impl Delete {
107107
/// ```
108108
/// # use sql_query_builder as sql;
109109
/// let raw_query = "delete from users";
110+
///
110111
/// let delete_query = sql::Delete::new()
111112
/// .raw(raw_query)
112113
/// .where_clause("login = 'foo'")
@@ -133,6 +134,7 @@ impl Delete {
133134
/// ```
134135
/// # use sql_query_builder as sql;
135136
/// let raw = "where name = 'Foo'";
137+
///
136138
/// let delete_query = sql::Delete::new()
137139
/// .delete_from("users")
138140
/// .raw_after(sql::DeleteClause::DeleteFrom, raw)
@@ -159,6 +161,7 @@ impl Delete {
159161
/// ```
160162
/// # use sql_query_builder as sql;
161163
/// let raw = "delete from users";
164+
///
162165
/// let delete_query = sql::Delete::new()
163166
/// .raw_before(sql::DeleteClause::Where, raw)
164167
/// .where_clause("name = 'Bar'")
@@ -178,6 +181,35 @@ impl Delete {
178181
self
179182
}
180183

184+
/// This method is un alias of `where_clause`. The `where_and` will concatenate mulltiples calls using the `and` operator.
185+
/// The intention is to enable more idiomatic concatenation of conditions.
186+
///
187+
/// # Example
188+
///
189+
/// ```
190+
/// # use sql_query_builder as sql;
191+
/// let delete_query = sql::Delete::new()
192+
/// .where_clause("login = $1")
193+
/// .where_and("product_id = $2")
194+
/// .where_and("created_at >= current_date")
195+
/// .as_string();
196+
///
197+
/// # let expected = "WHERE login = $1 AND product_id = $2 AND created_at >= current_date";
198+
/// # assert_eq!(delete_query, expected);
199+
/// ```
200+
///
201+
/// Outputs
202+
///
203+
/// ```sql
204+
/// WHERE
205+
/// login = $1
206+
/// AND product_id = $2
207+
/// AND created_at >= current_date
208+
/// ```
209+
pub fn where_and(self, condition: &str) -> Self {
210+
self.where_clause(condition)
211+
}
212+
181213
/// The `where` clause, this method will concatenate mulltiples calls using the `and` operator.
182214
/// If you intended to use the `or` operator you should use the [where_or](Delete::where_or) method
183215
///
@@ -237,7 +269,7 @@ impl Delete {
237269

238270
#[cfg(any(doc, feature = "postgresql", feature = "sqlite"))]
239271
impl Delete {
240-
/// The `returning` clause, this method can be used enabling a feature flag
272+
/// The `returning` clause, this method can be used enabling one of the feature flags `postgresql` or `sqlite`
241273
///
242274
/// # Example
243275
///
@@ -265,7 +297,7 @@ impl Delete {
265297
self
266298
}
267299

268-
/// The `with` clause, this method can be used enabling a feature flag
300+
/// The `with` clause, this method can be used enabling one of the feature flags `postgresql` or `sqlite`
269301
///
270302
/// # Example
271303
///

src/insert/insert.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,7 @@ impl Insert {
224224
/// ```
225225
/// # use sql_query_builder as sql;
226226
/// let raw_query = "insert into users (login, name)";
227+
///
227228
/// let insert_query = sql::Insert::new()
228229
/// .raw(raw_query)
229230
/// .values("('foo', 'Foo')")
@@ -250,6 +251,7 @@ impl Insert {
250251
/// ```
251252
/// # use sql_query_builder as sql;
252253
/// let raw = "values ('foo', 'Foo')";
254+
///
253255
/// let insert_query = sql::Insert::new()
254256
/// .insert_into("users (login, name)")
255257
/// .raw_after(sql::InsertClause::InsertInto, raw)
@@ -276,6 +278,7 @@ impl Insert {
276278
/// ```
277279
/// # use sql_query_builder as sql;
278280
/// let raw = "insert into users (login, name)";
281+
///
279282
/// let insert_query = sql::Insert::new()
280283
/// .raw_before(sql::InsertClause::Values, raw)
281284
/// .values("('bar', 'Bar')")
@@ -324,7 +327,7 @@ impl Insert {
324327

325328
#[cfg(any(doc, feature = "postgresql", feature = "sqlite"))]
326329
impl Insert {
327-
/// The `returning` clause, this method can be used enabling a feature flag
330+
/// The `returning` clause, this method can be used enabling one of the feature flags `postgresql` or `sqlite`
328331
///
329332
/// # Example
330333
///
@@ -353,7 +356,7 @@ impl Insert {
353356
self
354357
}
355358

356-
/// The `with` clause, this method can be used enabling a feature flag
359+
/// The `with` clause, this method can be used enabling one of the feature flags `postgresql` or `sqlite`
357360
///
358361
/// # Example
359362
///

src/select/select.rs

Lines changed: 64 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,7 @@ impl Select {
294294
/// ```
295295
/// # use sql_query_builder as sql;
296296
/// let raw_query = "select * from users";
297+
///
297298
/// let select_query = sql::Select::new()
298299
/// .raw(raw_query)
299300
/// .where_clause("users.login = 'foo'")
@@ -320,6 +321,7 @@ impl Select {
320321
/// ```
321322
/// # use sql_query_builder as sql;
322323
/// let raw_join = "inner join addresses addr on u.login = addr.owner_login";
324+
///
323325
/// let select_query = sql::Select::new()
324326
/// .from("users u")
325327
/// .raw_after(sql::SelectClause::From, raw_join)
@@ -353,6 +355,7 @@ impl Select {
353355
/// ```
354356
/// # use sql_query_builder as sql;
355357
/// let raw_query = "from users";
358+
///
356359
/// let select_query = sql::Select::new()
357360
/// .raw_before(sql::SelectClause::Where, raw_query)
358361
/// .where_clause("users.login = 'foo'")
@@ -393,6 +396,37 @@ impl Select {
393396
self
394397
}
395398

399+
/// This method is un alias of `where_clause`. The `where_and` will concatenate mulltiples calls using the `and` operator.
400+
/// The intention is to enable more idiomatic concatenation of conditions.
401+
///
402+
/// # Example
403+
///
404+
/// ```
405+
/// # use sql_query_builder as sql;
406+
/// let select_query = sql::Select::new()
407+
/// .from("carts")
408+
/// .where_clause("login = $1")
409+
/// .where_and("session_id = $2")
410+
/// .where_and("created_at >= current_date")
411+
/// .as_string();
412+
///
413+
/// # let expected = "FROM carts WHERE login = $1 AND session_id = $2 AND created_at >= current_date";
414+
/// # assert_eq!(select_query, expected);
415+
/// ```
416+
///
417+
/// Outputs
418+
///
419+
/// ```sql
420+
/// FROM carts
421+
/// WHERE
422+
/// login = $1
423+
/// AND session_id = $2
424+
/// AND created_at >= current_date
425+
/// ```
426+
pub fn where_and(self, condition: &str) -> Self {
427+
self.where_clause(condition)
428+
}
429+
396430
/// The `where` clause, this method will concatenate mulltiples calls using the `and` operator.
397431
/// If you intended to use the `or` operator you should use the [where_or](Select::where_or) method
398432
///
@@ -498,11 +532,35 @@ impl Select {
498532
push_unique(&mut self._where, (LogicalOperator::Or, condition.trim().to_string()));
499533
self
500534
}
535+
536+
/// The `window` clause
537+
///
538+
/// # Example
539+
///
540+
/// ```
541+
/// # use sql_query_builder as sql;
542+
/// let select_query = sql::Select::new()
543+
/// .window("win as (partition by department)")
544+
/// .as_string();
545+
///
546+
/// # let expected = "WINDOW win as (partition by department)";
547+
/// # assert_eq!(select_query, expected);
548+
/// ```
549+
///
550+
/// Output
551+
///
552+
/// ```sql
553+
/// WINDOW win as (partition by department)
554+
/// ```
555+
pub fn window(mut self, name: &str) -> Self {
556+
push_unique(&mut self._window, name.trim().to_string());
557+
self
558+
}
501559
}
502560

503561
#[cfg(any(doc, feature = "postgresql", feature = "sqlite"))]
504562
impl Select {
505-
/// The `except` clause, this method can be used enabling a feature flag
563+
/// The `except` clause, this method can be used enabling one of the feature flags `postgresql` or `sqlite`
506564
///
507565
/// # Example
508566
///
@@ -542,7 +600,7 @@ impl Select {
542600
self
543601
}
544602

545-
/// The `intersect` clause, this method can be used enabling a feature flag
603+
/// The `intersect` clause, this method can be used enabling one of the feature flags `postgresql` or `sqlite`
546604
///
547605
/// # Example
548606
///
@@ -582,7 +640,7 @@ impl Select {
582640
self
583641
}
584642

585-
/// The `limit` clause, this method overrides the previous value, this method can be used enabling a feature flag
643+
/// The `limit` clause, this method overrides the previous value, this method can be used enabling one of the feature flags `postgresql` or `sqlite`
586644
///
587645
/// # Example
588646
///
@@ -606,7 +664,7 @@ impl Select {
606664
self
607665
}
608666

609-
/// The `offset` clause, this method overrides the previous value, this method can be used enabling a feature flag
667+
/// The `offset` clause, this method overrides the previous value, this method can be used enabling one of the feature flags `postgresql` or `sqlite`
610668
///
611669
/// # Example
612670
///
@@ -630,7 +688,7 @@ impl Select {
630688
self
631689
}
632690

633-
/// The `union` clause, this method can be used enabling a feature flag
691+
/// The `union` clause, this method can be used enabling one of the feature flags `postgresql` or `sqlite`
634692
///
635693
/// # Example
636694
///
@@ -670,7 +728,7 @@ impl Select {
670728
self
671729
}
672730

673-
/// The `with` clause, this method can be used enabling a feature flag
731+
/// The `with` clause, this method can be used enabling one of the feature flags `postgresql` or `sqlite`
674732
///
675733
/// # Example
676734
///

src/select/select_internal.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ impl Concat for Select {
4545
);
4646
query = self.concat_group_by(query, &fmts);
4747
query = self.concat_having(query, &fmts);
48+
query = self.concat_window(query, &fmts);
4849
query = self.concat_order_by(query, &fmts);
4950

5051
#[cfg(any(feature = "postgresql", feature = "sqlite"))]
@@ -160,6 +161,25 @@ impl Select {
160161
sql,
161162
)
162163
}
164+
165+
fn concat_window(&self, query: String, fmts: &fmt::Formatter) -> String {
166+
let fmt::Formatter { comma, lb, space, .. } = fmts;
167+
let sql = if self._window.is_empty() == false {
168+
let columns = self._window.join(comma);
169+
format!("WINDOW{space}{columns}{space}{lb}")
170+
} else {
171+
"".to_string()
172+
};
173+
174+
concat_raw_before_after(
175+
&self._raw_before,
176+
&self._raw_after,
177+
query,
178+
fmts,
179+
SelectClause::Window,
180+
sql,
181+
)
182+
}
163183
}
164184

165185
#[cfg(any(feature = "postgresql", feature = "sqlite"))]

src/structure.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ pub struct Delete {
3333
/// # use sql_query_builder as sql;
3434
///
3535
/// let raw = "where name = 'Foo'";
36+
///
3637
/// let delete_query = sql::Delete::new()
3738
/// .delete_from("users")
3839
/// .raw_after(sql::DeleteClause::DeleteFrom, raw)
@@ -88,6 +89,7 @@ pub(crate) enum InsertVars {
8889
/// # use sql_query_builder as sql;
8990
///
9091
/// let raw = "values ('foo', 'Foo')";
92+
///
9193
/// let insert_query = sql::Insert::new()
9294
/// .insert_into("users (login, name)")
9395
/// .raw_after(sql::InsertClause::InsertInto, raw)
@@ -132,6 +134,7 @@ pub struct Select {
132134
pub(crate) _raw: Vec<String>,
133135
pub(crate) _select: Vec<String>,
134136
pub(crate) _where: Vec<(LogicalOperator, String)>,
137+
pub(crate) _window: Vec<String>,
135138

136139
#[cfg(any(feature = "postgresql", feature = "sqlite"))]
137140
pub(crate) _except: Vec<Self>,
@@ -172,6 +175,7 @@ pub enum SelectClause {
172175
OrderBy,
173176
Select,
174177
Where,
178+
Window,
175179

176180
#[cfg(any(feature = "postgresql", feature = "sqlite"))]
177181
Except,
@@ -259,6 +263,7 @@ pub(crate) enum UpdateVars {
259263
/// # use sql_query_builder as sql;
260264
///
261265
/// let raw = "set name = 'Foo'";
266+
///
262267
/// let update_query = sql::Update::new()
263268
/// .update("users")
264269
/// .raw_after(sql::UpdateClause::Update, raw)

0 commit comments

Comments
 (0)