cayleygraph / cayleygraph/cayley

`LoadToDepth` from `schema` with property on depth 0 and depth 1 crashes

Open
#952 1 comment 0 reactions 0 assignees View on GitHub
Dominant language
Go
Stars
15.1k
Forks
1.2k
PR merge metrics
No merged PRs in 30d

Description

**Description**

I am trying to build up an ontology of a service, its endpoint and a TLS configuration and trying to persist it into Cayley and then load it again. If I try to load it again into objects, there seems to be some kind of type confusion between objects on depth 0 and depth 1, resulting into the crash below.

```go
package main

import (
"context"
"fmt"
"log"
"math/rand"

"github.com/cayleygraph/cayley"
"github.com/cayleygraph/cayley/graph"
"github.com/cayleygraph/cayley/schema"
"github.com/cayleygraph/quad"
"github.com/cayleygraph/quad/voc"
)

type TlsConfiguration struct {
rdfType struct{} `quad:"@type > ex:TlsConfig"`

Version string `quad:"ex:version"`
}

type HttpEndpoint struct {
rdfType struct{} `quad:"@type > ex:Http"`

URL string `quad:"ex:url"`
TlsConfig TlsConfiguration `quad:"ex:tls"`
}

type Category struct {
Name string `quad:"ex:name"`
}

type Service struct {
rdfType struct{} `quad:"@type > ex:Service"`

ID quad.IRI `json:"@id"`
HttpEndpoint HttpEndpoint `quad:"ex:http"`
Category Category `quad:"ex:category"`
}

func main() {
store, err := cayley.NewMemoryGraph()
if err != nil {
log.Fatalln(err)
}

voc.RegisterPrefix("ex:", "https://example.io")

sch := schema.NewConfig()
// Override a function to generate IDs. Can be changed to generate UUIDs, for example.
sch.GenerateID = func(_ interface{}) quad.Value {
return quad.BNode(fmt.Sprintf("node%d", rand.Intn(1000)))
}

qw := graph.NewWriter(store)

s1 := &Service{
ID: quad.IRI("s1"),
HttpEndpoint: HttpEndpoint{
URL: "https://example.io",
TlsConfig: TlsConfiguration{
Version: "1.2",
},
},
Category: Category{Name: "An example service"},
}

sch.WriteAsQuads(qw, s1)

s2 := &Service{
ID: quad.IRI("s2"),
HttpEndpoint: HttpEndpoint{
URL: "https://cayley.io",
TlsConfig: TlsConfiguration{
Version: "1.3",
},
},
Category: Category{Name: "A graph service"},
}

sch.WriteAsQuads(qw, s2)

qw.Close()

// Print quads
fmt.Println("\nquads:")
it := store.QuadsAllIterator().Iterate()
defer it.Close()

for it.Next(context.TODO()) {
fmt.Println(store.Quad(it.Result()))
}

var services []Service
sch.LoadToDepth(context.TODO(), store, &services, 1) // depth=0 will work, 1 will crash

for _, v := range services {
fmt.Printf("%+v\n", v)
}
}
```

**Steps to reproduce the issue:**
1. Build up a schema with objects on depth 0 and depth 1
2. Store it
3. Load it

**Received results:**

