Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LoadToDepth from schema with property on depth 0 and depth 1 crashes #952

Open
oxisto opened this issue May 19, 2021 · 1 comment
Open

Comments

@oxisto
Copy link
Contributor

oxisto commented May 19, 2021

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.

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:

<s1> -- <rdf:type> -> <ex:Actor>
_:node81 -- <rdf:type> -> <ex:Http>
_:node81 -- <ex:url> -> "https://example.io"
_:node887 -- <rdf:type> -> <ex:TlsConfig>
_:node887 -- <ex:version> -> "1.2"
_:node81 -- <ex:tls> -> _:node887
<s1> -- <ex:http> -> _:node81
_:node847 -- <ex:name> -> "An example service"
<s1> -- <ex:category> -> _:node847
<s2> -- <rdf:type> -> <ex:Actor>
_:node59 -- <rdf:type> -> <ex:Http>
_:node59 -- <ex:url> -> "https://cayley.io"
_:node81 -- <rdf:type> -> <ex:TlsConfig>
_:node81 -- <ex:version> -> "1.3"
_:node59 -- <ex:tls> -> _:node81
<s2> -- <ex:http> -> _:node59
_:node318 -- <ex:name> -> "A graph service"
<s2> -- <ex:category> -> _: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

@oxisto
Copy link
Contributor Author

oxisto commented May 19, 2021

It seems to work if you add a @id annotation to the URL field of the HttpEndpoint, so that it is not a non-named node. I will try to create a PR that adds this caveat to the documentation and check whether we can avoid the panic.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant