添加sqlx动态查询说明
This commit is contained in:
parent
274ef8b68d
commit
7fb6d5893d
119
README.MD
119
README.MD
@ -11,4 +11,121 @@
|
||||
|
||||
|
||||
### note
|
||||
- 展开宏:cargo expand --manifest-path .\server\Cargo.toml controller::feedback_controller
|
||||
- 展开宏:cargo expand --manifest-path .\server\Cargo.toml controller::feedback_controller
|
||||
|
||||
### sql dynamic query
|
||||
https://github.com/launchbadge/sqlx/blob/main/FAQ.md#how-can-i-bind-an-array-to-a-values-clause-how-can-i-do-bulk-inserts
|
||||
```rust
|
||||
use sqlx::{query_builder::QueryBuilder, Execute};
|
||||
|
||||
struct Search {
|
||||
id: i64,
|
||||
username: Option<String>,
|
||||
min_age: Option<i8>,
|
||||
max_age: Option<i8>,
|
||||
}
|
||||
|
||||
fn search_query(search: Search) -> String {
|
||||
let mut query = QueryBuilder::new("SELECT * from users where id = ");
|
||||
query.push_bind(search.id);
|
||||
|
||||
if let Some(username) = search.username {
|
||||
query.push(" AND username = ");
|
||||
query.push_bind(username);
|
||||
}
|
||||
|
||||
if let Some(min_age) = search.min_age {
|
||||
query.push(" AND age > ");
|
||||
query.push_bind(min_age);
|
||||
}
|
||||
|
||||
if let Some(max_age) = search.max_age {
|
||||
query.push(" AND age < ");
|
||||
query.push_bind(max_age);
|
||||
}
|
||||
|
||||
query.build().sql().into()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
dbg!(search_query(Search {
|
||||
id: 12,
|
||||
username: None,
|
||||
min_age: None,
|
||||
max_age: None,
|
||||
})); // "SELECT * from users where id = $1"
|
||||
dbg!(search_query(Search {
|
||||
id: 12,
|
||||
username: Some("Bob".into()),
|
||||
min_age: None,
|
||||
max_age: None,
|
||||
})); // "SELECT * from users where id = $1 AND username = $2"
|
||||
dbg!(search_query(Search {
|
||||
id: 12,
|
||||
username: Some("Bob".into()),
|
||||
min_age: Some(10),
|
||||
max_age: Some(70),
|
||||
})); // "SELECT * from users where id = $1 AND username = $2 AND age > $3 AND age < $4"
|
||||
}
|
||||
```
|
||||
|
||||
```rust
|
||||
use sqlx::{Execute, MySql, QueryBuilder};
|
||||
|
||||
struct User {
|
||||
id: i32,
|
||||
username: String,
|
||||
email: String,
|
||||
password: String,
|
||||
}
|
||||
|
||||
// The number of parameters in MySQL must fit in a `u16`.
|
||||
const BIND_LIMIT: usize = 65535;
|
||||
|
||||
// This would normally produce values forever!
|
||||
let users = (0..).map(|i| User {
|
||||
id: i,
|
||||
username: format!("test_user_{i}"),
|
||||
email: format!("test-user-{i}@example.com"),
|
||||
password: format!("Test!User@Password#{i}"),
|
||||
});
|
||||
|
||||
let mut query_builder: QueryBuilder<MySql> = QueryBuilder::new(
|
||||
// Note the trailing space; most calls to `QueryBuilder` don't automatically insert
|
||||
// spaces as that might interfere with identifiers or quoted strings where exact
|
||||
// values may matter.
|
||||
"INSERT INTO users(id, username, email, password) "
|
||||
);
|
||||
|
||||
// Note that `.into_iter()` wasn't needed here since `users` is already an iterator.
|
||||
query_builder.push_values(users.take(BIND_LIMIT / 4), |mut b, user| {
|
||||
// If you wanted to bind these by-reference instead of by-value,
|
||||
// you'd need an iterator that yields references that live as long as `query_builder`,
|
||||
// e.g. collect it to a `Vec` first.
|
||||
b.push_bind(user.id)
|
||||
.push_bind(user.username)
|
||||
.push_bind(user.email)
|
||||
.push_bind(user.password);
|
||||
});
|
||||
|
||||
let mut query = query_builder.build();
|
||||
|
||||
// You can then call `query.execute()`, `.fetch_one()`, `.fetch_all()`, etc.
|
||||
// For the sake of demonstration though, we're just going to assert the contents
|
||||
// of the query.
|
||||
|
||||
// These are methods of the `Execute` trait, not normally meant to be called in user code.
|
||||
let sql = query.sql();
|
||||
let arguments = query.take_arguments().unwrap();
|
||||
|
||||
assert!(sql.starts_with(
|
||||
"INSERT INTO users(id, username, email, password) VALUES (?, ?, ?, ?), (?, ?, ?, ?)"
|
||||
));
|
||||
|
||||
assert!(sql.ends_with("(?, ?, ?, ?)"));
|
||||
|
||||
// Not a normally exposed function, only used for this doctest.
|
||||
// 65535 / 4 = 16383 (rounded down)
|
||||
// 16383 * 4 = 65532
|
||||
assert_eq!(arguments.len(), 65532);
|
||||
```
|
Loading…
Reference in New Issue
Block a user