clickhouse.rs icon indicating copy to clipboard operation
clickhouse.rs copied to clipboard

The fetch API is unsound if used with borrowed types

Open loyd opened this issue 3 years ago • 6 comments

The current API allows the following code:

let mut cursor = client.query("...").fetch::<MyRow<'_>>()?;
let a = cursor.next().await?;
let b = cursor.next().await?; // <- must be error

We should use something like sqlx::fetch or wait for GAT stabilization.

Sadly, it will be a breaking change.

loyd avatar Oct 25 '21 05:10 loyd

Is the issue that you are reusing a temporary and returning a reference to that temporary?

droundy avatar May 05 '23 19:05 droundy

Is there a reason you couldn't change from

pub async fn next<'a, 'b: 'a>(&'a mut self) -> Result<Option<T>> where
    T: Deserialize<'b>,

to

pub async fn next<'a>(&'a mut self) -> Result<Option<T>> where
    T: Deserialize<'a>,

Yes, this would be a breaking change, but doesn't seem like it would be productively complicated.

droundy avatar May 06 '23 13:05 droundy

Sadly, it's not enough:

  --> examples/usage.rs:69:27
   |
69 |     while let Some(row) = cursor.next().await? {
   |                           ^^^^^^^^^^^^^
   |                           |
   |                           `cursor` was mutably borrowed here in the previous iteration of the loop
   |                           first borrow used here, in later iteration of loop

loyd avatar May 14 '23 08:05 loyd