Skip to content

query_as! does not recognize Option<T> in some left join queries #3408

@demhadais

Description

@demhadais

Bug Description

If you run a query with a left join and a where condition outside the left join, sqlx yells at you during runtime (not compile time) with the following error:

error occurred while decoding column <col_number>: unexpected null; try decoding as an `Option`

even if you read the column into an Option<T>. However, if you put that condition inside the left join, it works fine.

Minimal Reproduction

Here's a contrived example with two tables, employee and department:

schema.sql:

create table department (
    id serial primary key,
    name text not null
);

create table employee (
    name text primary key,
    department_id integer references department
);

main.rs:

struct QueryResult {
    employee_name: String,
    department_name: Option<String>,
}

#[tokio::main]
async fn main() {
    let pool = sqlx::postgres::PgPool::connect("postgres://localhost/sqlx-mre")
        .await
        .unwrap();

    sqlx::query!("insert into employee (name) values ('ahmed')")
        .execute(&pool)
        .await
        .unwrap();


    // This works!
    let good_query_result = sqlx::query_as!(
        QueryResult,

        "
        select
            employee.name as employee_name,
            department.name as department_name
        from employee
        left join
            department
            on
                employee.department_id = department.id
                and employee.name = $1
        ",

        "ahmed"
    )
    .fetch_one(&pool)
    .await
    .unwrap();

    // This doesn't
    let bad_query_result = sqlx::query_as!(
        QueryResult,

        "select
            employee.name as employee_name,
            department.name as department_name
        from employee
        left join
            department
            on employee.department_id = department.id
        where employee.name = $1",
        
        "ahmed"
    )
    .fetch_one(&pool)
    .await
    .unwrap();
}
    /*
    thread 'main' panicked at src/main.rs:57:6:
    called `Result::unwrap()` on an `Err` value: ColumnDecode { index: "1", source: UnexpectedNullError }
    */

I believe this is a bug with sqlx because each query returns the expected (and same) result when run in a psql shell.

PS: I know issue #3336 exists, but I don't think it's quite the same.

Info

  • SQLx version: 0.8.0
  • SQLx features enabled: ["postgres", "macros", "uuid", "runtime-tokio"]
  • Database server and version: Postgres 16.3
  • Operating system: macos Sonoma 14.5
  • rustc --version: 1.80

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