Skip to content

Commit 47de6f5

Browse files
committed
adds sqlite syntax
1 parent b3765b6 commit 47de6f5

28 files changed

+1755
-643
lines changed

.github/workflows/pull-requests.yml

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,18 @@ jobs:
1010
- uses: actions/checkout@v2
1111
- uses: actions-rs/toolchain@v1
1212
with:
13-
toolchain: stable
13+
toolchain: 1.62.0
1414
- uses: actions-rs/cargo@v1
15+
name: Test standard syntax
1516
with:
1617
command: test
1718
- uses: actions-rs/cargo@v1
19+
name: Test PostgreSQL syntax
1820
with:
1921
command: test
20-
args: --features postgresql --test feature_flag_postgresql
22+
args: --features postgresql
23+
- uses: actions-rs/cargo@v1
24+
name: Test SQLite syntax
25+
with:
26+
command: test
27+
args: --features sqlite

.vscode/extensions.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
{
22
"recommendations": [
3-
"rust-lang.rust-analyzer"
3+
"rust-lang.rust-analyzer",
4+
"serayuzgur.crates",
5+
"tamasfe.even-better-toml",
46
]
57
}

.vscode/settings.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@
1212
"rust-analyzer.diagnostics.disabled": [
1313
"inactive-code"
1414
],
15-
"rust-analyzer.cargo.features": [
16-
"postgresql"
15+
"rust-analyzer.cargo.features": [],
16+
"rust-analyzer.linkedProjects": [
17+
"./Cargo.toml"
1718
],
1819
}

Cargo.toml

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,18 @@ 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 = "1.1.4"
7+
version = "2.0.0"
88
edition = "2021"
9-
rust-version = "1.58"
9+
rust-version = "1.62"
1010
license = "MIT"
11-
keywords = ["sql", "query", "postgres"]
11+
keywords = ["sql", "query", "postgres", "sqlite"]
1212

1313
[features]
1414
postgresql = []
15+
sqlite = []
1516

1617
[package.metadata.docs.rs]
17-
features = ["postgresql"]
18+
features = ["postgresql", "sqlite"]
1819

1920
[dev-dependencies]
20-
pretty_assertions = "1.2.1"
21+
pretty_assertions = "1.4.0"

README.md

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,14 @@ SELECT id, login FROM users WHERE login = $1 AND is_admin = true
3636

3737
SQL Query Builder comes with the following optional features:
3838
- `postgresql` enable Postgres syntax
39+
- `sqlite` enable SQLite syntax
3940

4041
You can enable features like
4142

4243
```toml
4344
## Cargo.toml
4445

45-
sql_query_builder = { version = "1.x.x", features = ["postgresql"] }
46+
sql_query_builder = { version = "2.x.x", features = ["postgresql"] }
4647
```
4748

4849

@@ -68,7 +69,7 @@ let select = sql::Select::new()
6869

6970
Methods like `limit` and `offset` will override the previous value, the two select is equivalent
7071

71-
```text
72+
```ts
7273
use sql_query_builder as sql;
7374

7475
let select = sql::Select::new()
@@ -154,7 +155,7 @@ let query = Some(sql::Select::new())
154155
println!("{}", query);
155156
```
156157

157-
Output (indented for redability)
158+
Output (indented for readability)
158159

159160
```sql
160161
SELECT u.id, u.name as user_name, u.login, a.name as address_name, o.name as product_name
@@ -167,7 +168,7 @@ WHERE u.login = $1 AND o.id = $2
167168

168169
## Raw queries
169170

170-
You can use the raw method to accomplish some edge cases that are hard to rewrite into the Select syntax.
171+
You can use the raw method to reach some edge cases that are hard to rewrite into the Select syntax.
171172
The `select.raw()` method will put any SQL you define on top of the output
172173

173174
```rust
@@ -213,7 +214,7 @@ let select = sql::Select::new()
213214

214215
## Debugging queries
215216

216-
Sometimes it's more ease just print de current state of the query builder, to do this just add the .debug() method at any part of the builder, note that the where clause will not be printed because the debug was added before
217+
Sometimes it's more ease just print de current state of the query builder, to do so adds the `.debug()` method anywhere in the builder. In the example below, the where clause will not be printed because the debug was added before the clause
217218

218219
```rust
219220
use sql_query_builder as sql;
@@ -228,8 +229,10 @@ let mut select = sql::Select::new()
228229
Output
229230

230231
```sql
232+
-- ------------------------------------------------------------------------------
231233
SELECT id, login
232234
FROM users
235+
-- ------------------------------------------------------------------------------
233236
```
234237

235238
See the [documentation](https://docs.rs/sql_query_builder/) for more builders like [Insert](https://docs.rs/sql_query_builder/latest/sql_query_builder/struct.Insert.html), [Update](https://docs.rs/sql_query_builder/latest/sql_query_builder/struct.Update.html) and [Delete](https://docs.rs/sql_query_builder/latest/sql_query_builder/struct.Delete.html)

scripts/coverage_test.sh

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,11 @@ COVERAGE_TARGET="target/coverage"
1111
rm -fr "$COVERAGE_TARGET"
1212
mkdir -p "$COVERAGE_OUTPUT"
1313
mkdir -p "$COVERAGE_TARGET"
14+
clear
1415

1516
RUSTFLAGS="-C instrument-coverage" LLVM_PROFILE_FILE="$COVERAGE_TARGET/$PKG_NAME-%m.profraw" cargo test --target-dir $COVERAGE_TARGET;
16-
RUSTFLAGS="-C instrument-coverage" LLVM_PROFILE_FILE="$COVERAGE_TARGET/$PKG_NAME-%m.profraw" cargo test --target-dir $COVERAGE_TARGET --features postgresql --test feature_flag_postgresql;
17+
RUSTFLAGS="-C instrument-coverage" LLVM_PROFILE_FILE="$COVERAGE_TARGET/$PKG_NAME-%m.profraw" cargo test --target-dir $COVERAGE_TARGET --features postgresql;
18+
RUSTFLAGS="-C instrument-coverage" LLVM_PROFILE_FILE="$COVERAGE_TARGET/$PKG_NAME-%m.profraw" cargo test --target-dir $COVERAGE_TARGET --features sqlite;
1719

1820
cargo profdata -- merge -sparse $COVERAGE_TARGET/$PKG_NAME-*.profraw -o $COVERAGE_TARGET/$PKG_NAME.profdata;
1921

scripts/test.sh

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,5 @@
22

33
clear
44
cargo test
5-
cargo test --features postgresql --test feature_flag_postgresql
5+
cargo test --features postgresql
6+
cargo test --features sqlite

scripts/watch_test.sh

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,21 @@
33
# Prerequisites
44
# cargo install cargo-watch
55

6+
# Usage
7+
# ./scripts/watch_test.sh # will run without enable feature
8+
# ./scripts/watch_test.sh all # will enable all feature
9+
# ./scripts/watch_test.sh postgresql # will enable only the postgresql feature
10+
11+
all_features='postgresql sqlite'
12+
features=''
13+
14+
case "$@" in
15+
"") features="";;
16+
"all") features="$all_features";;
17+
*) features="$@";;
18+
esac
19+
20+
[ ! -z "$features" ] && features="--features $features"
21+
622
# cargo watch -w ./src -w ./tests -x 'test --features postgresql -- --nocapture --color always'
7-
cargo watch -w ./src -w ./tests -x 'test --features postgresql'
23+
cargo watch -w ./src -w ./tests -x "test $features"

src/behavior.rs

Lines changed: 102 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
use crate::fmt;
2+
#[cfg(feature = "sqlite")]
3+
use crate::structure::{InsertClause, InsertVars, UpdateClause, UpdateVars};
24
use std::cmp::PartialEq;
35

46
pub trait Concat {
@@ -78,8 +80,8 @@ pub trait ConcatSqlStandard<Clause: PartialEq> {
7880
}
7981
}
8082

