添加sqlx动态查询说明

This commit is contained in:
liyunjia 2024-10-11 19:11:16 +08:00
parent 274ef8b68d
commit 7fb6d5893d

119
README.MD
View File

@ -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);
```