Skip to content

Commit

Permalink
wip: support to-one relation and fix serializer
Browse files Browse the repository at this point in the history
  • Loading branch information
Weakky committed Oct 26, 2023
1 parent e2be94c commit 975a05f
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,29 @@ pub(crate) fn coerce_record_with_join(record: &mut Record, rq_indexes: Vec<(usiz
// TODO: find better name
pub(crate) fn coerce_json_relation_to_pv(value: serde_json::Value, q: &RelatedQuery) -> PrismaValue {
match value {
serde_json::Value::Array(values) => PrismaValue::List(
// to-many
serde_json::Value::Array(values) if q.parent_field.is_list() => PrismaValue::List(
values
.into_iter()
.map(|value| coerce_json_relation_to_pv(value, q))
.collect(),
),
// to-one
serde_json::Value::Array(values) => {
let coerced = values
.into_iter()
.next()
.map(|value| coerce_json_relation_to_pv(value, q));

// TODO(HACK): We probably want to update the sql builder instead to not aggregate to-one relations as array
// If the arary is empty, it means there's no relations
if let Some(val) = coerced {
val
// else the relation's null
} else {
PrismaValue::Null
}
}
serde_json::Value::Object(obj) => {
let mut map: Vec<(String, PrismaValue)> = Vec::with_capacity(obj.len());
let related_model = q.parent_field.related_model();
Expand Down
17 changes: 14 additions & 3 deletions query-engine/core/src/response_ir/internal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use schema::{
constants::{aggregations::*, output_fields::*},
*,
};
use std::collections::HashMap;
use std::collections::{HashMap, HashSet};

/// A grouping of items to their parent record.
/// The item implicitly holds the information of the type of item contained.
Expand Down Expand Up @@ -240,7 +240,9 @@ fn serialize_record_selection_with_relations(
query_schema,
),
InnerOutputType::Object(obj) => {
dbg!(&record_selection);
let result = serialize_objects_with_relation(record_selection, obj, query_schema)?;
dbg!(&result);

process_object(field, is_list, result, name)
}
Expand Down Expand Up @@ -346,6 +348,10 @@ fn serialize_objects_with_relation(
.filter_map(|f| model.fields().all().find(|field| field.db_name() == f))
.collect();

// Hack: we convert it to a hashset to support contains with &str as input
// because Vec<String>::contains(&str) doesn't work and we don't want to allocate a string record value
let selected_db_field_names: HashSet<String> = result.fields.into_iter().collect();

for record in result.records.records.into_iter() {
if !object_mapping.contains_key(&record.parent_id) {
object_mapping.insert(record.parent_id.clone(), Vec::new());
Expand All @@ -355,6 +361,11 @@ fn serialize_objects_with_relation(
let mut object = IndexMap::with_capacity(values.len());

for (val, field) in values.into_iter().zip(fields.iter()) {
// Skip fields that aren't part of the selection set
if !selected_db_field_names.contains(field.name()) {
continue;
}

let out_field = typ.find_field(field.name()).unwrap();

match field {
Expand Down Expand Up @@ -409,12 +420,12 @@ fn serialize_relation_selection(
let db_field_names = &rrs.fields;
let fields: Vec<_> = db_field_names
.iter()
.filter_map(|f| rrs.model.fields().all().find(|field| field.db_name() == f))
.filter_map(|f| rrs.model.fields().all().find(|field| field.name() == f))
.collect();

for field in fields {
let out_field = typ.find_field(field.name()).unwrap();
let value = value_obj.remove(field.name()).unwrap();
let value = value_obj.remove(field.db_name()).unwrap();

match field {
Field::Scalar(_) if !out_field.field_type().is_object() => {
Expand Down

0 comments on commit 975a05f

Please sign in to comment.