如何从 Rocket 的 fairing 中访问数据库连接?

huangapple go评论70阅读模式
英文:

How to access database connection from a Rocket's fairing?

问题

I'm trying to use database connection from a Rocket's on_ignite fairing:

use sqlx::{self, FromRow};
use rocket::fairing::{self, Fairing, Info, Kind};
use rocket::{Build, Rocket};

use crate::database::PostgresDb;
    
#[derive(FromRow)]
struct TableRow {
  column_a: String,
  column_b: String
}

#[rocket::async_trait]
impl Fairing for TableRow {
  fn info(&self) -> Info {
    Info {
      name: "Cache table row",
      kind: Kind::Ignite,
    }
  }

  async fn on_ignite(&self, rocket: Rocket<Build>) -> fairing::Result {
    let mut db = rocket
      .state::<Connection<PostgresDb>>()
      .expect("Unable to find db connection.");

    let row = sqlx::query_as::<_, TableRow>("SELECT * FROM table WHERE id = 1;")
      .fetch_one(&mut db)
      .await
      .unwrap();

    fairing::Result::Ok(rocket.manage(row))
  }
}

The problem is I get the following rust error during .fetch_one(&mut db):

the trait bound `&mut rocket_db_pools::Connection<PostgresDb>: Executor<'_>` is not satisfied
the following other types implement trait `Executor<'c>`:
  <&'c mut PgConnection as Executor<'c>>
  <&'c mut PgListener as Executor<'c>>
  <&'c mut PoolConnection<Postgres> as Executor<'c>>
  <&'t mut Transaction<'c, Postgres> as Executor<'t>>
  <&sqlx::Pool<DB> as Executor<'p>>
cache_rbac_on_ignite.rs(56, 14): required by a bound introduced by this call
query_as.rs(132, 17): required by a bound in `QueryAs::<'q, DB, O, A>::fetch_all`

I tried the solution suggested here: https://stackoverflow.com/questions/68394258/how-to-get-the-database-connection-in-rocket-rs-fairing/68394259#68394259, but it did not work out.

Here is the code:

use sqlx::{ self, FromRow, Database };
use rocket::fairing::{self, Fairing, Info, Kind};
use rocket::{Build, Rocket};

use crate::database::PostgresDb;
    
#[derive(FromRow)]
struct TableRow {
  column_a: String,
  column_b: String
}

#[rocket::async_trait]
impl Fairing for TableRow {
  fn info(&self) -> Info {
    Info {
      name: "Cache table row",
      kind: Kind::Ignite,
    }
  }

  async fn on_ignite(&self, rocket: Rocket<Build>) -> fairing::Result {
    let mut db = PostgresDb::get_one(rocket).await.unwrap();

    let row = sqlx::query_as::<_, TableRow>("SELECT * FROM table WHERE id = 1;")
      .fetch_one(&mut db)
      .await
      .unwrap();

    fairing::Result::Ok(rocket.manage(row))
  }
}

I get the following rust error on line let mut db = PostgresDb::get_one(rocket).await.unwrap();:

no function or associated item named `get_one` found for struct `PostgresDb` in the current scope
function or associated item not found in `PostgresDb`
mod.rs(8, 1): function or associated item `get_one` not found for this struct

What is the right way to use a database connection inside of the fairing? Thank you!

英文:

I'm trying to use database connection from a Rocket's on_ignite fairing:

use sqlx::{ self, FromRow };
use rocket::fairing::{self, Fairing, Info, Kind};
use rocket::{Build, Rocket};

use crate::database::PostgresDb;
    
#[derive(FromRow)]
struct TableRow {
  column_a: String,
  column_b: String
}

#[rocket::async_trait]
impl Fairing for TableRow {
  fn info(&self) -> Info {
    Info {
      name: "Cache table row",
      kind: Kind::Ignite,
    }
  }

  async fn on_ignite(&self, rocket: Rocket<Build>) -> fairing::Result {
    let mut db = rocket
      .state::<Connection<PostgresDb>>()
      .expect("Unable to find db connection.");

    let row = sqlx::query_as::<_, TableRow>("SELECT * FROM table WHERE id = 1;")
      .fetch_one(&mut db)
      .await
      .unwrap();

    fairing::Result::Ok(rocket.manage(row))
  }
}

The problem is I get following rust error during .fetch_one(&mut db):