81-
#[cfg(feature = "postgresql")]
82-
pub trait ConcatPostgres<Clause: PartialEq> {
83+
#[cfg(any(feature = "postgresql", feature = "sqlite"))]
84+
pub trait ConcatCommon<Clause: PartialEq> {
8385
fn concat_returning(
8486
&self,
8587
items_raw_before: &Vec<(Clause, String)>,
@@ -142,6 +144,104 @@ pub trait ConcatPostgres<Clause: PartialEq> {
142144
}
143145
}
144146

147+
#[cfg(feature = "sqlite")]
148+
pub trait ConcatSqlite {
149+
fn concat_insert(
150+
&self,
151+
items_raw_before: &Vec<(InsertClause, String)>,
152+
items_raw_after: &Vec<(InsertClause, String)>,
153+
query: String,
154+
fmts: &fmt::Formatter,
155+
insert: &(InsertVars, String),
156+
) -> String {
157+
let fmt::Formatter { lb, space, .. } = fmts;
158+
159+
let (clause, sql) = match insert {
160+
(InsertVars::InsertInto, exp) if exp.is_empty() => (InsertClause::InsertInto, "".to_owned()),
161+
(InsertVars::InsertInto, exp) => (InsertClause::InsertInto, format!("INSERT INTO{space}{exp}{space}{lb}")),
162+
163+
(InsertVars::InsertOr, exp) if exp.is_empty() => (InsertClause::InsertOr, "".to_owned()),
164+
(InsertVars::InsertOr, exp) => (InsertClause::InsertOr, format!("INSERT OR{space}{exp}{space}{lb}")),
165+
166+
(InsertVars::ReplaceInto, exp) if exp.is_empty() => (InsertClause::ReplaceInto, "".to_owned()),
167+
(InsertVars::ReplaceInto, exp) => (
168+
InsertClause::ReplaceInto,
169+
format!("REPLACE INTO{space}{exp}{space}{lb}"),
170+
),
171+
};
172+
173+
concat_raw_before_after(items_raw_before, items_raw_after, query, fmts, clause, sql)
174+
}
175+
176+
fn concat_join<Clause: PartialEq>(
177+
&self,
178+
items_raw_before: &Vec<(Clause, String)>,
179+
items_raw_after: &Vec<(Clause, String)>,
180+
query: String,
181+
fmts: &fmt::Formatter,
182+
clause: Clause,
183+
join: &Vec<String>,
184+
) -> String {
185+
let fmt::Formatter { lb, space, .. } = fmts;
186+
let sql = if join.is_empty() == false {
187+
let joins = join.join(format!("{space}{lb}").as_str());
188+
format!("{joins}{space}{lb}")
189+
} else {
190+
"".to_owned()
191+
};
192+
193+
concat_raw_before_after(&items_raw_before, &items_raw_after, query, fmts, clause, sql)
194+
}
195+
196+
fn concat_update(
197+
&self,
198+
items_raw_before: &Vec<(UpdateClause, String)>,
199+
items_raw_after: &Vec<(UpdateClause, String)>,
200+
query: String,
201+
fmts: &fmt::Formatter,
202+
update: &(UpdateVars, String),
203+
) -> String {
204+
let fmt::Formatter { lb, space, .. } = fmts;
205+
let (clause, sql) = match update {
206+
(UpdateVars::Update, table_name) if table_name.is_empty() => (UpdateClause::Update, "".to_string()),
207+
(UpdateVars::Update, table_name) => (UpdateClause::Update, format!("UPDATE{space}{table_name}{space}{lb}")),
208+
209+
(UpdateVars::UpdateOr, expression) if expression.is_empty() => (UpdateClause::UpdateOr, "".to_string()),
210+
(UpdateVars::UpdateOr, expression) => (
211+
UpdateClause::UpdateOr,
212+
format!("UPDATE OR{space}{expression}{space}{lb}"),
213+
),
214+
};
215+
216+
concat_raw_before_after(items_raw_before, items_raw_after, query, fmts, clause, sql)
217+
}
218+
219+
fn concat_values<Clause: PartialEq>(
220+
&self,
221+
items_raw_before: &Vec<(Clause, String)>,
222+
items_raw_after: &Vec<(Clause, String)>,
223+
query: String,
224+
fmts: &fmt::Formatter,
225+
clause: Clause,
226+
values: &Vec<String>,
227+
default_values: &bool,
228+
) -> String {
229+
let fmt::Formatter { comma, lb, space, .. } = fmts;
230+
231+
let sql = if *default_values {
232+
format!("DEFAULT VALUES{space}{lb}")
233+
} else if values.is_empty() == false {
234+
let sep = format!("{comma}{lb}");
235+
let values = values.join(&sep);
236+
format!("VALUES{space}{lb}{values}{space}{lb}")
237+
} else {
238+
"".to_owned()
239+
};
240+
241+
concat_raw_before_after(items_raw_before, items_raw_after, query, fmts, clause, sql)
242+
}
243+
}
244+
145245
/// Represents all commands that can be used in a transaction
146246
pub trait TransactionQuery: Concat {}
147247

src/delete/delete.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ use crate::{
44
structure::{Delete, DeleteClause},
55
};
66

7+
impl WithQuery for Delete {}
8+
9+
impl TransactionQuery for Delete {}
10+
711
impl Delete {
812
/// The same as [where_clause](Delete::where_clause) method, useful to write more idiomatic SQL query
913
///
@@ -197,19 +201,19 @@ impl Delete {
197201
}
198202
}
199203

200-
#[cfg(any(doc, feature = "postgresql"))]
204+
#[cfg(any(doc, feature = "postgresql", feature = "sqlite"))]
201205
impl Delete {
202-
/// The `returning` clause, this method can be used enabling the feature flag `postgresql`
206+
/// The `returning` clause, this method can be used enabling a feature flag
203207
pub fn returning(mut self, output_name: &str) -> Self {
204208
push_unique(&mut self._returning, output_name.trim().to_owned());
205209
self
206210
}
207211

208-
/// The `with` clause, this method can be used enabling the feature flag `postgresql`
212+
/// The `with` clause, this method can be used enabling a feature flag
209213
///
210214
/// # Example
211215
///
212-
/// ```text
216+
/// ```ts
213217
/// use sql_query_builder as sql;
214218
///
215219
/// let deactivated_users = sql::Select::new().select("id").from("users").where_clause("ative = false");
@@ -237,10 +241,6 @@ impl Delete {
237241
}
238242
}
239243

240-
impl WithQuery for Delete {}
241-
242-
impl TransactionQuery for Delete {}
243-
244244
impl std::fmt::Display for Delete {
245245
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
246246
write!(f, "{}", self.as_string())

src/delete/delete_internal.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
#[cfg(feature = "postgresql")]
2-
use crate::behavior::ConcatPostgres;
1+
#[cfg(any(feature = "postgresql", feature = "sqlite"))]
2+
use crate::behavior::ConcatCommon;
33
use crate::{
44
behavior::{concat_raw_before_after, Concat, ConcatSqlStandard},
55
fmt,
@@ -8,9 +8,6 @@ use crate::{
88

99
impl ConcatSqlStandard<DeleteClause> for Delete {}
1010

11-
#[cfg(feature = "postgresql")]
12-
impl ConcatPostgres<DeleteClause> for Delete {}
13-
1411
impl Delete {
1512
fn concat_delete_from(&self, query: String, fmts: &fmt::Formatter) -> String {
1613
let fmt::Formatter { lb, space, .. } = fmts;
@@ -37,7 +34,7 @@ impl Concat for Delete {
3734
let mut query = "".to_owned();
3835

3936
query = self.concat_raw(query, &fmts, &self._raw);
40-
#[cfg(feature = "postgresql")]
37+
#[cfg(any(feature = "postgresql", feature = "sqlite"))]
4138
{
4239
query = self.concat_with(
4340
&self._raw_before,
@@ -57,7 +54,7 @@ impl Concat for Delete {
5754
DeleteClause::Where,
5855
&self._where,
5956
);
60-
#[cfg(feature = "postgresql")]
57+
#[cfg(any(feature = "postgresql", feature = "sqlite"))]
6158
{
6259
query = self.concat_returning(
6360
&self._raw_before,
@@ -72,3 +69,6 @@ impl Concat for Delete {
7269
query.trim_end().to_owned()
7370
}
7471
}
72+
73+
#[cfg(any(feature = "postgresql", feature = "sqlite"))]
74+
impl ConcatCommon<DeleteClause> for Delete {}

0 commit comments

Comments
 (0)