我想设置一个接受 SQLx PgPool或MySqlPool的通用函数。
use dotenv::dotenv;
use sqlx::postgres::PgPool;
use sqlx::{Pool, Database};
use std::env;
#[derive(Debug)]
struct Todo {
id: i64,
description: String,
done: bool,
}
#[actix_web::main]
async fn main() -> anyhow::Result<()> {
dotenv().ok();
let pool = PgPool::connect(&env::var("DATABASE_URL")?).await?;
list_todos(&pool).await?;
Ok(())
}
async fn list_todos<D: Database>(pool: &Pool<D>) -> anyhow::Result<Vec<Todo>> {
let todos = sqlx::query_as!(
Todo,
r#"
SELECT id, description, done
FROM todos
ORDER BY id
"#
)
.fetch_all(pool)
.await?;
Ok(todos)
}
Run Code Online (Sandbox Code Playgroud)
我看到的错误是:
32 | .fetch_all(pool)
| ^^^^^^^^^ expected type parameter `D`, …Run Code Online (Sandbox Code Playgroud) 我使用脚本循环请求时sqlx报错
“等待打开连接时池超时”
这个池在下面
Pool { size: 5, num_idle: 5, is_closed: false, options: PoolOptions { max_connections: 5, min_connections: 0, connect_timeout: 30s, max_lifetime: Some(1800s), idle_timeout: Some(600s), test_before_acquire: true } }
Run Code Online (Sandbox Code Playgroud)
这是我的代码
#[derive(Serialize)]
struct JsonResp {
id: i32
}
#[derive(Clone)]
struct AppState {
pub pool: MySqlPool
}
#[async_std::main]
async fn main() -> tide::Result<()> {
let pool = MySqlPoolOptions::new()
.max_connections(5)
.connect("mysql://root:123456@localhost:3306/blog").await?;
println!("{:?}", pool);
let app_state = AppState { pool: pool };
let mut app = tide::with_state(app_state);
app.at("/test").get(test);
app.listen("127.0.0.1:8080").await?;
Ok(())
}
async fn …Run Code Online (Sandbox Code Playgroud) 我正在尝试从 rusqlite => sqlx 进行转换。
通过调用 SQLite::open 打开连接rusqlite并创建数据库文件。以下作品:
use rusqlite::Connection;
Connection::open(db_filename)
Run Code Online (Sandbox Code Playgroud)
但是,我正在关注 sqlx 方面的文档(https://github.com/launchbadge/sqlx#connecting),他们立即让我创建一个池:
use sqlx::sqlite::{SqlitePoolOptions};
SqlitePoolOptions::new()
.max_connections(1)
.connect(&format!("sqlite://{}", db_filename))
.await
.map_err(|err| format!("{}\nfile: {}", err.to_string(), db_filename))?;
Run Code Online (Sandbox Code Playgroud)
这实际上产生了Result<_, String>这样的信息:
Error: "error returned from database: unable to open database file\nfile: /path/to/my.db"
Run Code Online (Sandbox Code Playgroud)
我不清楚如何sqlx在第一次启动时实际写入这些数据库文件。
尖端?
上下文:rust、sqlx 库
问题:如何在不丢失类型检查的情况下从较小的部分组成类似的查询?
macro_rules! select {
() => {"select col from tab"}
}
macro_rules! guard1 {
() => {"where col > 1"}
}
macro_rules! guard2 {
() => {"where col > 2"}
}
let mut conn = get_pg_connection_from_somewhere();
if some_condition() {
sqlx::query!(select!() + guard1!()).fetch_all(&mut conn).await?;
} else {
sqlx::query!(select!() + guard2!()).fetch_all(&mut conn).await?;
}
Run Code Online (Sandbox Code Playgroud)
文档说:
查询必须是字符串文字,或使用 + 连接字符串文字(对于宏生成的查询很有用),否则它无法进行内省(因此不能是动态的或另一个宏的结果)。
你可以看到它说“对于宏生成的查询有用”(尽管后来“不能是另一个宏的结果”)
我想解决的问题是,根据条件,我想运行不同但相似的(例如它们都具有相同的列)查询,并且我想从较小的可重用部分组成查询[
我正在尝试使用 SQLX 来开发 Rust 应用程序服务器作为后端存储。它适用于具有一些特殊默认行为的原始 CMS,即:如果找不到页面,则自动生成带有一些空白内容的页面。我希望能够重用调用 SQL 的函数,因此我希望它们采用实现该sqlx::Executor特征的类型,包括&mut sqlx::Connection、&mut sqlx::pool::PoolConnection和&mut sqlx::Transaction。
每个只需调用数据库一次的函数就可以很好地工作!
但是,我似乎无法重复使用执行器。在我确定页面不存在后调用此函数;我创建一个事务并使用 an&mut Transaction作为e参数调用它:
async fn create_page_for_title(e: impl Executor<'_, Database = Sqlite>, title: &str) -> SqlResult<RawPage> {
let newcontent_id = insert_new_root_content(e).await?;
let newpage = insert_new_page(e, title, newcontent_id).await?;
Ok(newpage)
}
Run Code Online (Sandbox Code Playgroud)
Rust (1.46) 是这样说的:
Error[E0382]: use of moved value: `e`
--> src/store.rs:239:30
|
230 | async fn create_page_for_title(e: impl Executor<'_, Database = Sqlite>, title: &str) -> …Run Code Online (Sandbox Code Playgroud) 背景:
sqlx我在与订阅集成时遇到问题juniper。
我收到了Pin<Box<dyn Stream<Item = Result<User, sqlx::Error>> + 'e + Send>>来自sqlx::query::QueryAs::fetch().
juniper需要将订阅返回为Pin<Box<dyn Stream<Item = Result<User, juniper::FieldError>> + Send>>.
Result<User, sqlx::Error>请注意从到 的更改Result<User, juniper::FieldError>。使用map_err()fromfutures::TryStreamExt,我创建了以下代码来执行查询并转换错误类型。
type UsersStream =
Pin<Box<dyn Stream<Item = Result<User, FieldError>> + Send>>;
#[juniper::graphql_subscription(Context = Context)]
impl SubscriptionRoot {
async fn users(context: &Context) -> UsersStream {
let sqlx::query_as!(User, "SELECT * FROM users")
.fetch(&context.pool)
.map_err(|e| {
FieldError::new(
"Database error",
graphql_value!(format!("{}", e)))
})
.boxed() …Run Code Online (Sandbox Code Playgroud) 注意:这是一个类似但不重复的问题How to use sqlx to query mysql IN a slice? 。我要的是Rust 的。
这就是我尝试做的事情。
let v = vec![..];
sqlx::query("SELECT something FROM table WHERE column IN (?)").bind(v)
...
Run Code Online (Sandbox Code Playgroud)
然后我收到以下错误
the trait bound `std::vec::Vec<u64>: sqlx::Encode<'_, _>` is not satisfied
Run Code Online (Sandbox Code Playgroud) 我尝试手动实现sqlx::FrowRow而不是使用derive,因为需要一些自定义初始化逻辑(例如将整数转换i16为枚举)。
默认的 impl 是这样生成的:
use sqlx::FromRow;
impl FromRow for User {
fn from_row(row: &'r R) -> Result<Self, sqlx::Error> {
todo!()
}
}
Run Code Online (Sandbox Code Playgroud)
但尚不清楚我应该使用什么生命周期和类型。
我目前正在使用actix-web和构建一个应用程序sqlx。我构建的架构与此源代码非常相似。
这基本上是包装数据库访问的特征,到目前为止一切顺利。但这假设每个方法都会从池中获取连接并执行它。无法共享事务工作流程的连接(例如,SELECT FOR UPDATE ... process ... UPDATE)。
我可以使用哪种架构或库来实现这一目标?
我使用sqlx与 Postgres 数据库进行通信。我试图用存储库模式抽象数据库通信。另外,通过这个抽象,我想使用工作单元模式在存储库之间共享数据库事务。我遇到的唯一问题是,如果没有明确提供参数(例如) ,我不知道如何sqlx在这些存储库之间共享事务。我想在(工作单元)抽象中创建和共享事务。transactionsaverepository_x.save(entity, transaction)uow
我想实现这样的目标
struct CommandHandler {
unit_of_work: UnitOfWork
}
impl CommandHandler {
pub fn handle(&self, &command: Command) {
let repository_a = self.unit_of_work.repository_a();
let repository_b = self.unit_of_work.repository_b();
let entity_a = repository_a.get_by_id(command.id);
let entity_b = repository_b.get_by_id(entity_a.id);
unit_of_work.start_transaction();
repository_a.save(entity_a);
repository_b.save(entity_b);
unit_of_work.commit_transaction();
}
}
Run Code Online (Sandbox Code Playgroud)
unit_of_work有谁知道执行上述示例的结构的实现是什么样的?