Brendonovich / prisma-client-rust

Type-safe database access for Rust
https://prisma.brendonovich.dev
Apache License 2.0
1.83k stars 108 forks source link

@db.UniqueIdentifier raw query panicked at 'called `Result::unwrap()` on an `Err` value: Error(ByteLength { len: 36 })' #378

Closed bangbaew closed 1 year ago

bangbaew commented 1 year ago

I tried a simple raw query to select * from this table in SQL Server, and my schema model has @db.UniqueIdentifier as id image

It panics with this error,

thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Error(ByteLength { len: 36 })', /usr/local/cargo/git/checkouts/prisma-client-rust-fa967aa5ad0ec391/51f0473/src/raw.rs:92:75
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

This is line raw.rs:92:75 it refers to, image

but when I remove @db.UniqueIdentifier from the model in schema.prisma and migrate, the raw query works fine.

Brendonovich commented 1 year ago

Can you make a minimal reproduction for this please? I'm probably handling UUIDs incorrectly.

bangbaew commented 1 year ago

Can you make a minimal reproduction for this please? I'm probably handling UUIDs incorrectly.

Ok, here's the steps to reproduce:

  1. Create this model in schema.prisma and run migrate (current using prisma-client-rust 0.6.9)

    model TestTable {
    id String @id @default(uuid()) @db.UniqueIdentifier
    }
  2. Build a client instance and create a row

    let client = PrismaClient::_builder().build().await.unwrap();
    client.test_table().create(vec![]).exec().await?;
  3. A new record will be inserted to the TestTable as usual image

  4. Try running the raw query, type Data I referred to is the one generated by the cli

    #[derive(Debug, Clone, :: serde :: Serialize, :: serde :: Deserialize)]
    pub struct Data {
        #[serde(rename = "id")]
        pub id: String,
    }
    let _: Vec<Data> = client._query_raw(raw!("SELECT id FROM TestTable")).exec().await?;
  5. Program will panic

    thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Error(ByteLength { len: 36 })', /usr/local/cargo/git/checkouts/prisma-client-rust-fa967aa5ad0ec391/895aac7/src/raw.rs:92:75
    note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
Brendonovich commented 1 year ago

Steps are nice but a repo I can download + run would be preferred

bangbaew commented 1 year ago

Steps are nice but a repo I can download + run would be preferred

I have a simpler way to reproduce, by copying the code generated in raw.rs at uuid section:

let s = "adea87ff-6a7e-4b95-90c8-1d6858814988".to_string();
let fromslice = uuid::Uuid::from_slice(s.as_bytes())?;
println!("{}", fromslice);

causes the same panic

thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Error(ByteLength { len: 36 })'

this is the from_slice() function in uuid crate

pub fn from_slice(b: &[u8]) -> Result<Uuid, Error> {
        if b.len() != 16 {
            return Err(Error(ErrorKind::ByteLength { len: b.len() }));
        }

        let mut bytes: Bytes = [0; 16];
        bytes.copy_from_slice(b);
        Ok(Uuid::from_bytes(bytes))
    }

so I tried reducing to 16 characters and it doesn't panic but it generates this

let s = "adea87ff-6a7e-4b".to_string();
let fromslice = uuid::Uuid::from_slice(s.as_bytes())?;
println!("{}", fromslice); // the printed result is: 61646561-3837-6666-2d36-6137652d3462
bangbaew commented 1 year ago

So I think uuid::Uuid::from_str(s.as_str()) should be used as this doesn't panic and returns the correct result:

let s = "adea87ff-6a7e-4b95-90c8-1d6858814988".to_string();
let fromslice = uuid::Uuid::from_str(s.as_str())?;
println!("{}", fromslice); // the printed result is: adea87ff-6a7e-4b95-90c8-1d6858814988
Brendonovich commented 1 year ago

I will investigate this but for future reference please provide a reproduction repo when possible, as a maintainer I want to focus on fixing bugs, not setting up test environments

Brendonovich commented 1 year ago

My guess is that using from_slice is incorrect since it expects the raw bytes of the UUID, not the bytes of the hyphenated string form. from_str is probably the correct one.

bangbaew commented 1 year ago

My guess is that using from_slice is incorrect since it expects the raw bytes of the UUID, not the bytes of the hyphenated string form. from_str is probably the correct one.

ok, so is my information enough or do I still have to setup a new repo?

Brendonovich commented 1 year ago

No need now that we've got it figured out