Skip to content

Commit

Permalink
hack: filter null values from joined JSON arrays
Browse files Browse the repository at this point in the history
  • Loading branch information
Weakky committed Dec 4, 2023
1 parent 6e804a0 commit 8109c3f
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,49 @@ mod m2m {
Ok(())
}

fn schema() -> String {
let schema = indoc! {
r#"model Item {
id Int @id @default(autoincrement())
categories Category[]
createdAt DateTime @default(now())
updatedAt DateTime? @updatedAt
}
model Category {
id Int @id @default(autoincrement())
items Item[]
createdAt DateTime @default(now())
updatedAt DateTime? @updatedAt
}"#
};

schema.to_owned()
}

// https://github.com/prisma/prisma/issues/16390
#[connector_test(schema(schema), relation_mode = "prisma", only(Postgres))]
async fn repro_16390(runner: Runner) -> TestResult<()> {
run_query!(&runner, r#"mutation { createOneCategory(data: {}) { id } }"#);
run_query!(
&runner,
r#"mutation { createOneItem(data: { categories: { connect: { id: 1 } } }) { id } }"#
);
run_query!(&runner, r#"mutation { deleteOneItem(where: { id: 1 }) { id } }"#);

insta::assert_snapshot!(
run_query!(&runner, r#"{ findUniqueItem(where: { id: 1 }) { id categories { id } } }"#),
@r###"{"data":{"findUniqueItem":null}}"###
);

insta::assert_snapshot!(
run_query!(&runner, r#"{ findUniqueCategory(where: { id: 1 }) { id items { id } } }"#),
@r###"{"data":{"findUniqueCategory":{"id":1,"items":[]}}}"###
);

Ok(())
}

async fn test_data(runner: &Runner) -> TestResult<()> {
runner
.query(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,18 @@ fn coerce_json_relation_to_pv(value: serde_json::Value, rs: &RelationSelection)
match value {
// one-to-many
serde_json::Value::Array(values) if rs.field.is_list() => {
let iter = values.into_iter().map(|value| coerce_json_relation_to_pv(value, rs));
let iter = values.into_iter().filter_map(|value| {
// FIXME: In the case of m2m relations, the aggregation produces null values if the B side of the m2m table points to a record that doesn't exist.
// FIXME: This only seems to happen because of a bug with `relationMode=prisma`` which doesn't cleanup the relation table properly when deleting records that belongs to a m2m relation.
// FIXME: This hack filters down the null values from the array, but we should fix the root cause instead, if possible.
// FIXME: In theory, the aggregated array should only contain objects, which are the joined rows.
// FIXME: See m2m.rs::repro_16390 for a reproduction.
if value.is_null() && rs.field.relation().is_many_to_many() {
None
} else {
Some(coerce_json_relation_to_pv(value, rs))
}
});

// Reverses order when using negative take.
let iter = match rs.args.needs_reversed_order() {
Expand Down Expand Up @@ -75,7 +86,7 @@ fn coerce_json_relation_to_pv(value: serde_json::Value, rs: &RelationSelection)

Ok(PrismaValue::Object(map))
}
_ => unreachable!(),
x => unreachable!("Unexpected value when deserializing JSON relation data: {x:?}"),
}
}

Expand Down

0 comments on commit 8109c3f

Please sign in to comment.