diesel-rs / diesel

A safe, extensible ORM and Query Builder for Rust
https://diesel.rs
Apache License 2.0
12.79k stars 1.08k forks source link

`Nullable<Varchar>` generated instead of `Varchar` #4319

Closed SamuelMarks closed 1 month ago

SamuelMarks commented 1 month ago

Setup

Versions

Feature Flags

Problem Description

What are you trying to accomplish?

#[derive(Queryable, Selectable, PartialEq, Debug)]
#[diesel(table_name = crate::schema::users)]
#[diesel(check_for_backend(diesel::pg::Pg))]
pub struct User {
    pub username: String,
    pub password_hash: String,
    pub role: String,
    pub created_at: std::time::SystemTime,
}
CREATE TABLE "users"
(
    username      VARCHAR(50) PRIMARY KEY,
    password_hash VARCHAR(50) NOT NULL,
    role          TEXT        NOT NULL DEFAULT 'regular',
    created_at    TIMESTAMP   NOT NULL DEFAULT current_timestamp
);

What is the expected output?

schema.rs of

diesel::table! {
    users (username) {
        #[max_length = 50]
        username -> Varchar,
        #[max_length = 50]
        password_hash -> Varchar,
        role -> Text,
        created_at -> Timestamp,
    }
}

What is the actual output?

schema.rs of

diesel::table! {
    users (username) {
        #[max_length = 50]
        username -> Varchar,
        #[max_length = 50]
        password_hash -> Nullable<Varchar>,
        role -> Nullable<Text>,
        created_at -> Timestamp,
    }
}

Are you seeing any additional errors?

No

Steps to reproduce

https://github.com/offscale/rust-actix-diesel-auth-scaffold/tree/2f01d2b

Checklist

weiznich commented 1 month ago

I cannot reproduce this locally. Additionally diesel does "only" query the database to get information whether or not a column is nullable. So if your schema.rs file says that the column is nullable the database considers it to be nullable. You should be able to verify this by using the following query:

SELECT "information_schema"."columns"."column_name", "information_schema"."columns"."udt_name", "information_schema"."columns"."udt_schema", "information_schema"."columns"."is_nullable", "information_schema"."columns"."character_maximum_length", col_description('users'::regclass, "information_schema"."columns"."ordinal_position") FROM "information_schema"."columns" WHERE (("information_schema"."columns"."table_name" = 'users') AND ("information_schema"."columns"."table_schema" = 'public')) ORDER BY "information_schema"."columns"."ordinal_position"

Please provide the output of that query for further debugging, otherwise this issue will likely be closed as cannot reproduce.

SamuelMarks commented 1 month ago

Try deleting the schema.rs file. Then run that diesel command again and you'll see it get regenerated. It has Nullables; it shouldn't.

And to answer your question:

  column_name  | udt_name  | udt_schema | is_nullable | character_maximum_length | col_description 
---------------+-----------+------------+-------------+--------------------------+-----------------
 username      | varchar   | pg_catalog | NO          |                       50 | 
 password_hash | varchar   | pg_catalog | YES         |                       50 | 
 role          | text      | pg_catalog | YES         |                          | 
 created_at    | timestamp | pg_catalog | NO          |                          | 
(4 rows)
weiznich commented 1 month ago

Thanks for providing the output of that query. This output clearly shows that the database allows nullable values for these columns. At this point it's likely that the provided SQL does not match that SQL what you actually used to create the table. The other possibility is a bug in the database system itself.

Both variants are not an issue in diesel, so I will close this issue now.