sqlx icon indicating copy to clipboard operation
sqlx copied to clipboard

Uppercase enum type is not being double quoted when fetching Oid.

Open Andrepuel opened this issue 1 year ago • 1 comments

Bug Description

When binding a parameter that is of a custom type (enum in my test case), if the custom type name has uppercase letters, then double quote should be used. It appears that it is not being used, as the error message prints the type back in lower case.

Minimal Reproduction

schema.sql

CREATE TYPE public."RecordStatus" AS ENUM (
    'ACTIVE',
    'INACTIVE'
);


#[derive(sqlx::Type)]
enum RecordStatus {
    #[sqlx(rename = "ACTIVE")] Active,
    #[sqlx(rename = "INACTIVE")] Inactive,
}

async fn bad_param(conn: &mut sqlx::PgConnection) {
    sqlx::query("INSERT INTO a VALUE ($1)").bind(RecordStatus::Active).execute(conn.as_mut()).await.unwrap();
}

// Error message: type "recordstatus" does not exist

Workaround

Adding the attribute #[sqlx(type_name = "\"Currency\"")] fixes the problem for insertions. But then queries will not work.

Remarks

If we were to added the double quotes for every custom type, this would probably break compatibility. I believe that there are many people taking advantage of the fact that postgres will lowercase the type name. For example, you may have CREATE TYPE currency on the database, and enum Currency on the rust code and it would work.

Unfortunately I am working with an already existing database, thus I can not change the name of the types.

Info

  • SQLx version: 0.7.3
  • SQLx features enabled: "postgres", "runtime-tokio", "tls-native-tls", "bigdecimal", "time"
  • Database server and version: Debian 16.1-1.pgdg120+1 / (Docker image: postgres:16.1)
  • Operating system: Linux
  • rustc --version: 1.75

Andrepuel avatar Feb 13 '24 13:02 Andrepuel

I am sometimes (!) seeing a similar bug that makes my CI tests flaky since I updated from sqlx 0.5.7 to 0.7.4. I have a few enums, named in camelcase, like the one below.

#[derive(Clone, Copy, Debug, Deserialize, derive_more::Display, Serialize, sqlx::Type)]
#[sqlx(type_name = "MyEnum", rename_all = "lowercase")]
#[serde(rename_all = "PascalCase")]
pub enum MyEnum {
  ...
}

In postgres I have something like

CREATE TYPE public."myEnum" AS ENUM ...

The error is

"type "myenum" does not exist"

When the test fails its always the same ones that write to the DB, however, there are times where the test passes. The particular tests even have 3 retries, so when I see it fail, it already failed three consecutive times. I have observed instances where I got the error locally for one run, while everything was fine on the next run against the same database instance/rust server with the same sqlx pool. I have never seen this on reads (those tests pass in the same test run). Nor have I seen the error on the old 0.5.7 version I was using. I went with renaming those enums to lowercase for now

DeppLearning avatar Apr 10 '24 19:04 DeppLearning