Skip to content

Commit 3375cbb

Browse files
committed
store: Abstract to_entity as deserialize_with_layout
1 parent d0e62f1 commit 3375cbb

File tree

2 files changed

+47
-20
lines changed

2 files changed

+47
-20
lines changed

store/postgres/src/relational.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -496,7 +496,7 @@ impl Layout {
496496
FindQuery::new(table.as_ref(), id, block)
497497
.get_result::<EntityData>(conn)
498498
.optional()?
499-
.map(|entity_data| entity_data.to_entity(self))
499+
.map(|entity_data| entity_data.deserialize_with_layout(self))
500500
.transpose()
501501
}
502502

@@ -521,7 +521,7 @@ impl Layout {
521521
entities_for_type
522522
.entry(data.entity_type())
523523
.or_default()
524-
.push(data.to_entity(self)?);
524+
.push(data.deserialize_with_layout(self)?);
525525
}
526526
Ok(entities_for_type)
527527
}
@@ -619,7 +619,11 @@ impl Layout {
619619
log_query_timing(logger, &query_clone, start.elapsed(), values.len());
620620
values
621621
.into_iter()
622-
.map(|entity_data| entity_data.to_entity(self).map_err(|e| e.into()))
622+
.map(|entity_data| {
623+
entity_data
624+
.deserialize_with_layout(self)
625+
.map_err(|e| e.into())
626+
})
623627
.collect()
624628
}
625629

store/postgres/src/relational_queries.rs

Lines changed: 40 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -171,14 +171,40 @@ impl ForeignKeyClauses for Column {
171171
}
172172
}
173173

174-
trait FromColumnValue: Sized {
174+
pub trait FromEntityData: Default {
175+
type Value: FromColumnValue;
176+
177+
fn insert_entity_data(&mut self, key: String, v: Self::Value);
178+
}
179+
180+
impl FromEntityData for Entity {
181+
type Value = graph::prelude::Value;
182+
183+
fn insert_entity_data(&mut self, key: String, v: Self::Value) {
184+
self.insert(key, v);
185+
}
186+
}
187+
188+
pub trait FromColumnValue: Sized {
189+
fn is_null(&self) -> bool;
190+
191+
fn from_string(s: String) -> Self;
192+
175193
fn from_column_value(
176194
column_type: &ColumnType,
177195
json: serde_json::Value,
178196
) -> Result<Self, StoreError>;
179197
}
180198

181199
impl FromColumnValue for graph::prelude::Value {
200+
fn is_null(&self) -> bool {
201+
self == &Value::Null
202+
}
203+
204+
fn from_string(s: String) -> Self {
205+
Value::String(s)
206+
}
207+
182208
fn from_column_value(
183209
column_type: &ColumnType,
184210
json: serde_json::Value,
@@ -276,36 +302,33 @@ impl EntityData {
276302
self.entity.clone()
277303
}
278304

279-
/// Map the `EntityData` to an entity using the schema information
280-
/// in `Layout`
281-
pub fn to_entity(self, layout: &Layout) -> Result<Entity, StoreError> {
305+
/// Map the `EntityData` using the schema information in `Layout`
306+
pub fn deserialize_with_layout<T: FromEntityData>(
307+
self,
308+
layout: &Layout,
309+
) -> Result<T, StoreError> {
282310
let table = layout.table_for_entity(&self.entity)?;
283311

284312
use serde_json::Value as j;
285313
match self.data {
286314
j::Object(map) => {
287-
let mut entity = Entity::new();
288-
entity.insert(
289-
"__typename".to_owned(),
290-
graph::prelude::Value::from(self.entity),
291-
);
315+
let mut out = T::default();
316+
out.insert_entity_data("__typename".to_owned(), T::Value::from_string(self.entity));
292317
for (key, json) in map {
293318
// Simply ignore keys that do not have an underlying table
294319
// column; those will be things like the block_range that
295320
// is used internally for versioning
296321
if key == "g$parent_id" {
297-
let value =
298-
graph::prelude::Value::from_column_value(&ColumnType::String, json)?;
299-
entity.insert("g$parent_id".to_owned(), value);
322+
let value = T::Value::from_column_value(&ColumnType::String, json)?;
323+
out.insert_entity_data("g$parent_id".to_owned(), value);
300324
} else if let Some(column) = table.column(&SqlName::verbatim(key)) {
301-
let value =
302-
graph::prelude::Value::from_column_value(&column.column_type, json)?;
303-
if value != Value::Null {
304-
entity.insert(column.field.clone(), value);
325+
let value = T::Value::from_column_value(&column.column_type, json)?;
326+
if !value.is_null() {
327+
out.insert_entity_data(column.field.clone(), value);
305328
}
306329
}
307330
}
308-
Ok(entity)
331+
Ok(out)
309332
}
310333
_ => unreachable!(
311334
"we use `to_json` in our queries, and will therefore always get an object back"

0 commit comments

Comments
 (0)