Skip to content

Commit aeacbeb

Browse files
committed
graph, store : fix loadRelated not working with Bytes as id
1 parent e0d90c2 commit aeacbeb

File tree

7 files changed

+99
-16
lines changed

7 files changed

+99
-16
lines changed

graph/src/components/store/entity_cache.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -199,13 +199,14 @@ impl EntityCache {
199199
&mut self,
200200
eref: &LoadRelatedRequest,
201201
) -> Result<Vec<Entity>, anyhow::Error> {
202-
let (base_type, field) = self.schema.get_field_related(eref)?;
202+
let (base_type, field, id_is_bytes) = self.schema.get_field_related(eref)?;
203203

204204
let query = DerivedEntityQuery {
205205
entity_type: EntityType::new(base_type.to_string()),
206206
entity_field: field.name.clone().to_snake_case().into(),
207207
value: eref.entity_id.clone(),
208208
causality_region: eref.causality_region,
209+
id_is_bytes: id_is_bytes,
209210
};
210211

211212
let entities = self.store.get_derived(&query)?;

graph/src/components/store/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,8 @@ pub struct DerivedEntityQuery {
188188
pub entity_field: Word,
189189
/// The value to compare against
190190
pub value: Word,
191+
/// Boolean indicating if the id is of the type `Bytes`
192+
pub id_is_bytes: bool,
191193

192194
/// This is the causality region of the data source that created the entity.
193195
///

graph/src/schema/input_schema.rs

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,34 @@ impl InputSchema {
120120
///
121121
/// When asked to load the related entities from "Account" in the field "wallets"
122122
/// This function will return the type "Wallet" with the field "account"
123-
pub fn get_field_related(&self, key: &LoadRelatedRequest) -> Result<(&str, &s::Field), Error> {
123+
pub fn get_field_related(
124+
&self,
125+
key: &LoadRelatedRequest,
126+
) -> Result<(&str, &s::Field, bool), Error> {
127+
let id_field = self
128+
.inner
129+
.schema
130+
.document
131+
.get_object_type_definition(key.entity_type.as_str())
132+
.ok_or_else(|| {
133+
anyhow!(
134+
"Entity {}[{}]: unknown entity type `{}`",
135+
key.entity_type,
136+
key.entity_id,
137+
key.entity_type,
138+
)
139+
})?
140+
.field("id")
141+
.ok_or_else(|| {
142+
anyhow!(
143+
"Entity {}[{}]: unknown field `{}`",
144+
key.entity_type,
145+
key.entity_id,
146+
key.entity_field,
147+
)
148+
})?;
149+
150+
let id_is_bytes = id_field.field_type.get_base_type() == "Bytes";
124151
let field = self
125152
.inner
126153
.schema
@@ -171,7 +198,7 @@ impl InputSchema {
171198
)
172199
})?;
173200

174-
Ok((base_type, field))
201+
Ok((base_type, field, id_is_bytes))
175202
} else {
176203
Err(anyhow!(
177204
"Entity {}[{}]: field `{}` is not derived",

store/postgres/src/relational_queries.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1739,6 +1739,7 @@ impl<'a> QueryFragment<Pg> for FindDerivedQuery<'a> {
17391739
entity_field,
17401740
value: entity_id,
17411741
causality_region,
1742+
id_is_bytes,
17421743
} = self.derived_query;
17431744

17441745
// Generate
@@ -1765,7 +1766,13 @@ impl<'a> QueryFragment<Pg> for FindDerivedQuery<'a> {
17651766
}
17661767
out.push_identifier(entity_field.as_str())?;
17671768
out.push_sql(" = ");
1768-
out.push_bind_param::<Text, _>(&entity_id.as_str())?;
1769+
if *id_is_bytes {
1770+
out.push_sql("decode(");
1771+
out.push_bind_param::<Text, _>(&entity_id.as_str().strip_prefix("0x").unwrap())?;
1772+
out.push_sql(", 'hex')");
1773+
} else {
1774+
out.push_bind_param::<Text, _>(&entity_id.as_str())?;
1775+
}
17691776
out.push_sql(" and ");
17701777
if self.table.has_causality_region {
17711778
out.push_sql("causality_region = ");

tests/integration-tests/derived-loaders/schema.graphql

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,14 @@
1+
type BFoo @entity {
2+
id: Bytes!
3+
value: Int8!
4+
bar: BBar! @derivedFrom(field: "fooValue")
5+
}
6+
7+
type BBar @entity {
8+
id: Bytes!
9+
fooValue: BFoo!
10+
}
11+
112
type Foo @entity {
213
id: ID!
314
value: Int8!
Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,34 @@
1+
import { Bytes, store } from "@graphprotocol/graph-ts";
12
import { Trigger } from "../generated/Contract/Contract";
2-
import { Bar, Foo } from "../generated/schema";
3+
import { Bar, Foo, BFoo, BBar } from "../generated/schema";
34

45
export function handleTrigger(event: Trigger): void {
5-
let obj = new Foo("0");
6-
obj.value = 1;
7-
obj.save();
6+
let foo = new Foo("0");
7+
foo.value = 1;
8+
foo.save();
89

9-
let obj2 = new Bar("1");
10-
obj2.fooValue = "0";
11-
obj2.save();
10+
let bar = new Bar("1");
11+
bar.fooValue = "0";
12+
bar.save();
1213

13-
let obj3 = Foo.load("0");
14-
let obj4 = obj3!.bar.load();
14+
let fooLoaded = Foo.load("0");
1515

16+
let barDerived = fooLoaded!.bar.load();
1617

17-
assert(obj4 !== null, "obj4 should not be null");
18+
assert(barDerived !== null, "barDerived should not be null");
19+
20+
let bFoo = new BFoo(Bytes.fromUTF8("0"));
21+
bFoo.value = 1;
22+
bFoo.save();
23+
24+
let bBar = new BBar(Bytes.fromUTF8("1"));
25+
bBar.fooValue = Bytes.fromUTF8("0");
26+
bBar.save();
27+
28+
let bFooLoaded = BFoo.load(Bytes.fromUTF8("0"));
29+
let bBarDerived = changetype<Bar[]>(
30+
store.loadRelated("BFoo", bFooLoaded!.id.toHexString(), "bar")
31+
);
32+
33+
assert(bBarDerived !== null, "bBarDerived should not be null");
1834
}

tests/integration-tests/derived-loaders/test/test.js

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,27 @@ contract("Contract", (accounts) => {
7979
await waitForSubgraphToBeSynced();
8080
});
8181

82-
it("test query", async () => {
83-
// Also test that multiple block constraints do not result in a graphql error.
82+
it("should return correct BFoos", async () => {
83+
let result = await fetchSubgraph({
84+
query: `{
85+
bfoos(orderBy: id) { id value bar { id } }
86+
}`,
87+
});
88+
89+
expect(result.errors).to.be.undefined;
90+
expect(result.data).to.deep.equal({
91+
bfoos: [
92+
{
93+
id: "0x30",
94+
value: "1",
95+
bar: { id: "0x31" },
96+
},
97+
],
98+
});
99+
});
100+
101+
102+
it("should return correct Foos", async () => {
84103
let result = await fetchSubgraph({
85104
query: `{
86105
foos(orderBy: id) { id value bar { id } }

0 commit comments

Comments
 (0)