5

I'm trying to add a postgres database to a rocket app using diesel. My main.rs file looks like this, but gives the error "the trait diesel::Connection is not implemented for DbConnection" at .get_result(connection)

#[macro_use] extern crate diesel;
extern crate dotenv;
#[macro_use] extern crate rocket;
#[macro_use] extern crate rocket_contrib;

use diesel::prelude::*;
use rocket_contrib::database;
use rocket_contrib::json::JsonValue;

mod models;
mod schema;

use self::models::*;
use self::schema::*;

#[database("my_db")]
struct DbConnection(diesel::PgConnection);

#[get("/")]
fn index(connection: DbConnection) -> JsonValue {
    json!(all_bicycles(&connection))
}

fn create_bicycle<'a>(connection: &DbConnection, make: &'a str, model: &'a str, rider_type: &'a str, size: &'a str) -> Bicycle {
    let new_bicycle = NewBicycle {
        make,
        model,
        rider_type,
        size
    };

    diesel::insert_into(bicycles::table)
        .values(new_bicycle)
        // the error is on the following line, on `connection`
        .get_result(connection)
        .expect("Error saving bicycle")
}

fn main() {
    rocket::ignite()
        .attach(DbConnection::fairing())
        .mount("/", routes![index])
        .launch();
}

My Cargo.toml (the relevant parts)

[dependencies]
diesel = { version = "1.4.4", features = ["postgres"] }
dotenv = "0.15.0"
rocket = { git = "https://github.com/SergioBenitez/Rocket" }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"

[dependencies.rocket_contrib]
git = "https://github.com/SergioBenitez/Rocket"
default-features = false
features = ["json", "diesel_postgres_pool"]

and my Rocket.toml:

[global.databases]
my_db = { url = "postgres://postgres:@localhost/bikes" }

The error looks like this when expanded:

&DbConnection
the trait bound `DbConnection: diesel::Connection` is not satisfied

the trait `diesel::Connection` is not implemented for `DbConnection`

I've managed to establish the connection to the database, and diesel setup was successful. I'm also able to add migrations - although I think they're unnecessary for this issue.

What am I doing wrong here?

Edit

I worked through the Rocket docs again and realised I was missing the line use rocket_contrib::databases::diesel;, which conflicts with extern crate diesel;, so I moved the database logic into a new module - database.rs. Nothing has really changed, but the new module looks like this:

use rocket_contrib::database;
use rocket_contrib::databases::diesel;

#[database("my_db")]
pub struct DbConnection(diesel::PgConnection);

and it's being used like so:

main.rs

// ...
mod database;
use self::database::DbConnection;
// ...

The error remains the same.

Konrad Rudolph
  • 530,221
  • 131
  • 937
  • 1,214
Michael Evans
  • 971
  • 1
  • 13
  • 30

3 Answers3

3

According to the rocket documentation you need to deref your connection type into some type type that implements diesel::connection::Connection as the wrapper type does not implement the necessary trait. So you need to change your code to the following:

    diesel::insert_into(bicycles::table)
        .values(new_bicycle)
        // the error is on the following line, on `connection`
        .get_result(&*connection)
        .expect("Error saving bicycle")

(Note the additional &* before passing the connection into the get_result function.)

weiznich
  • 2,910
  • 9
  • 16
  • 2
    Thanks for the answer, but it unfortunately didn't work. I'm still new to Rust, but I believe the issue lies in the `#[database]` not correctly applying the traits to the struct, that said I don't know how to fix it, so I'm just guessing really. – Michael Evans Jan 21 '21 at 20:35
  • "It's not working" is nothing that is helping someone to understand you issue. Please provide exactly what you've done so far and what you expect do happen and what is happening instead. This includes all potential error messages and so on. Otherwise the only thing other people can do is point to the corresponding documentation. – weiznich Jan 22 '21 at 09:32
  • 1
    @weiznich I've been facing same issue, implemented your solution but it throws a different error: `fn create_todo(conn: DbConn) {}...` "Type DbConn cannot be dereferenced". – Andres Urdaneta Dec 17 '21 at 15:36
2

I created a StackOverflow account to answer this. I got it working with

connection.run(|conn| {
    diesel::insert_into(bicycles::table)
      .values(new_bicycle)
      .get_result::<Bicycle>(conn)
      .expect("Error saving bicycle")
  }).await;

I have to make the fn async. Also, I am having a Deserialization issue, but I think it's not related.

0

If I recall it correctly, it should be

#[get("/")]
fn index(connection: DbConnection) -> JsonValue {
    json!(all_bicycles(&*connection))
}

for the route and

fn all_bicycles(connection: &diesel::PgConnection) -> Vec<Bicycle> {
    // ...
    .get_result(connection)
    .expect("Error saving bicycle")
    // ...
}

for your acutal method for querying the database. So, passing the actual diesel connection directly as a reference (since your database abstraction should not necessarily know something about rocket).

Tim
  • 65
  • 2
  • 6