136 lines
4.0 KiB
Markdown
136 lines
4.0 KiB
Markdown
### todo
|
||
- [*] 使用Extractor方式提取数据,包括Body、Query和Path
|
||
- [ ] multipart/form-data的实现
|
||
- [*] 参考example中的jwt实现方式,移除context对extension的依赖?那么language-tag该怎么处理?
|
||
- [ ] 参考rocket,移除参数的元组类型
|
||
- [-] 能否自定义实现宏路由
|
||
- [*] 定向路由的实现
|
||
- [*] 支持多种method的路由
|
||
- [ ] 宏路由支持fallback等
|
||
|
||
|
||
### note
|
||
- 展开宏:cargo expand --manifest-path .\server\Cargo.toml controller::feedback_controller
|
||
|
||
### sqlx type
|
||
注意:sqlx feature里面time和chrono选择一个即可
|
||
https://docs.rs/sqlx/latest/sqlx/postgres/types/index.html
|
||
|
||
https://sqlx.dev/
|
||
|
||
### 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);
|
||
``` |