Skip to content

Commit 43f90a7

Browse files
committed
Simplified select builder
1 parent 4c6d29d commit 43f90a7

2 files changed

Lines changed: 84 additions & 148 deletions

File tree

src/lib.rs

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -69,15 +69,15 @@ use crate::insert::{Insert, InsertData, InsertImpl};
6969
use crate::join_table::{JoinTableData, JoinTableImpl, JoinType};
7070
use crate::on_conflict::OnConflict;
7171
use crate::ordering::OrderByEntry;
72-
use crate::select::{Select, SelectData, SelectImpl};
72+
use crate::select::Select;
7373
use crate::select_column::{SelectColumnData, SelectColumnImpl};
7474
use crate::update::{Update, UpdateData, UpdateImpl};
7575
use crate::value::Value;
7676

7777
/**
7878
The main interface for creating sql strings
7979
*/
80-
#[derive(Copy, Clone)]
80+
#[derive(Copy, Clone, Debug)]
8181
pub enum DBImpl {
8282
/// Implementation of SQLite
8383
#[cfg(feature = "sqlite")]
@@ -296,23 +296,17 @@ impl DBImpl {
296296
from_clause: &'until_build str,
297297
joins: &'until_build [JoinTableImpl<'until_build, 'post_build>],
298298
order_by_clause: &'until_build [OrderByEntry<'until_build>],
299-
) -> impl Select<'until_build, 'post_build> {
300-
let d = SelectData {
299+
) -> Select<'until_build, 'post_build> {
300+
Select {
301+
db_impl: *self,
301302
join_tables: joins,
302303
resulting_columns: columns,
303304
limit: None,
304305
offset: None,
305306
from_clause,
306307
where_clause: None,
307308
distinct: false,
308-
lookup: vec![],
309309
order_by_clause,
310-
};
311-
match self {
312-
#[cfg(feature = "sqlite")]
313-
DBImpl::SQLite => SelectImpl::SQLite(d),
314-
#[cfg(feature = "postgres")]
315-
DBImpl::Postgres => SelectImpl::Postgres(d),
316310
}
317311
}
318312

src/select.rs

Lines changed: 79 additions & 137 deletions
Original file line numberDiff line numberDiff line change
@@ -7,141 +7,85 @@ use crate::ordering::{OrderByEntry, Ordering};
77
use crate::select_column::{SelectColumn, SelectColumnImpl};
88
use crate::{DBImpl, Value};
99

10-
/**
11-
Trait representing a select builder.
12-
*/
13-
pub trait Select<'until_build, 'post_query> {
14-
/**
15-
Set a limit to the resulting rows.
16-
*/
17-
fn limit_clause(self, limit: LimitClause) -> Self;
18-
19-
/**
20-
Only retrieve distinct rows.
21-
*/
22-
fn distinct(self) -> Self;
23-
24-
/**
25-
Set a where clause to the query.
26-
*/
27-
fn where_clause(self, where_clause: &'until_build Condition<'post_query>) -> Self;
28-
29-
/**
30-
Build the select query
31-
*/
32-
fn build(self) -> (String, Vec<Value<'post_query>>);
33-
}
34-
35-
/**
36-
Representation of the data of a SELECT operation in SQL.
37-
*/
10+
/// Select builder
11+
///
12+
/// Can be constructed via [`DBImpl::select`]
3813
#[derive(Debug)]
39-
pub struct SelectData<'until_build, 'post_query> {
14+
pub struct Select<'until_build, 'post_query> {
15+
// Set on construction
16+
pub(crate) db_impl: DBImpl,
4017
pub(crate) resulting_columns: &'until_build [SelectColumnImpl<'until_build>],
41-
pub(crate) limit: Option<u64>,
42-
pub(crate) offset: Option<u64>,
4318
pub(crate) from_clause: &'until_build str,
44-
pub(crate) where_clause: Option<&'until_build Condition<'post_query>>,
45-
pub(crate) distinct: bool,
46-
pub(crate) lookup: Vec<Value<'post_query>>,
4719
pub(crate) join_tables: &'until_build [JoinTableImpl<'until_build, 'post_query>],
48-
pub(crate) order_by_clause: &'until_build [OrderByEntry<'until_build>],
49-
}
50-
51-
/**
52-
Implementation of the [Select] trait for the different implementations.
20+
pub(crate) where_clause: Option<&'until_build Condition<'post_query>>,
5321

54-
Should only be constructed via [DBImpl::select]
55-
*/
56-
#[derive(Debug)]
57-
pub enum SelectImpl<'until_build, 'post_query> {
58-
/**
59-
SQLite representation of the SELECT operation.
60-
*/
61-
#[cfg(feature = "sqlite")]
62-
SQLite(SelectData<'until_build, 'post_query>),
63-
/**
64-
Postgres representation of the SELECT operation.
65-
*/
66-
#[cfg(feature = "postgres")]
67-
Postgres(SelectData<'until_build, 'post_query>),
22+
// Set by builder
23+
pub(crate) order_by_clause: &'until_build [OrderByEntry<'until_build>],
24+
pub(crate) distinct: bool,
25+
pub(crate) limit: Option<u64>,
26+
pub(crate) offset: Option<u64>,
6827
}
6928

