-
Notifications
You must be signed in to change notification settings - Fork 1.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[query_as!] Incorrect nullability inferred on left join leading to a runtime exception #2127
Comments
Please provide the relevant database schema as well as the output of |
create table plants
(
id uuid default gen_random_uuid() not null
primary key,
name text not null
constraint plants_name_uniq
unique,
created_at timestamp with time zone default now() not null,
updated_at timestamp with time zone not null
);
create table user_plants
(
id uuid default gen_random_uuid() not null
primary key,
user_id text not null,
plant_id uuid not null
references plants,
created_at timestamp with time zone default now() not null,
updated_at timestamp with time zone not null,
unique (user_id, plant_id)
); [
{
"Plan": {
"Node Type": "Nested Loop",
"Parallel Aware": false,
"Async Capable": false,
"Join Type": "Left",
"Startup Cost": 0.00,
"Total Cost": 2.35,
"Plan Rows": 1,
"Plan Width": 72,
"Output": ["plants.id", "plants.name", "plants.created_at", "plants.updated_at", "up.created_at"],
"Inner Unique": true,
"Join Filter": "(plants.id = up.plant_id)",
"Plans": [
{
"Node Type": "Seq Scan",
"Parent Relationship": "Outer",
"Parallel Aware": false,
"Async Capable": false,
"Relation Name": "plants",
"Schema": "public",
"Alias": "plants",
"Startup Cost": 0.00,
"Total Cost": 1.29,
"Plan Rows": 1,
"Plan Width": 64,
"Output": ["plants.id", "plants.name", "plants.created_at", "plants.updated_at"],
"Filter": "(plants.id = '11c1229c-c71c-41e6-8b55-771437202390'::uuid)"
},
{
"Node Type": "Seq Scan",
"Parent Relationship": "Inner",
"Parallel Aware": false,
"Async Capable": false,
"Relation Name": "user_plants",
"Schema": "public",
"Alias": "up",
"Startup Cost": 0.00,
"Total Cost": 1.04,
"Plan Rows": 1,
"Plan Width": 24,
"Output": ["up.id", "up.user_id", "up.plant_id", "up.created_at", "up.updated_at"],
"Filter": "((up.plant_id = '11c1229c-c71c-41e6-8b55-771437202390'::uuid) AND (up.user_id = '11c1229c-c71c-41e6-8b55-771437202390'::text))"
}
]
}
}
] |
Can confirm the bug still exists in sqlx v0.6.2 with rustc 1.67.0-nightly. Workaround attempt with
|
I had a similar query that worked before adding an sqlx::query!(
"SELECT nt.id, user_id, title, subtitle
FROM notification_types nt
LEFT JOIN opted_out_notification_types
ON notification_type = nt.id AND opted_out_notification_types.user_id = $1
ORDER BY title
",
user_id
).fetch_all(&mut conn)
.await
.context("Trying to fetch all notification types")?
.into_iter()
.map(|r| NotificationTypeRow {
id: r.id,
title: r.title,
subtitle: r.subtitle,
opted_in: r.user_id.is_none(),
}) The above failed to compile because I've got a workaround by overriding the type but I rather not rely on this too much sqlx::query!(
r#"SELECT nt.id, user_id as "user_id?", title, subtitle
FROM notification_types nt
LEFT JOIN opted_out_notification_types
ON notification_type = nt.id AND opted_out_notification_types.user_id = $1
ORDER BY title
"#,
user_id
)
.fetch_all(&mut conn)
.await
.context("Trying to fetch all notification types")?
.into_iter()
.map(|r| NotificationTypeRow {
id: r.id,
title: r.title,
subtitle: r.subtitle,
opted_in: r.user_id.is_none(),
}) |
I think with |
Can confirm sqlx is inferring non-Option for left joins in 0.7 as well. As a workaround, you can use |
I'm also having this issue and it seems to be caused by the For example, the column in this simple left join is correctly inferred as SELECT
foo.id,
bar.foo_id -- Option<T>
FROM
foo
LEFT JOIN bar ON bar.foo_id = foo.id But adding a SELECT
foo.id,
bar.foo_id -- T
FROM
foo
LEFT JOIN bar ON bar.foo_id = foo.id
WHERE
foo.id = $1 Strangely, using SELECT
foo.id,
bar.foo_id -- Option<T>
FROM
foo
LEFT JOIN bar ON bar.foo_id = foo.id
AND foo.id = $1 |
Bug Description
When doing a left join, sqlx infers a column as non-nullable vs an option.
Minimal Reproduction
Leads to:
If I change my struct to match:
I end up with a runtime exception:
Info
rustc --version
: rustc 1.64.0 (a55dd71d5 2022-09-19)The text was updated successfully, but these errors were encountered: