I’m developing a Rust application using sqlx with SQLite, and I’m encountering an issue with lifetime management when dynamically generating SQL queries.
Here is a simplified version of my code:
use sqlx::{sqlite::SqlitePool, query_as, FromRow};
use sqlx::Error;
use futures::stream::Stream;
use futures::StreamExt;
use std::pin::Pin;
struct Dao {
pool: SqlitePool,
}
impl Dao {
pub fn new(pool: SqlitePool) -> Self {
Self { pool }
}
pub async fn find<'a>(&'a self, order_by: &str) -> Result<Pin<Box<dyn Stream<Item = Result<MyStruct, Error>> + Send + 'a>>, Error> {
let sql = format!("SELECT * FROM my_table ORDER BY {}", order_by);
// Execute query
let stream = query_as::<_, MyStruct>(&sql)
.fetch(&self.pool);
// Return the stream
Ok(Box::pin(stream))
}
}
#[derive(FromRow, Debug)]
struct MyStruct {
id: i32,
name: String,
}
#[tokio::main]
async fn main() -> Result<(), Error> {
let pool = SqlitePool::connect("sqlite::memory:").await?;
let dao = Dao::new(pool);
let order_by = "name ASC, id ASC";
let mut stream = dao.find(order_by).await?;
while let Some(result) = stream.next().await {
match result {
Ok(record) => println!("Found record: {} - {}", record.id, record.name),
Err(e) => eprintln!("Error: {}", e),
}
}
Ok(())
}
When I run this code, I encounter the following error:
error[E0515]: cannot return value referencing local variable `sql`
--> src/issues/avoid-e0515.rs:24:9
|
20 | let stream = query_as::<_, MyStruct>(&sql)
| ---- `sql` is borrowed here
...
24 | Ok(Box::pin(stream))
| ^^^^^^^^^^^^^^^^^^^^ returns a value referencing data owned by the current function
It seems that sqlx::query_as holds a reference to the query string, and this reference cannot outlive the function scope where the string is created.
Is there a way to safely pass a dynamically generated SQL query to sqlx::query_as without encountering lifetime issues in Rust? Or is this inherently impossible due to Rust’s strict borrowing rules? Any insights or alternative approaches would be greatly appreciated.
Soichiro Shishido is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.