1

While working with Rust's MySQL Crate I have been unable to compile with the conn.exec() function that seems to be matching with documentation as well as guides online.

The line conn.exec() causes the error

52 |     conn.exec(&stmt, params! {"username" => args.username})?;
   |          ^^^^ cannot infer type of the type parameter `T` declared on the associated function `exec`
   |
help: consider specifying the generic arguments
   |
52 |     conn.exec::<T, &Statement, Params>(&stmt, params! {"username" => args.username})?;

My code is the following:

fn execute_sql(conn_string: String, args: Args) -> std::result::Result<(), Box<dyn Error>> {
    let sql_statement = match args.query.as_str(){
        "promote" => "UPDATE Users SET admin = 1 WHERE username = ':username';",
        &_ => return Err(Box::from("query type invalid")),
    };
    println!("{}", sql_statement);

    let pool = Pool::new(conn_string.as_str())?;
    let mut conn = pool.get_conn()?;
    let stmt = conn.prep(sql_statement)?;
    //conn.exec(sql_statement, params! {"username" => args.username})?;
    conn.exec(&stmt, params! {"username" => args.username})?;

    Ok(())
}

The documentation shows:

let pool = Pool::new(get_opts())?;

let mut conn = pool.get_conn()?;
let stmt = conn.prep("SELECT :foo, :bar, :foo")?;

let foo = 42;

let val_13 = conn.exec_first(&stmt, params! { "foo" => 13, "bar" => foo })?.unwrap();
// Short syntax is available when param name is the same as variable name:
let val_42 = conn.exec_first(&stmt, params! { foo, "bar" => 13 })?.unwrap();

assert_eq!((foo, 13, foo), val_42);
assert_eq!((13, foo, 13), val_13);

Am I missing something fairly obvious here?

I have attempted passing &self as the first parameter, I've tried marking it as ::<T, &Statement, Params>, and some other less successful ideas

Jared
  • 41
  • 3

1 Answers1

3

You need to specify the type of value returned by exec. In the example from the documentation this is implied because the return value is assigned to a variable that is later used, so Rust is able to infer the type from usage. But since you don't use the return value you need to be explicit:

fn execute_sql(conn_string: String, args: Args) -> std::result::Result<(), Box<dyn Error>> {
    let sql_statement = match args.query.as_str(){
        "promote" => "UPDATE Users SET admin = 1 WHERE username = ':username';",
        &_ => return Err(Box::from("query type invalid")),
    };
    println!("{}", sql_statement);

    let pool = Pool::new(conn_string.as_str())?;
    let mut conn = pool.get_conn()?;
    let stmt = conn.prep(sql_statement)?;
    //conn.exec(sql_statement, params! {"username" => args.username})?;
    conn.exec::<(), _, _>(&stmt, params! {"username" => args.username})?;

    Ok(())
}

Note that () is the "void" type, that signifies that the statement doesn't return any value.

Jmb
  • 18,893
  • 2
  • 28
  • 55
  • Thanks for the help! After some modification I have compiled rust using `let sql_result = conn.exec::(sql_statement, params! {"username" => args.username})?; ` – Jared Mar 23 '23 at 15:54