Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Passing around a reference to a mysql connection in a struct

So Im trying to make my program create a DB struct that has an open connection that i can pass around as a reference to places that need it. So I have the following class

use mysql::*;
use mysql::prelude::*;

pub struct DB {
    pub conn: PooledConn
}

pub fn initialize(url: &str) -> DB{
    println!("Initializing!");
    let pool = get_pool(url).unwrap();
    let conn = pool.get_conn().unwrap();
    let db = DB {
        conn
    };
    return db;
}

fn get_pool(url: &str) -> Result<Pool> {
    let opts = Opts::from_url(url).unwrap();
    println!("{:?}", opts);
    let pool = match Pool::new(opts){
        Ok(pool) => pool,
        Err(e) => {
            return Err(e);
        }
    };

    return Ok(pool);
}

So when i call initialize it creates the connection, puts it in a struct and sends that back.

let mut db = db::initialize("connection_string");

Then I can use my connection as follows:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

#[derive(Debug, PartialEq, Eq)]
    struct Place {
        name: String
    }

    let mut places: Vec<Place> = vec![];
    let selected_places = db.conn
        .query_map(
            "SELECT name from places",
            |(name)| {
                places.push( Place { name } );
            },
        ).unwrap();

    println!("{:?}", places);
}

And this works fine. It prints out the places as expected. But what I want to do is pass that struct around so that a single instance of the database connection is used everywhere a query is needed. so I am trying to do something like:

use mysql::*;
use mysql::prelude::*;

mod db;

fn main() {
    println!("Hello, world!");
    let mut db = db::initialize("connection_string");
    let mut test: &db::DB = &db;
    query(test);
}

fn query(mut db: &db::DB) {
    #[derive(Debug, PartialEq, Eq)]
    struct Place {
        name: String
    }

    let mut rooms: Vec<Place> = vec![];
    let selected_places = db.conn
        .query_map(
            "SELECT name from places",
            |(name)| {
                places.push( Place { name } );
            },
        ).unwrap();

    println!("{:?}", places);
}

If I do this the compiler says when I want to use db.conn

`db` is a `&` reference, so the data it refers to cannot be borrowed as mutable

So how do I pass in a reference to that struct so I can use the same connection in multiple places?

>Solution :

Your function query:

fn query(mut db: &db::DB)

is being passed an immutable reference to a db::DB, but making the db variable mutable. This allows you to change which db::DB the variable references, by eg assigning to it, but doesn’t actually allow you to do anything to the db::DB itself that would require a mutable reference (such as calling .query_map on the conn attribute).

If you change the function signature to:

fn query(db: &mut db::DB)

you should be able to achieve what you’re looking for. In that case, you have a mutable reference to the db::DB.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading