prisma / tiberius

TDS 7.2+ (Microsoft SQL Server) driver for Rust
Apache License 2.0
321 stars 118 forks source link

Vec<u8>: tiberius::FromSql<'_> is missing #256

Closed dimdin closed 1 year ago

dimdin commented 1 year ago

There is no way to get varbinary data.

error[E0277]: the trait bound `Vec< u8 >: tiberius::FromSql<'_>` is not satisfied
   --> src/db/mod.rs:338:66
    |
338 | ...                   let value: Option> = row.get(col.name());
    |                                                        ^^^ the trait `tiberius::FromSql<'_>` is not implemented for `Vec< u8 >`
    |
pimeys commented 1 year ago

You can't take a vector out without copying it using the get function. get only returns a reference to the data, so you can reference to the slice: https://docs.rs/tiberius/0.11.3/tiberius/trait.FromSql.html#impl-FromSql%3C%27a%3E-for-%26%27a%20%5Bu8%5D

So if you want to use this api:

let value: Option<&[u8]> = row.get(col.name());

Or, if you take the quite large copying penalty, which we will do not automatically do for you:

let value: Option<Vec<u8>> = row.get::<&[u8]>(col.name()).map(|r| r.to_owned());

The fast way is to iterate on every column of the row, and move the data out (docs):

for column in row.into_iter() {
    let value: Option<Vec<u8>> = Vec::<u8>::from_sql_owned(column)?;
}

The get will always be referencing, we will not add anything that gives you a copy penalty without the user explicitly asking for that. The correct way is to iterate the row by-value and convert them with the correspnding trait.