Skip to content

[query_as!] Incorrect nullability inferred on left join leading to a runtime exception #2127

@jetaggart

Description

@jetaggart

Bug Description

When doing a left join, sqlx infers a column as non-nullable vs an option.

Minimal Reproduction

#[derive(Clone)]
pub struct PlantWithUserDetails {
    pub id: Uuid,
    pub in_garden_at: Option<DateTime<Utc>>,
}

// ...
        let res  = sqlx::query_as!(PlantWithUserDetails, r#"
            SELECT plants.*, up.created_at as in_garden_at
            FROM plants
            LEFT JOIN user_plants up on plants.id = up.plant_id and up.user_id = $1
            WHERE plants.id = $2
        "#, id, user_id)
            .fetch_one(&self.db)
            .await?;

Leads to:

error[E0308]: mismatched types
  --> src/plant/plant_repo.rs:62:20
   |
62 |           let res  = sqlx::query_as!(PlantWithUserDetails, r#"
   |  ____________________^
63 | |             SELECT plants.*, up.created_at as in_garden_at
64 | |             FROM plants
65 | |             LEFT JOIN user_plants up on plants.id = up.plant_id and up.user_id = $1
66 | |             WHERE plants.id = $2
67 | |         "#, user_id, id)
   | |________________________^ expected enum `std::option::Option`, found struct `DateTime`
   |
   = note: expected enum `std::option::Option<DateTime<_>>`
            found struct `DateTime<_>`

If I change my struct to match:

#[derive(Clone)]
pub struct PlantWithUserDetails {
    pub id: Uuid,
    pub in_garden_at: DateTime<Utc>,
}

I end up with a runtime exception:

occurred while decoding column 4: unexpected null; try decoding as an `Option`

Caused by:
    unexpected null; try decoding as an `Option`

Info

  • SQLx version: 0.6.2
  • SQLx features enabled: ["runtime-tokio-native-tls", "postgres", "uuid", "chrono", "offline"]
  • Database server and version: Postgres 14
  • Operating system: macos
  • rustc --version: rustc 1.64.0 (a55dd71d5 2022-09-19)

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions