123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743 |
- /*
- * EliasDB
- *
- * Copyright 2016 Matthias Ladkau. All rights reserved.
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
- */
- package interpreter
- import (
- "errors"
- "fmt"
- "strings"
- "testing"
- "devt.de/krotik/eliasdb/eql/parser"
- "devt.de/krotik/eliasdb/graph"
- "devt.de/krotik/eliasdb/graph/data"
- "devt.de/krotik/eliasdb/graph/graphstorage"
- "devt.de/krotik/eliasdb/graph/util"
- "devt.de/krotik/eliasdb/hash"
- "devt.de/krotik/eliasdb/storage"
- )
- type testNodeInfo struct {
- *defaultNodeInfo
- }
- func (ni *testNodeInfo) SummaryAttributes(kind string) []string {
- return []string{"key"}
- }
- /*
- Helper function to run a search and check against a result.
- */
- func runSearch(query string, expectedResult string, rt parser.RuntimeProvider) error {
- ast, err := parser.ParseWithRuntime("test", query, rt)
- if err != nil {
- return err
- }
- res, err := ast.Runtime.Eval()
- if err != nil {
- return err
- }
- res.(*SearchResult).StableSort()
- if fmt.Sprint(res) != expectedResult {
- return errors.New(fmt.Sprint("Unexpected search result:", res, err))
- }
- return nil
- }
- func TestLookup(t *testing.T) {
- gm, _ := simpleGraph()
- rt := NewLookupRuntimeProvider("test", "main", gm, NewDefaultNodeInfo(gm))
- if err := runSearch("lookup mynode '000', '123'", `
- Labels: Mynode Key, Name
- Format: auto, auto
- Data: 1:n:key, 1:n:Name
- 000, Node0
- 123, Node1
- `[1:], rt); err != nil {
- t.Error(err)
- return
- }
- if err := runSearch("lookup mynode '000', '123' where true", `
- Labels: Mynode Key, Name
- Format: auto, auto
- Data: 1:n:key, 1:n:Name
- 000, Node0
- 123, Node1
- `[1:], rt); err != nil {
- t.Error(err)
- return
- }
- }
- func TestMultiKindTraversal(t *testing.T) {
- gm := multiKindGraph()
- rt := NewGetRuntimeProvider("test", "main", gm, NewDefaultNodeInfo(gm))
- // Test simple traversal and setting of primary kind
- if err := runSearch("get mynode0 traverse :::", `
- Labels: Mynode0 Key, Name, Type, Key, Kind, Name
- Format: auto, auto, auto, auto, auto, auto
- Data: 1:n:key, 1:n:Name, 1:n:Type, 2:n:key, 2:n:kind, 2:n:name
- 000, Node0, root, 123, mynode1, <not set>
- 000, Node0, root, 456, mynode2, <not set>
- `[1:], rt); err != nil {
- t.Error(err)
- return
- }
- // Test simple traversal and access the edge
- if err := runSearch("get mynode0 traverse :myedge:: end show mynode0:key, 2:n:key, 2:e:key, myedge:name", `
- Labels: Mynode0 Key, Key, Key, Myedge Name
- Format: auto, auto, auto, auto
- Data: 1:n:key, 2:n:key, 2:e:key, 2:e:name
- 000, 123, abc1, edge:abc1
- 000, 456, abc2, edge:abc2
- `[1:], rt); err != nil {
- t.Error(err)
- return
- }
- // Test primary kind
- ast, err := parser.ParseWithRuntime("test", "get mynode0 traverse ::: end primary mynode2", rt)
- if err != nil {
- t.Error(err)
- return
- }
- res, err := ast.Runtime.Eval()
- if err != nil {
- t.Error(err)
- return
- }
- if pk := res.(*SearchResult).ResPrimaryKind; pk != "mynode2" {
- t.Error("Unexpected primary kind:", pk)
- return
- }
- ast, err = parser.ParseWithRuntime("test", "get mynode0 traverse ::: end primary bla", rt)
- if err != nil {
- t.Error(err)
- return
- }
- _, err = ast.Runtime.Eval()
- if err.Error() != "EQL error in test: Unknown node kind (bla) (Line:1 Pos:38)" {
- t.Error(err)
- return
- }
- }
- func TestErrors(t *testing.T) {
- gm, mgs := simpleGraph()
- rt := NewGetRuntimeProvider("test", "main", gm, NewDefaultNodeInfo(gm))
- // Test simple eval error
- generalProviderMap[parser.NodeGET] = invalidRuntimeInst
- if err := runSearch("get mynode", "", rt); err.Error() !=
- "EQL error in test: Invalid construct (get) (Line:1 Pos:1)" {
- t.Error(err)
- delete(generalProviderMap, parser.NodeGET)
- return
- }
- invast, err := parser.ParseWithRuntime("test", "get mynode", rt)
- if err != nil {
- t.Error(err)
- return
- }
- _, err = invast.Runtime.(*invalidRuntime).CondEval(nil, nil)
- if err.Error() != "EQL error in test: Invalid construct (get) (Line:1 Pos:1)" {
- t.Error(err)
- return
- }
- delete(generalProviderMap, parser.NodeGET)
- // Test validation errors
- if err := runSearch("get mynode show x traverse :::", "", rt); err.Error() !=
- "EQL error in test: Invalid construct (traversals must be before show clause) (Line:1 Pos:19)" {
- t.Error(err)
- return
- }
- if err := runSearch("get mynode traverse ::", "", rt); err.Error() !=
- "EQL error in test: Invalid traversal spec (::) (Line:1 Pos:12)" {
- t.Error(err)
- return
- }
- if err := runSearch("get mynode show mynode0:bla", "", rt); err.Error() !=
- "EQL error in test: Invalid construct (Cannot determine data position for kind: mynode0) (Line:1 Pos:17)" {
- t.Error(err)
- return
- }
- if err := runSearch("get mynode show 0:n:bla", "", rt); err.Error() !=
- "EQL error in test: Invalid construct (Invalid data index: 0:n:bla (index must be greater than 0)) (Line:1 Pos:17)" {
- t.Error(err)
- return
- }
- if err := runSearch("get mynode show a:n:bla", "", rt); err.Error() !=
- "EQL error in test: Invalid construct (Invalid data index: a:n:bla (strconv.Atoi: parsing \"a\": invalid syntax)) (Line:1 Pos:17)" {
- t.Error(err)
- return
- }
- if err := runSearch("get mynode show 1:b:bla", "", rt); err.Error() !=
- "EQL error in test: Invalid construct (Invalid data source 'b' (either n - Node or e - Edge)) (Line:1 Pos:17)" {
- t.Error(err)
- return
- }
- if err := runSearch("get mynode show 2:n:bla", "", rt); err.Error() !=
- "EQL error in test: Invalid column data spec (Data index out of range: 2) (Line:1 Pos:17)" {
- t.Error(err)
- return
- }
- // Test datastore errors
- msm := mgs.StorageManager("main"+"mynode"+graph.StorageSuffixNodes, false).(*storage.MemoryStorageManager)
- msm.AccessMap[1] = storage.AccessCacheAndFetchError
- if err := runSearch("get mynode", "", rt); err.Error() !=
- "GraphError: Failed to access graph storage component (Slot not found (mystorage/mainmynode.nodes - Location:1))" {
- t.Error(err)
- return
- }
- delete(msm.AccessMap, 1)
- // Test nextStartKey error
- msm.AccessMap[1] = storage.AccessCacheAndFetchSeriousError
- if _, err := rt.nextStartKey(); err.Error() != "GraphError: Could not read graph information (Record is already in-use (? - ))" {
- t.Error(err)
- return
- }
- delete(msm.AccessMap, 1)
- // Test FetchNodePart error
- msm.AccessMap[3] = storage.AccessCacheAndFetchError
- if err := runSearch("get mynode", "", rt); err.Error() !=
- "GraphError: Could not read graph information (Slot not found (mystorage/mainmynode.nodes - Location:3))" {
- t.Error(err)
- return
- }
- delete(msm.AccessMap, 3)
- // Test TraverseMulti errors
- msm = mgs.StorageManager("main"+"mynewnode"+graph.StorageSuffixNodes, false).(*storage.MemoryStorageManager)
- msm.AccessMap[5] = storage.AccessCacheAndFetchError // Node 3 attribute lookup
- if err := runSearch("get mynode traverse :::mynewnode traverse :::mynewnode end end", "", rt); err.Error() !=
- "GraphError: Could not read graph information (Slot not found (mystorage/mainmynewnode.nodes - Location:5))" {
- t.Error(err)
- return
- }
- delete(msm.AccessMap, 5)
- msm.AccessMap[11] = storage.AccessCacheAndFetchError // Traversal spec error
- if err := runSearch("get mynode traverse :::mynewnode traverse :::mynewnode end end", "", rt); err.Error() !=
- "GraphError: Could not read graph information (Slot not found (mystorage/mainmynewnode.nodes - Location:11))" {
- t.Error(err)
- return
- }
- delete(msm.AccessMap, 11)
- msm = mgs.StorageManager("main"+"myedge"+graph.StorageSuffixEdges, false).(*storage.MemoryStorageManager)
- msmtree, _ := hash.LoadHTree(msm, msm.Root(graph.RootIDNodeHTree))
- nm := util.NewNamesManager(mgs.MainDB())
- _, slot, _ := msmtree.GetValueAndLocation([]byte(graph.PrefixNSAttr + "abc2" + nm.Encode32("name", false)))
- msm.AccessMap[slot] = storage.AccessCacheAndFetchError // Edge attribute
- if err := runSearch("get mynode traverse :::mynewnode end show 1:n:key, 2:n:key, 2:e:key, 2:e:name", "", rt); strings.HasPrefix(err.Error(),
- "GraphError: Could not read graph information (Slot not found (mystorage/mainmynewnode.nodes - ") {
- t.Error(err)
- return
- }
- delete(msm.AccessMap, slot)
- // Test unknown ast node
- ast, err := parser.ParseWithRuntime("test", "get mynode show x", rt)
- if err != nil {
- t.Error(err)
- return
- }
- unknownASTNode := &parser.ASTNode{}
- unknownASTNode.Name = "Unknown"
- unknownASTNode.Token = &parser.LexToken{}
- ast.Children[1].Children = append(ast.Children[1].Children, unknownASTNode)
- if err = ast.Runtime.Validate(); err.Error() != "EQL error in test: Invalid construct (Unknown)" {
- t.Error(err)
- return
- }
- ast, err = parser.ParseWithRuntime("test", "get mynode show x as y", rt)
- if err != nil {
- t.Error(err)
- return
- }
- ast.Children[1].Children[0].Children = append(ast.Children[1].Children[0].Children, unknownASTNode)
- if err = ast.Runtime.Validate(); err.Error() != "EQL error in test: Invalid construct (Unknown)" {
- t.Error(err)
- return
- }
- ast, err = parser.ParseWithRuntime("test", "get mynode traverse ::: traverse ::: end end", rt)
- if err != nil {
- t.Error(err)
- return
- }
- ast.Children[1].Children[1].Children = append(ast.Children[1].Children[1].Children, unknownASTNode)
- if err = ast.Runtime.Validate(); err.Error() != "EQL error in test: Invalid construct (Unknown)" {
- t.Error(err)
- return
- }
- ast, err = parser.ParseWithRuntime("test", "get mynode", rt)
- if err != nil {
- t.Error(err)
- return
- }
- ast.Children = append(ast.Children, unknownASTNode)
- if err = ast.Runtime.Validate(); err.Error() != "EQL error in test: Invalid construct (Unknown)" {
- t.Error(err)
- return
- }
- ast.Children = ast.Children[:1]
- // Test add row errors
- if err = ast.Runtime.Validate(); err != nil {
- t.Error(err)
- return
- }
- ast.Runtime.(*getRuntime).rtp.colData[0] = "uu"
- res := newSearchResult(ast.Runtime.(*getRuntime).rtp.eqlRuntimeProvider, "")
- if err = res.addRow([]data.Node{data.NewGraphNode()}, nil); err.Error() !=
- "EQL result error in test: Invalid column data spec (Column data spec must have 3 items: uu)" {
- t.Error(err)
- return
- }
- ast.Runtime.(*getRuntime).rtp.colData[0] = "0:p:test"
- res = newSearchResult(ast.Runtime.(*getRuntime).rtp.eqlRuntimeProvider, "")
- if err = res.addRow([]data.Node{data.NewGraphNode()}, nil); err.Error() !=
- "EQL result error in test: Invalid column data spec (Invalid data source 'p' (either n - Node or e - Edge))" {
- t.Error(err)
- return
- }
- ast.Runtime.(*getRuntime).rtp.colData[0] = "0:e:test"
- allowMultiEval = true
- if _, err = ast.Runtime.Eval(); err.Error() !=
- "EQL result error in test: Invalid column data spec (Invalid data index: 0:e:test)" {
- t.Error(err)
- return
- }
- allowMultiEval = false
- ast.Runtime.(*getRuntime).rtp.colData[0] = "1:e:test"
- i := 0
- oldNextStartKey := ast.Runtime.(*getRuntime).rtp.nextStartKey
- ast.Runtime.(*getRuntime).rtp.nextStartKey = func() (string, error) {
- i++
- if i == 3 {
- return "", errors.New("testerror")
- }
- return "000", nil
- }
- allowMultiEval = true
- if _, err = ast.Runtime.Eval(); err.Error() != "testerror" {
- t.Error(err)
- return
- }
- allowMultiEval = false
- ast.Runtime.(*getRuntime).rtp.nextStartKey = oldNextStartKey
- // Test valid result
- r, err := ast.Runtime.Eval()
- if err != nil || fmt.Sprint(r) != `
- Labels: Mynode Key, Name
- Format: auto, auto
- Data: 1:n:key, 1:n:Name
- 123, Node1
- 000, Node0
- `[1:] {
- t.Error(r, err)
- return
- }
- }
- func TestBasicTraversalAndShow(t *testing.T) {
- gm, _ := simpleGraph()
- rt := NewGetRuntimeProvider("test", "main", gm, &testNodeInfo{&defaultNodeInfo{gm}})
- // Test unknown initial kind
- ast, err := parser.ParseWithRuntime("test", "get mymissingnode", rt)
- if err != nil {
- t.Error(err)
- return
- }
- if _, err := ast.Runtime.Eval(); err.Error() !=
- "EQL error in test: Unknown node kind (mymissingnode) (Line:1 Pos:5)" {
- t.Error(err)
- return
- }
- // Test simple query with traversals
- ast, err = parser.ParseWithRuntime("test", `
- get mynode
- traverse :::mynewnode
- traverse :::mynewnode
- end
- end
- traverse :::mynewnode
- end`, rt)
- if err != nil {
- t.Error(err)
- return
- }
- // Expected result explanation:
- // Row 1 - Node 000 is alone so no traversals possible
- // Row 2, 3, 4, 5 - there are two edges from 123 to 456 so possible traversals are doubled
- // 456 is also connected to 789 and 789-2
- // Node 123 has also a direct connection to xxx
- // 6 and 7 are duplicated because of the two edges from 123 to 456
- // 8 is the last combination of twice traversing from 123 to xxx
- expectedResult := `
- Labels: Mynode Key, Mynewnode Key, Mynewnode Key, Mynewnode Key
- Format: auto, auto, auto, auto
- Data: 1:n:key, 2:n:key, 3:n:key, 4:n:key
- 123, 456, 789-2, 456
- 123, 456, 789-2, 456
- 123, 456, 789, 456
- 123, 456, 789, 456
- 123, xxx ⌘, 789, 456
- 123, xxx ⌘, 789, 456
- 123, xxx ⌘, 789, xxx ⌘
- `[1:]
- res, err := ast.Runtime.Eval()
- if err != nil {
- t.Error(err)
- return
- }
- res.(*SearchResult).StableSort()
- if fmt.Sprint(res) != expectedResult {
- t.Error("Unexpected search result:", res, err)
- return
- }
- // Test showing empty traversals
- grt := ast.Runtime.(*getRuntime).rtp
- ast.Runtime.Validate()
- allowMultiEval = true
- grt.eqlRuntimeProvider.allowNilTraversal = true
- res, err = ast.Runtime.Eval()
- if err != nil {
- t.Error(err)
- return
- }
- res.(*SearchResult).StableSort()
- expectedResult = `
- Labels: Mynode Key, Mynewnode Key, Mynewnode Key, Mynewnode Key
- Format: auto, auto, auto, auto
- Data: 1:n:key, 2:n:key, 3:n:key, 4:n:key
- 000, <not set>, <not set>, <not set>
- 123, 456, 789-2, 456
- 123, 456, 789-2, 456
- 123, 456, 789, 456
- 123, 456, 789, 456
- 123, xxx ⌘, 789, 456
- 123, xxx ⌘, 789, 456
- 123, xxx ⌘, 789, xxx ⌘
- `[1:]
- if fmt.Sprint(res) != expectedResult {
- t.Error("Unexpected search result:", res, err)
- return
- }
- allowMultiEval = false
- // Test showing the traversal attributes in reverse order
- ast, err = parser.ParseWithRuntime("test", `
- get mynode
- traverse :::mynewnode
- traverse :::mynewnode
- end
- end
- show 3:n:key AS key1,
- 2:n:key FORMAT keystring1,
- key as key3 FORMAT x`, rt)
- if err != nil {
- t.Error(err)
- return
- }
- // Expected result explanation:
- // Row 1, 2, 3, 4 - there are two edges from 123 to 456 so possible traversals are doubled
- // 456 is also connected to 789 and 789-2
- // Row 5 - Node 123 has also a direct connection to xxx
- // Row 6 - Node 000 is alone so no traversals possible
- expectedResult = `
- Labels: key1, Key, key3
- Format: auto, keystring1, x
- Data: 3:n:key, 2:n:key, 1:n:key
- 789-2, 456, 123
- 789-2, 456, 123
- 789, 456, 123
- 789, 456, 123
- 789, xxx ⌘, 123
- `[1:]
- res, err = ast.Runtime.Eval()
- if err != nil {
- t.Error(err)
- return
- }
- res.(*SearchResult).StableSort()
- if fmt.Sprint(res) != expectedResult {
- t.Error("Unexpected search result:", res, err)
- return
- }
- }
- func simpleGraph() (*graph.Manager, *graphstorage.MemoryGraphStorage) {
- mgs := graphstorage.NewMemoryGraphStorage("mystorage")
- gm := graph.NewGraphManager(mgs)
- constructEdge := func(key string, node1 data.Node, node2 data.Node) data.Edge {
- edge := data.NewGraphEdge()
- edge.SetAttr("key", key)
- edge.SetAttr("kind", "myedge")
- edge.SetAttr(data.EdgeEnd1Key, node1.Key())
- edge.SetAttr(data.EdgeEnd1Kind, node1.Kind())
- edge.SetAttr(data.EdgeEnd1Role, "node1")
- edge.SetAttr(data.EdgeEnd1Cascading, true)
- edge.SetAttr(data.EdgeEnd2Key, node2.Key())
- edge.SetAttr(data.EdgeEnd2Kind, node2.Kind())
- edge.SetAttr(data.EdgeEnd2Role, "node2")
- edge.SetAttr(data.EdgeEnd2Cascading, false)
- edge.SetAttr(data.NodeName, "Edge1"+key)
- return edge
- }
- node0 := data.NewGraphNode()
- node0.SetAttr("key", "000")
- node0.SetAttr("kind", "mynode")
- node0.SetAttr("Name", "Node0")
- gm.StoreNode("main", node0)
- node1 := data.NewGraphNode()
- node1.SetAttr("key", "123")
- node1.SetAttr("kind", "mynode")
- node1.SetAttr("Name", "Node1")
- gm.StoreNode("main", node1)
- node2 := data.NewGraphNode()
- node2.SetAttr("key", "456")
- node2.SetAttr("kind", "mynewnode")
- node2.SetAttr("Na me", "Node2")
- gm.StoreNode("main", node2)
- node3 := data.NewGraphNode()
- node3.SetAttr("key", "789")
- node3.SetAttr("kind", "mynewnode")
- node3.SetAttr("Name", "Node3")
- gm.StoreNode("main", node3)
- node33 := data.NewGraphNode()
- node33.SetAttr("key", "789-2")
- node33.SetAttr("kind", "mynewnode")
- node33.SetAttr("Name", "Node3-2")
- gm.StoreNode("main", node33)
- node4 := data.NewGraphNode()
- node4.SetAttr("key", "xxx \xe2\x8c\x98")
- node4.SetAttr("kind", "mynewnode")
- node4.SetAttr("Nam \xe2\x8c\x98 e", "Node4")
- gm.StoreNode("main", node4)
- gm.StoreEdge("main", constructEdge("abc2", node1, node2))
- gm.StoreEdge("main", constructEdge("abc3", node1, node2))
- gm.StoreEdge("main", constructEdge("abc1", node2, node3))
- gm.StoreEdge("main", constructEdge("abc4", node2, node33))
- gm.StoreEdge("main", constructEdge("abc0", node3, node4))
- gm.StoreEdge("main", constructEdge("abc99", node4, node1))
- return gm, mgs.(*graphstorage.MemoryGraphStorage)
- }
- func multiKindGraph() *graph.Manager {
- mgs := graphstorage.NewMemoryGraphStorage("mystorage")
- gm := graph.NewGraphManager(mgs)
- constructEdge := func(key string, node1 data.Node, node2 data.Node) data.Edge {
- edge := data.NewGraphEdge()
- edge.SetAttr("key", key)
- edge.SetAttr("kind", "myedge")
- edge.SetAttr(data.EdgeEnd1Key, node1.Key())
- edge.SetAttr(data.EdgeEnd1Kind, node1.Kind())
- edge.SetAttr(data.EdgeEnd1Role, "src")
- edge.SetAttr(data.EdgeEnd1Cascading, true)
- edge.SetAttr(data.EdgeEnd2Key, node2.Key())
- edge.SetAttr(data.EdgeEnd2Kind, node2.Kind())
- edge.SetAttr(data.EdgeEnd2Role, "dest")
- edge.SetAttr(data.EdgeEnd2Cascading, false)
- edge.SetAttr(data.NodeName, "edge:"+key)
- return edge
- }
- node0 := data.NewGraphNode()
- node0.SetAttr("key", "000")
- node0.SetAttr("kind", "mynode0")
- node0.SetAttr("Name", "Node0")
- node0.SetAttr("Type", "root")
- gm.StoreNode("main", node0)
- node1 := data.NewGraphNode()
- node1.SetAttr("key", "123")
- node1.SetAttr("kind", "mynode1")
- gm.StoreNode("main", node1)
- node2 := data.NewGraphNode()
- node2.SetAttr("key", "456")
- node2.SetAttr("kind", "mynode2")
- gm.StoreNode("main", node2)
- node3 := data.NewGraphNode()
- node3.SetAttr("key", "789")
- node3.SetAttr("kind", "mynode3")
- gm.StoreNode("main", node3)
- gm.StoreEdge("main", constructEdge("abc1", node0, node1))
- gm.StoreEdge("main", constructEdge("abc2", node0, node2))
- gm.StoreEdge("main", constructEdge("abc3", node2, node3))
- return gm
- }
- func dataNodes() *graph.Manager {
- mgs := graphstorage.NewMemoryGraphStorage("mystorage")
- gm := graph.NewGraphManager(mgs)
- node0 := data.NewGraphNode()
- node0.SetAttr("key", "000")
- node0.SetAttr("kind", "mynode")
- node0.SetAttr("name", "Node0")
- node0.SetAttr("type", "type1")
- gm.StoreNode("main", node0)
- node1 := data.NewGraphNode()
- node1.SetAttr("key", "123")
- node1.SetAttr("kind", "mynode")
- node1.SetAttr("name", "Node1")
- node1.SetAttr("nested.nest1.nest2.atom1", 1.46)
- node1.SetAttr("type", "type1")
- gm.StoreNode("main", node1)
- node2 := data.NewGraphNode()
- node2.SetAttr("key", "456")
- node2.SetAttr("kind", "mynode")
- node2.SetAttr("name", "Node2")
- node2.SetAttr("type", "type2")
- node2.SetAttr("nested", map[string]interface{}{
- "nest1": map[string]interface{}{
- "nest2": map[string]interface{}{
- "atom1": 1.45,
- },
- },
- })
- gm.StoreNode("main", node2)
- return gm
- }
|