70-
impl<'until_build, 'post_build> Select<'until_build, 'post_build>
71-
for SelectImpl<'until_build, 'post_build>
72-
{
73-
fn limit_clause(mut self, limit: LimitClause) -> Self {
74-
match self {
75-
#[cfg(feature = "sqlite")]
76-
SelectImpl::SQLite(ref mut d) => {
77-
d.limit = Some(limit.limit);
78-
d.offset = limit.offset;
79-
}
80-
#[cfg(feature = "postgres")]
81-
SelectImpl::Postgres(ref mut d) => {
82-
d.limit = Some(limit.limit);
83-
d.offset = limit.offset;
84-
}
85-
};
29+
impl<'until_build, 'post_build> Select<'until_build, 'post_build> {
30+
/// Set a limit to the resulting rows.
31+
pub fn limit_clause(mut self, limit: LimitClause) -> Self {
32+
self.limit = Some(limit.limit);
33+
self.offset = limit.offset;
8634
self
8735
}
8836

89-
fn distinct(mut self) -> Self {
90-
match self {
91-
#[cfg(feature = "sqlite")]
92-
SelectImpl::SQLite(ref mut d) => d.distinct = true,
93-
#[cfg(feature = "postgres")]
94-
SelectImpl::Postgres(ref mut d) => d.distinct = true,
95-
};
37+
/// Only retrieve distinct rows.
38+
pub fn distinct(mut self) -> Self {
39+
self.distinct = true;
9640
self
9741
}
9842

99-
fn where_clause(mut self, where_clause: &'until_build Condition<'post_build>) -> Self {
100-
match self {
101-
#[cfg(feature = "sqlite")]
102-
SelectImpl::SQLite(ref mut d) => d.where_clause = Some(where_clause),
103-
#[cfg(feature = "postgres")]
104-
SelectImpl::Postgres(ref mut d) => d.where_clause = Some(where_clause),
105-
};
43+
/// Set a where clause to the query.
44+
pub fn where_clause(mut self, where_clause: &'until_build Condition<'post_build>) -> Self {
45+
self.where_clause = Some(where_clause);
10646
self
10747
}
10848

109-
fn build(self) -> (String, Vec<Value<'post_build>>) {
110-
match self {
49+
/// Build the select query
50+
pub fn build(self) -> (String, Vec<Value<'post_build>>) {
51+
let mut sql;
52+
let mut values = Vec::new();
53+
54+
match self.db_impl {
11155
#[cfg(feature = "sqlite")]
112-
SelectImpl::SQLite(mut d) => {
113-
let mut s = format!("SELECT{} ", if d.distinct { " DISTINCT" } else { "" });
56+
DBImpl::SQLite => {
57+
sql = format!("SELECT{} ", if self.distinct { " DISTINCT" } else { "" });
11458

115-
let column_len = d.resulting_columns.len();
116-
for (idx, column) in d.resulting_columns.iter().enumerate() {
117-
column.build(&mut s);
59+
let column_len = self.resulting_columns.len();
60+
for (idx, column) in self.resulting_columns.iter().enumerate() {
61+
column.build(&mut sql);
11862

11963
if idx != column_len - 1 {
120-
write!(s, ", ").unwrap();
64+
write!(sql, ", ").unwrap();
12165
}
12266
}
12367

124-
write!(s, " FROM \"{}\"", d.from_clause).unwrap();
68+
write!(sql, " FROM \"{}\"", self.from_clause).unwrap();
12569

126-
for x in d.join_tables {
127-
write!(s, " ").unwrap();
128-
x.build(&mut s, &mut d.lookup);
70+
for x in self.join_tables {
71+
write!(sql, " ").unwrap();
72+
x.build(&mut sql, &mut values);
12973
}
13074

131-
if let Some(c) = d.where_clause {
132-
write!(s, " WHERE {}", c.build(DBImpl::SQLite, &mut d.lookup)).unwrap()
75+
if let Some(c) = self.where_clause {
76+
write!(sql, " WHERE {}", c.build(DBImpl::SQLite, &mut values)).unwrap()
13377
};
13478

135-
if !d.order_by_clause.is_empty() {
136-
write!(s, " ORDER BY ").unwrap();
79+
if !self.order_by_clause.is_empty() {
80+
write!(sql, " ORDER BY ").unwrap();
13781

138-
let order_by_len = d.order_by_clause.len();
139-
for (idx, entry) in d.order_by_clause.iter().enumerate() {
82+
let order_by_len = self.order_by_clause.len();
83+
for (idx, entry) in self.order_by_clause.iter().enumerate() {
14084
if let Some(table_name) = entry.table_name {
141-
write!(s, "{table_name}.").unwrap();
85+
write!(sql, "{table_name}.").unwrap();
14286
};
14387
write!(
144-
s,
88+
sql,
14589
"{}{}",
14690
entry.column_name,
14791
match entry.ordering {
@@ -152,56 +96,54 @@ impl<'until_build, 'post_build> Select<'until_build, 'post_build>
15296
.unwrap();
15397

15498
if idx != order_by_len - 1 {
155-
write!(s, ", ").unwrap();
99+
write!(sql, ", ").unwrap();
156100
}
157101
}
158102
};
159103

160-
if let Some(limit) = d.limit {
161-
write!(s, " LIMIT {limit}").unwrap();
162-
if let Some(offset) = d.offset {
163-
write!(s, " OFFSET {offset}").unwrap();
104+
if let Some(limit) = self.limit {
105+
write!(sql, " LIMIT {limit}").unwrap();
106+
if let Some(offset) = self.offset {
107+
write!(sql, " OFFSET {offset}").unwrap();
164108
}
165109
};
166110

167-
write!(s, ";").unwrap();
168-
169-
(s, d.lookup)
111+
write!(sql, ";").unwrap();
170112
}
171113
#[cfg(feature = "postgres")]
172-
SelectImpl::Postgres(mut d) => {
173-
let mut s = format!("SELECT{} ", if d.distinct { " DISTINCT" } else { "" });
114+
DBImpl::Postgres => {
115+
sql = format!("SELECT{} ", if self.distinct { " DISTINCT" } else { "" });
174116

175-
let column_len = d.resulting_columns.len();
176-
for (idx, column) in d.resulting_columns.iter().enumerate() {
177-
column.build(&mut s);
117+
let column_len = self.resulting_columns.len();
118+
for (idx, column) in self.resulting_columns.iter().enumerate() {
119+
column.build(&mut sql);
178120

179121
if idx != column_len - 1 {
180-
write!(s, ", ").unwrap();
122+
write!(sql, ", ").unwrap();
181123
}
182124
}
183125

184-
write!(s, " FROM \"{}\"", d.from_clause).unwrap();
126+
write!(sql, " FROM \"{}\"", self.from_clause).unwrap();
185127

186-
for x in d.join_tables {
187-
write!(s, " ").unwrap();
188-
x.build(&mut s, &mut d.lookup);
128+
for x in self.join_tables {
129+
write!(sql, " ").unwrap();
130+
x.build(&mut sql, &mut values);
189131
}
190132

191-
if let Some(c) = d.where_clause {
192-
write!(s, " WHERE {}", c.build(DBImpl::Postgres, &mut d.lookup)).unwrap()
133+
if let Some(c) = self.where_clause {
134+
write!(sql, " WHERE {}", c.build(DBImpl::Postgres, &mut values)).unwrap()
193135
};
194136

195-
if !d.order_by_clause.is_empty() {
196-
write!(s, " ORDER BY ").unwrap();
137+
if !self.order_by_clause.is_empty() {
138+
write!(sql, " ORDER BY ").unwrap();
197139

198-
let order_by_len = d.order_by_clause.len();
199-
for (idx, entry) in d.order_by_clause.iter().enumerate() {
140+
let order_by_len = self.order_by_clause.len();
141+
for (idx, entry) in self.order_by_clause.iter().enumerate() {
200142
if let Some(table_name) = entry.table_name {
201-
write!(s, "\"{table_name}\".").unwrap();
143+
write!(sql, "\"{table_name}\".").unwrap();
202144
};
203145
write!(
204-
s,
146+
sql,
205147
"\"{}\"{}",
206148
entry.column_name,
207149
match entry.ordering {
@@ -212,22 +154,22 @@ impl<'until_build, 'post_build> Select<'until_build, 'post_build>
212154
.unwrap();
213155

214156
if idx != order_by_len - 1 {
215-
write!(s, ", ").unwrap();
157+
write!(sql, ", ").unwrap();
216158
}
217159
}
218160
};
219161

220-
if let Some(limit) = d.limit {
221-
write!(s, " LIMIT {limit}").unwrap();
222-
if let Some(offset) = d.offset {
223-
write!(s, " OFFSET {offset}").unwrap();
162+
if let Some(limit) = self.limit {
163+
write!(sql, " LIMIT {limit}").unwrap();
164+
if let Some(offset) = self.offset {
165+
write!(sql, " OFFSET {offset}").unwrap();
224166
}
225167
};
226168

227-
write!(s, ";").unwrap();
228-
229-
(s, d.lookup)
169+
write!(sql, ";").unwrap();
230170
}
231171
}
172+
173+
(sql, values)
232174
}
233175
}

0 commit comments

Comments
 (0)