diff --git a/graph/src/components/store/write.rs b/graph/src/components/store/write.rs index e1c079103eb..8c9671cb347 100644 --- a/graph/src/components/store/write.rs +++ b/graph/src/components/store/write.rs @@ -474,6 +474,27 @@ impl RowGroup { if self.immutable { match row { EntityModification::Insert { .. } => { + // Check if this is an attempt to overwrite an immutable + // entity. We allow overwriting immutable entities in + // the same block, but not across blocks; if such an + // attempt happens across two batches, it would result + // in a database constraint violation. This check is + // simply here to provide a friendlier error message and + // to raise the error earlier, before we actually write + // to the database + match self + .last_mod + .get(row.id()) + .and_then(|&idx| self.rows.get(idx)) + { + Some(prev) if prev.block() != row.block() => { + return Err(StoreError::Input( + format!("entity {} is immutable; inserting it at block {} is not possible as it was already inserted at block {}", + row.key(), row.block(), prev.block()))); + } + _ => { /* nothing to check */ } + } + self.push_row(row); } EntityModification::Overwrite { .. } | EntityModification::Remove { .. } => { diff --git a/graph/src/schema/entity_key.rs b/graph/src/schema/entity_key.rs index 520d3d6320a..3a5a8581a3c 100644 --- a/graph/src/schema/entity_key.rs +++ b/graph/src/schema/entity_key.rs @@ -59,3 +59,17 @@ impl std::fmt::Debug for EntityKey { ) } } + +impl std::fmt::Display for EntityKey { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + if self.causality_region == CausalityRegion::ONCHAIN { + write!(f, "{}[{}]", self.entity_type, self.entity_id) + } else { + write!( + f, + "{}/{}[{}]", + self.entity_type, self.causality_region, self.entity_id + ) + } + } +}