Skip to content

Commit

Permalink
fix: order by self-relation (#3208)
Browse files Browse the repository at this point in the history
  • Loading branch information
Weakky committed Sep 21, 2022
1 parent 9887882 commit f0b0274
Show file tree
Hide file tree
Showing 4 changed files with 276 additions and 167 deletions.
Expand Up @@ -452,4 +452,111 @@ mod order_by_dependent {

Ok(())
}

fn schema_self_rel() -> String {
let schema = indoc! {
r#"model Parent {
#id(id, Int, @id)
resource Resource @relation("Resource", fields: [resourceId], references: [id], onUpdate: NoAction, onDelete: NoAction)
resourceId Int @unique
}
model Resource {
#id(id, Int, @id)
dependsOnId Int?
dependsOn Resource? @relation("DependsOn", fields: [dependsOnId], references: [id], onUpdate: NoAction, onDelete: NoAction)
dependedOn Resource[] @relation("DependsOn")
parent Parent? @relation("Resource")
}
"#
};

schema.to_owned()
}

// Regression test for: https://github.com/prisma/prisma/issues/12003
#[connector_test(schema(schema_self_rel))]
async fn self_relation_works(runner: Runner) -> TestResult<()> {
run_query!(
&runner,
r#"mutation {
createOneParent(
data: {
id: 1
resource: {
create: {
id: 1
dependsOn: { create: { id: 2, dependsOn: { create: { id: 3 } } } }
}
}
}
) {
id
}
}
"#
);
run_query!(
&runner,
r#"mutation {
createOneParent(
data: {
id: 2
resource: {
create: {
id: 4
dependsOn: { create: { id: 5, dependsOn: { create: { id: 6 } } } }
}
}
}
) {
id
}
}
"#
);

insta::assert_snapshot!(
run_query!(&runner, r#"{
findManyParent(orderBy: { resource: { dependsOn: { id: asc } } }) {
id
resource { dependsOn { id } }
}
}"#),
@r###"{"data":{"findManyParent":[{"id":1,"resource":{"dependsOn":{"id":2}}},{"id":2,"resource":{"dependsOn":{"id":5}}}]}}"###
);
insta::assert_snapshot!(
run_query!(&runner, r#"{
findManyParent(orderBy: { resource: { dependsOn: { id: desc } } }) {
id
resource { dependsOn { id } }
}
}"#),
@r###"{"data":{"findManyParent":[{"id":2,"resource":{"dependsOn":{"id":5}}},{"id":1,"resource":{"dependsOn":{"id":2}}}]}}"###
);

insta::assert_snapshot!(
run_query!(&runner, r#"{
findManyParent(orderBy: { resource: { dependsOn: { dependsOn: { id: asc } } } }) {
id
resource { dependsOn { dependsOn { id } } }
}
}"#),
@r###"{"data":{"findManyParent":[{"id":1,"resource":{"dependsOn":{"dependsOn":{"id":3}}}},{"id":2,"resource":{"dependsOn":{"dependsOn":{"id":6}}}}]}}"###
);
insta::assert_snapshot!(
run_query!(&runner, r#"{
findManyParent(orderBy: { resource: { dependsOn: { dependsOn: { id: desc } } } }) {
id
resource { dependsOn { dependsOn { id } } }
}
}"#),
@r###"{"data":{"findManyParent":[{"id":2,"resource":{"dependsOn":{"dependsOn":{"id":6}}}},{"id":1,"resource":{"dependsOn":{"dependsOn":{"id":3}}}}]}}"###
);

Ok(())
}
}
20 changes: 8 additions & 12 deletions query-engine/connectors/sql-query-connector/src/join_utils.rs
Expand Up @@ -216,7 +216,11 @@ fn compute_aggr_join_m2m(
}
}

pub fn compute_one2m_join(base_model: &ModelRef, rf: &RelationFieldRef, join_prefix: &str) -> AliasedJoin {
pub fn compute_one2m_join(
rf: &RelationFieldRef,
join_prefix: &str,
previous_join: Option<&AliasedJoin>,
) -> AliasedJoin {
let (left_fields, right_fields) = if rf.is_inlined_on_enclosing_model() {
(rf.scalar_fields(), rf.referenced_fields())
} else {
Expand All @@ -226,24 +230,16 @@ pub fn compute_one2m_join(base_model: &ModelRef, rf: &RelationFieldRef, join_pre
)
};

// `rf` is always the relation field on the left model in the join (parent).
let left_table_alias = if rf.model().name != base_model.name {
Some(format!("{}_{}", join_prefix, &rf.model().name))
} else {
None
};

let right_table_alias = format!("{}_{}", join_prefix, &rf.related_model().name);

let related_model = rf.related_model();
let pairs = left_fields.into_iter().zip(right_fields.into_iter());

let on_conditions: Vec<Expression> = pairs
.map(|(a, b)| {
let a_col = if let Some(alias) = left_table_alias.clone() {
Column::from((alias, a.db_name().to_owned()))
} else {
a.as_column()
let a_col = match previous_join {
Some(prev_join) => Column::from((prev_join.alias.to_owned(), a.db_name().to_owned())),
None => a.as_column(),
};

let b_col = Column::from((right_table_alias.clone(), b.db_name().to_owned()));
Expand Down

0 comments on commit f0b0274

Please sign in to comment.