the trait bound `&mut rocket_db_pools::Connection<PostgresDb>: Executor<'_>` is not satisfied
the following other types implement trait `Executor<'c>`:
  <&'c mut PgConnection as Executor<'c>>
  <&'c mut PgListener as Executor<'c>>
  <&'c mut PoolConnection<Postgres> as Executor<'c>>
  <&'t mut Transaction<'c, Postgres> as Executor<'t>>
  <&sqlx::Pool<DB> as Executor<'p>>rustcClick for full compiler diagnostic
cache_rbac_on_ignite.rs(56, 14): required by a bound introduced by this call
query_as.rs(132, 17): required by a bound in `QueryAs::<'q, DB, O, A>::fetch_all`

I tried solution suggested here: https://stackoverflow.com/questions/68394258/how-to-get-the-database-connection-in-rocket-rs-fairing/68394259#68394259. but it did not work out.
Here is the code:

use sqlx::{ self, FromRow, Database };
use rocket::fairing::{self, Fairing, Info, Kind};
use rocket::{Build, Rocket};

use crate::database::PostgresDb;
    
#[derive(FromRow)]
struct TableRow {
  column_a: String,
  column_b: String
}

#[rocket::async_trait]
impl Fairing for TableRow {
  fn info(&self) -> Info {
    Info {
      name: "Cache table row",
      kind: Kind::Ignite,
    }
  }

  async fn on_ignite(&self, rocket: Rocket<Build>) -> fairing::Result {
    let mut db = PostgresDb::get_one(rocket).await.unwrap();

    let row = sqlx::query_as::<_, TableRow>("SELECT * FROM table WHERE id = 1;")
      .fetch_one(&mut db)
      .await
      .unwrap();

    fairing::Result::Ok(rocket.manage(row))
  }
}

I get following rust error on line let mut db = PostgresDb::get_one(rocket).await.unwrap();:

no function or associated item named `get_one` found for struct `PostgresDb` in the current scope
function or associated item not found in `PostgresDb`rustcClick for full compiler diagnostic
mod.rs(8, 1): function or associated item `get_one` not found for this struct

What is the right way to use database connection inside of the fairing? Thank you!

答案1

得分: 1

这是代码的翻译部分:

use rocket::fairing::{self, Fairing, Info, Kind};
use rocket::{Build, Rocket};
use rocket_db_pools::{ sqlx::{ self, FromRow }, Database };

use crate::database::PostgresDb;

#[derive(FromRow)]
struct TableRow {
  column_a: String,
  column_b: String
}

#[rocket::async_trait]
impl Fairing for TableRow {
  fn info(&self) -> Info {
    Info {
      name: "缓存表行",
      kind: Kind::Ignite,
    }
  }

  async fn on_ignite(&self, rocket: Rocket<Build>) -> fairing::Result {
    let db = PostgresDb::fetch(&rocket).unwrap();
    let mut conn = db.acquire().await.unwrap();

    let row = sqlx::query_as::<_, TableRow>("SELECT * FROM table WHERE id = 1;")
      .fetch_one(&mut conn)
      .await
      .unwrap();

    fairing::Result::Ok(rocket.manage(row))
  }
}

注意:我已将代码中的HTML实体转义字符(&amp;&gt;)翻译为正常的Rust代码。如果需要进一步的帮助或翻译,请告诉我。

英文:

Finally found an answer. Here is what worked for me:

use rocket::fairing::{self, Fairing, Info, Kind};
use rocket::{Build, Rocket};
use rocket_db_pools::{ sqlx::{ self, FromRow }, Database };

use crate::database::PostgresDb;
    
#[derive(FromRow)]
struct TableRow {
  column_a: String,
  column_b: String
}

#[rocket::async_trait]
impl Fairing for TableRow {
  fn info(&amp;self) -&gt; Info {
    Info {
      name: &quot;Cache table row&quot;,
      kind: Kind::Ignite,
    }
  }

  async fn on_ignite(&amp;self, rocket: Rocket&lt;Build&gt;) -&gt; fairing::Result {
    let db = PostgresDb::fetch(&amp;rocket).unwrap();
    let mut conn = db.aquire().await.unwrap();

    let row = sqlx::query_as::&lt;_, TableRow&gt;(&quot;SELECT * FROM table WHERE id = 1;&quot;)
      .fetch_one(&amp;mut conn)
      .await
      .unwrap();

    fairing::Result::Ok(rocket.manage(row))
  }
}

huangapple
  • 本文由 发表于 2023年2月16日 07:42:55
  • 转载请务必保留本文链接:https://go.coder-hub.com/75466454.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定