Open
Description
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
Labels
No labels