Sharing a connection pool object

Hi, sorry, new to rust from a java background, im trying to create separation of files and purpose and want a connection pool object to be shared in the database DAO access files which will query the database. i dont want to pass the pool reference as a param each time i want to call the query function. my issue.

the error
let mut conn = poolLocal.get_conn()?;
| ^^^^^^^^^ a field by this name exists in Self

How do i get a self reference to a struct when the method is called from outside.

dao/pigeonDao.ts

pub struct PigeonDao{
poolLocal: Pool
}

impl PigeonDao {

pub fn init(pool: Pool)  {
    PigeonDao {
        poolLocal:pool
    };
}


pub fn runQuery() -> Result<()> {

    let mut conn = poolLocal.get_conn()?;
}
}

main.rs

fn main() {

println!("starting program");
init().expect("failed");

dao::pigeonDao::PigeonDao::runQuery();


}

fn init()-> Result<()> {
let url = "mysql://root:$post123@localhost:3306/vfolr";
let pool = Pool::new(url)?;
 dao::pigeonDao::PigeonDao::init(pool);
Ok(())
}

You need to have an instance of PigeonDao to access the fields on a PigeonDao, they don't exist otherwise. They're like fields on a Java class, they can store different values per instance.

Here's one way you could get your code to work:

  • init should return a PigeonDao.
  • runQuery should take &self or &mut self, to turn it into a method.
  • You should then call init to construct your PigeonDao, and call .runQuery on it to use the method.
  • Also, your variables/functions should be in snake_case.
pub struct PigeonDao {
    pool_local: Pool
}

impl PigeonDao {
    pub fn init(pool: Pool) -> PigeonDao {
        PigeonDao {
            pool_local: pool
        } // no semicolon here, so it returns
    }


    pub fn run_query(&mut self) -> Result<()> {
        let mut conn = poolLocal.get_conn()?;
        Ok(())
    }
}
fn main() {
    println!("starting program");
    let mut dao = init().expect("failed");
    dao.run_query().expect("failed");
}

fn init() -> Result<PigeonDao> {
    let url = "mysql://root:$post123@localhost:3306/vfolr";
    let pool = Pool::new(url)?;
    let dao = dao::pigeonDao::PigeonDao::init(pool);
    Ok(dao)
}
1 Like

I recommend checking out The Rust Programming Language book. Rust is in my experience a lot harder to learn by diving in and writing code compared to some other languages.

To try to relate the necessary changes to Java a bit, the first error is caused because functions inside impl blocks are not automatically methods and there's no "implicit this" in Rust. You have to first add a self parameter to the function to make it a method, and then explicitly use the fields through the self parameter. Without a self parameter, functions inside an impl block are closer to what you may know as "static methods".

As for the changes needed to init, there is no special constructor method in Rust, like there is in Java. A "constructor" is simply a normal function that returns the thing you want to construct. You can have multiple constructors, or none, as they're just normal functions without any special attributes whatsoever. What your current PigeonDao::init does is it creates a PigeonDao and then throws it away.

1 Like

cool, so that does kinda make sense but then trying to take that and up the scale a bit with Two Dao's where the pool is shared to create their "own" connections.

unless im thinking of this the wrong way because of java. so im playing with a variation of what the rust doc on a multithreaded webserver with the addtion of a database. In my brain i need the DAOs and those pull connections from the pool when they are called by a "thread" that receives a web connection.

unless i should be having those threads created and then each thread is to get a connection and use one per thread.

From digging on the internet there are very few "how to structure a rust project" for medium sized to large project. most are just a main.rs and a concept .

23 |     let pool = initDb().expect("failed");
  |         ---- move occurs because `pool` has type `mysql::Pool`, which does not implement the `Copy` trait
24 | 
25 |     let mut pigeonDao = dao::pigeonDao::PigeonDao::init(pool);
 |                                                         ---- value moved here

 28 |     let mut countriesDao = dao::countriesDao::CountriesDao::init(pool);
 |                                                                  ^^^^ value used here after move
fn main() {


println!("starting program");
let pool = initDb().expect("failed");

let mut pigeonDao = dao::pigeonDao::PigeonDao::init(pool);
pigeonDao.run_query();

let mut countriesDao = dao::countriesDao::CountriesDao::init(pool);

}

fn initDb() -> Result<Pool>{
  let url = "mysql://root:$post123@localhost:3306/vfolr";
 Pool::new(url)
}

Thanks in advance.

so in additon to this,

this works, but does it not create a pool per DAO ?

fn main() {


println!("starting program");
let pool = initDb().unwrap();

let mut pigeonDao = dao::pigeonDao::PigeonDao::init(pool.clone());
pigeonDao.run_query();

let mut countriesDao = dao::countriesDao::CountriesDao::init(pool.clone());
countriesDao.run_query();

}

Looking at the docs, it seems like that is how Pool is intended to be used.

And looking at the source code, all of the underlying data contained within a Pool is held within Arcs. When you clone an Arc (or a Rc, which is the single-threaded version), it doesn't clone the underlying data, it just creates a new Arc pointing at the same data as the one you cloned. When all of the Arcs pointing to a piece of data get dropped, the underlying data is disposed of.

This is called 'reference counting', and it's covered in chapter 15 of the book.

So, this won't create a new connection pool per DAO - you can think of the Pool type as being a 'handle' to a connection pool that exists elsewhere, rather than being the connection pool itself.

Or to put it a shorter way, your code is correct :stuck_out_tongue:

Thanks for the "pointers" :stuck_out_tongue:

yeah, just feel like a noob with a new language compared to what im used to. luckily its not for anything work related.

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.