Actix: move occurs because `p` has type `r2d2::Pool<MysqlConnectionManager>`, which does not implement the `Copy` trait

I'm trying to implement this Actix example, changing the database provider to mysql instead of sqlite.

My code is as follows:

extern crate mysql;

use actix_web::web::{Data};
use actix_web::{get, App, Error, HttpResponse, HttpServer};


use r2d2_mysql::mysql::{Opts,OptsBuilder};

use serde::Serialize;
use r2d2::Pool;

use r2d2_mysql::MysqlConnectionManager;
use r2d2_mysql::mysql::prelude::Queryable;


#[derive(Serialize)]
pub struct Organization {
    pub id: Option<i32>,
    pub name: String,
    pub country: String
}

#[get("/orgs")]
async fn get_orgs(
    pool: Data<Pool<MysqlConnectionManager>>,
) -> Result<HttpResponse, Error> {
    let mut conn = pool
        .get()
        .map_err(|_| HttpResponse::InternalServerError())?;

    let orgs = conn
        .query_map(
            "SELECT id, name, country from organization",
            |(id, name, country)| {
                Organization { id, name, country }
            },
        ).map_err(|_| HttpResponse::InternalServerError())?;

    Ok(HttpResponse::Ok().json(orgs))
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    let opts = Opts::from_url("mysql://root:mysql@127.0.0.1:33061/ebdb").unwrap();
    let builder = OptsBuilder::from_opts(opts);
    let m = MysqlConnectionManager::new(builder);

    let p = Pool::new(m).unwrap();

    HttpServer::new(move || App::new().data(p).service(get_orgs))
        .bind("127.0.0.1:8080")?
        .run()
        .await
}

Thought I had it running(happy IDE), but doing cargo run results in the following:

error[E0507]: cannot move out of `p`, a captured variable in an `Fn` closure
  --> src/main.rs:50:45
   |
48 |     let p = Pool::new(m).unwrap();
   |         - captured outer variable
49 | 
50 |     HttpServer::new(move || App::new().data(p).service(get_orgs))
   |                                             ^ move occurs because `p` has type `r2d2::Pool<MysqlConnectionManager>`, which does not implement the `Copy` trait

How am I to interpret this error? I've changed use r2d2_sqlite::SqliteConnectionManager; to use r2d2_mysql::MysqlConnectionManager; and build up the opts accordingly. Does it not implement the same traits? How do I then build up a mysql connection if this is not the way, using actix_web?

Thanks in advance. Learning Rust :smile:

Original code has this:

    HttpServer::new(move || App::new().data(p.clone()).service(get_orgs))

The difference is the p.clone() call, so that data consumes not the captured variable itself, but its copy.

1 Like

Mm.. I often see people using r2d2 in order to create a connection pool with mysq, but the mysql crate can already provide a connection pool, doesn't it?

1 Like

Few tutorials out there. thank you for the comment. will try using mysql crate directly, instead of r2d2.