```
-- ->
_:node81 -- ->
_:node81 -- -> "https://example.io"
_:node887 -- ->
_:node887 -- -> "1.2"
_:node81 -- -> _:node887
-- -> _:node81
_:node847 -- -> "An example service"
-- -> _:node847
-- ->
_:node59 -- ->
_:node59 -- -> "https://cayley.io"
_:node81 -- ->
_:node81 -- -> "1.3"
_:node59 -- -> _:node81
-- -> _:node59
_:node318 -- -> "A graph service"
-- -> _:node318

panic: reflect.Set: value of type main.HttpEndpoint is not assignable to type main.TlsConfiguration
goroutine 1 [running]:

reflect.Value.assignTo(0x100505fc0, 0x140001468a0, 0x199, 0x1004ce012, 0xb, 0x100500a60, 0x0, 0x0, 0x0, 0x0)
/opt/homebrew/Cellar/go/1.16.3/libexec/src/reflect/value.go:2451 +0x3f0
reflect.Value.Set(0x100500a60, 0x140001055d0, 0x199, 0x100505fc0, 0x140001468a0, 0x199)
/opt/homebrew/Cellar/go/1.16.3/libexec/src/reflect/value.go:1564 +0xa4
github.com/cayleygraph/cayley/schema.(*loader).loadIteratorToDepth(0x14000108a20, 0x100520230, 0x14000181b30, 0x100500a60, 0x140001055d0, 0x199, 0x0, 0x100520770, 0x140001217e8, 0x0, ...)
/Users/oxisto/go/pkg/mod/github.com/cayleygraph/cayley@v0.7.7-0.20210518204410-08381efb7f81/schema/loader.go:470 +0x790
github.com/cayleygraph/cayley/schema.(*loader).loadToValue(0x14000108a20, 0x100520230, 0x14000181800, 0x100505fc0, 0x14000147320, 0x199, 0x1, 0x1400018ac48, 0x0, 0x0, ...)
/Users/oxisto/go/pkg/mod/github.com/cayleygraph/cayley@v0.7.7-0.20210518204410-08381efb7f81/schema/loader.go:372 +0xe08
github.com/cayleygraph/cayley/schema.(*loader).loadIteratorToDepth(0x14000108a20, 0x100520230, 0x14000181800, 0x100505fc0, 0x14000147320, 0x199, 0x1, 0x100520770, 0x140001213f8, 0x0, ...)
/Users/oxisto/go/pkg/mod/github.com/cayleygraph/cayley@v0.7.7-0.20210518204410-08381efb7f81/schema/loader.go:511 +0xd58
github.com/cayleygraph/cayley/schema.(*loader).loadToValue(0x14000108a20, 0x100520230, 0x140001096e0, 0x10050b840, 0x14000182780, 0x199, 0x2, 0x1400018b848, 0x0, 0x0, ...)
/Users/oxisto/go/pkg/mod/github.com/cayleygraph/cayley@v0.7.7-0.20210518204410-08381efb7f81/schema/loader.go:372 +0xe08
github.com/cayleygraph/cayley/schema.(*loader).loadIteratorToDepth(0x14000108a20, 0x100520230, 0x140001096e0, 0x1004ef100, 0x140001203f0, 0x197, 0x2, 0x0, 0x0, 0x0, ...)
/Users/oxisto/go/pkg/mod/github.com/cayleygraph/cayley@v0.7.7-0.20210518204410-08381efb7f81/schema/loader.go:511 +0xd58
github.com/cayleygraph/cayley/schema.(*Config).LoadIteratorToDepth(0x1400012c0c0, 0x1005201f8, 0x1400010e008, 0x100521398, 0x14000146000, 0x1004ea340, 0x140001203f0, 0x16, 0x2, 0x0, ...)
/Users/oxisto/go/pkg/mod/github.com/cayleygraph/cayley@v0.7.7-0.20210518204410-08381efb7f81/schema/loader.go:142 +0xa8
github.com/cayleygraph/cayley/schema.(*Config).LoadToDepth(0x1400012c0c0, 0x1005201f8, 0x1400010e008, 0x100521398, 0x14000146000, 0x1004ea340, 0x140001203f0, 0x1, 0x0, 0x0, ...)
/Users/oxisto/go/pkg/mod/github.com/cayleygraph/cayley@v0.7.7-0.20210518204410-08381efb7f81/schema/loader.go:116 +0x240
main.main()
/Users/oxisto/Downloads/cayley-test/main.go:95 +0x750
```

**Expected results:**

I expect it to work - or at least give me a proper error message why it does not.

**Output of `cayley version` or commit hash:**

```
github.com/cayleygraph/cayley v0.7.7-0.20210518204410-08381efb7f81
```

**Environment details:**

Backend database: in-memory

Contributor guide

Open the contributing guide

Research direction

Reproduce the nested schema load with the Go example and inspect schema/loader.go at the reported paths around lines 372, 470, and 511. Trace how depth-0 and depth-1 values are assigned, then verify that LoadToDepth no longer panics and either loads the objects correctly or returns a proper error.

Written by the indexing model from the issue text.

Assessment

Tech stack
go
Domain
databases
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.