#How to create initial State object when you don't know reasonable default values (Mutex Issue)

8 messages · Page 1 of 1 (latest)

soft garnet
#

I am trying to create a small app that uses an Sqlite database to store information, however I need the ability for the user to be able to set where the database resides from the front end. So initially there is no database set and the front end will just show the "New / Open Database" screen.
My problem is that I need to store the database connection (diesel::SqliteConnection) in the rust app state so that I can use it, however I can not figure out how to create the initial State object as I do not have an SqliteConnection at startup time, so I can not create the Mutex that wraps it.

In main.rs:

struct AppState {
    count: Mutex<i64>,
    conn: Mutex<SqliteConnection>,
    db_location: Mutex<String>
}

fn main() {
    let state = AppState {
        count: Mutex::new(0),
        conn: Mutex::new(Default::default()),
        db_location: Mutex::new(String::from(""))
    };
    // Start the Application
    let context = tauri::generate_context!();
    let builder = tauri::Builder::default()
        .manage(state)
        .plugin(tauri_plugin_store::Builder::default().build())
        .invoke_handler(tauri::generate_handler![
            get_count,
            update_count,
            set_db_location,
            ... // bunch more handlers omitted for brevity
        ]);
    let app = match builder.build(context) {
        Err(e) => panic!("Can not build Tarui application: {e}"),
        Ok(_f) => _f
    };

However this fails to compile as the trait std::default::Default is not implemented for 'diesel::SqliteConnection'

Is it possible to set up a Mutex such that is does not have a value? I am loathe to randomly implement traits for SqliteConnection without understanding what I am messing with.

wind mason
#

That's where Option comes in

#

Wrap it in Option and set it to None

soft garnet
#

Thank you. I knew there must be something obvious I was missing. It has been a while since I did any coding. The last time I did any serious coding was C++ and I had to roll my own list class because the STL had not been created 😉

soft garnet
#

Any best practice on how to get the SqliteConnection back out of the Mutex<Option>> in order to make use of it? Diesel requires that a "conn: &mut SqliteConnection" is passed into the functions that perform the actual database operations (select, insert etc). I am having trouble figuring out how to get a mutable reference to an SqliteConnection from the Mutex.

#

In my main file I have simple handler functions that just pass of the work to other files:

#[tauri::command]
fn get_all_miniatures(state: tauri::State<AppState>) -> Result<String, String> {
  println!("Get all Minis");

  return db::miniatures_get_all(&state.conn);
}
#

Then in the db.rs I have:

pub fn miniatures_get_all(conn: &Mutex<Option<SqliteConnection>>)-> Result<String, String> {
    let connection_guard: std::sync::MutexGuard<Option<SqliteConnection>> = conn.lock().unwrap();
    let all_minis: Vec<Miniature> = match miniatures::table
        .select(Miniature::as_select())
        .load(&mut connection_guard.unwrap()) {
        Err(_e) => return Err(String::from("Can not load all miniatures from database")),
        Ok(f) => f,
    };
...

then I get the following error:

cannot move out of dereference of `MutexGuard<'_, std::option::Option<diesel::SqliteConnection>>`
help: consider calling `.as_ref()` or `.as_mut()` to borrow the type's contents

If i change the code to one of the suggested options I get:

mismatched types
expected mutable reference `&mut _`
                found enum `std::option::Option<&diesel::SqliteConnection>`

or:

cannot borrow `connection_guard` as mutable, as it is not declared as mutable
cannot borrow as mutable

respectively.

It looks like I could use & connection_guard.unwrap() if I wanted a &SqliteConnection, but I can not figure out how to get a &mut SqliteConnection

wind mason
#

You either unwrap or match options