Skip to content

Cannot use temporaries as query! arguments when using SQLite #1430

Open
@kangalio

Description

@kangalio

Many expressions cannot be used as arguments in the query! macro in SQLite mode because it throws a "temporary value dropped while borrowed" error:

sqlx::query!(
    "INSERT INTO todo (task, user_id) VALUES (?, ?)",
    task_description.trim(),
    msg.author.id.0 as i64,
)
error[E0716]: temporary value dropped while borrowed
  --> examples/e15_sqlite_database/src/main.rs:15:5
   |
13 | / sqlx::query!(
14 | |     "INSERT INTO todo (task, user_id) VALUES (?, ?)",
15 | |     task_description.trim(),
   | |     ^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
16 | |     msg.author.id.0 as i64,
17 | | )
   | |_- temporary value is freed at the end of this statement
18 |   .execute(&self.database)
   |    ------- borrow later used by call
The second argument fails too
error[E0716]: temporary value dropped while borrowed
  --> examples/e15_sqlite_database/src/main.rs:16:5
   |
13 | / sqlx::query!(
14 | |     "INSERT INTO todo (task, user_id) VALUES (?, ?)",
15 | |     task_description.trim(),
16 | |     msg.author.id.0 as i64,
   | |     ^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
17 | | )
   | |_- temporary value is freed at the end of this statement
18 |   .execute(&self.database)
   |    ------- borrow later used by call

Equipped with cargo expand and the source code of two bots using SQLx, I found out that the culprit lies in the SqliteArguments struct, which stores arguments to an SQLite query. Other Arguments types (PgArguments, MySqlArguments...) are owned but SqliteArguments has a lifetime and presumably stores references to the arguments instead of owning the arguments.

This is an issue because sqlx::query! expands to something like this:

{
    let arg0 = &(task_description.trim());
    let arg1 = &(msg.author.id.0 as i64);
    let mut query_args = SqliteArguments::new();
    query_args.add(arg0);
    query_args.add(arg1);
    query_args
}

query_args references arg0/arg1 which are destroyed at the end of scope, hence the error.

I don't know how it hard it is to do, but a fix for this would be awesome!

The issue can be worked around by binding the expressions beforehand, although it looks a bit ugly
let (a, b, c, d, e, f) = (
    showcase_msg.id.0 as i64,
    showcase_msg.channel_id.0 as i64,
    ctx.channel_id().0 as i64,
    name.id.0 as i64,
    description.id.0 as i64,
    links.id.0 as i64,
);
sqlx::query!(
    "INSERT INTO showcase (
        output_message,
        output_channel,
        input_channel,
        name_input_message,
        description_input_message,
        links_input_message
    ) VALUES (?, ?, ?, ?, ?, ?)",
    a,
    b,
    c,
    d,
    e,
    f,
)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions