func OutputQueryShapeForIterator(it graph.Iterator, ts graph.TripleStore, outputMap map[string]interface{}) { qs := &queryShape{ ts: ts, nodeId: 1, } node := qs.MakeNode(it.Clone()) qs.AddNode(node) outputMap["nodes"] = qs.nodes outputMap["links"] = qs.links }
func OutputQueryShapeForIterator(it graph.Iterator, qs graph.QuadStore, outputMap map[string]interface{}) { s := &queryShape{ qs: qs, nodeId: 1, } node := s.MakeNode(it.Clone()) s.AddNode(node) outputMap["nodes"] = s.nodes outputMap["links"] = s.links }
func TestOptimize(t *testing.T) { var ts *LevelDBTripleStore var lto graph.Iterator var tmpDir string Convey("Given a prepared database", t, func() { tmpDir, _ = ioutil.TempDir(os.TempDir(), "cayley_test") t.Log(tmpDir) defer os.RemoveAll(tmpDir) ok := CreateNewLevelDB(tmpDir) So(ok, ShouldBeTrue) ts = NewDefaultLevelDBTripleStore(tmpDir, nil) ts.AddTripleSet(makeTripleSet()) Convey("With an linksto-fixed pair", func() { fixed := ts.MakeFixed() fixed.AddValue(ts.GetIdFor("F")) fixed.AddTag("internal") lto = graph.NewLinksToIterator(ts, fixed, "o") Convey("Creates an appropriate iterator", func() { oldIt := lto.Clone() newIt, ok := lto.Optimize() So(ok, ShouldBeTrue) So(newIt.Type(), ShouldEqual, "leveldb") Convey("Containing the right things", func() { afterOp := extractTripleFromIterator(ts, newIt) beforeOp := extractTripleFromIterator(ts, oldIt) sort.Strings(afterOp) sort.Strings(beforeOp) So(afterOp, ShouldResemble, beforeOp) }) Convey("With the correct tags", func() { oldIt.Next() newIt.Next() oldResults := make(map[string]graph.TSVal) oldIt.TagResults(&oldResults) newResults := make(map[string]graph.TSVal) oldIt.TagResults(&newResults) So(newResults, ShouldResemble, oldResults) }) }) }) }) }
func buildIteratorTreeHelper(obj *otto.Object, ts graph.TripleStore, base graph.Iterator) graph.Iterator { var it graph.Iterator it = base // TODO: Better error handling kindVal, _ := obj.Get("_gremlin_type") stringArgs := getStringArgs(obj) var subIt graph.Iterator prevVal, _ := obj.Get("_gremlin_prev") if !prevVal.IsObject() { subIt = base } else { subIt = buildIteratorTreeHelper(prevVal.Object(), ts, base) } kind, _ := kindVal.ToString() switch kind { case "vertex": if len(stringArgs) == 0 { it = ts.GetNodesAllIterator() } else { fixed := ts.MakeFixed() for _, name := range stringArgs { fixed.AddValue(ts.GetIdFor(name)) } it = fixed } case "tag": it = subIt for _, tag := range stringArgs { it.AddTag(tag) } case "save": all := ts.GetNodesAllIterator() if len(stringArgs) > 2 || len(stringArgs) == 0 { return graph.NewNullIterator() } if len(stringArgs) == 2 { all.AddTag(stringArgs[1]) } else { all.AddTag(stringArgs[0]) } predFixed := ts.MakeFixed() predFixed.AddValue(ts.GetIdFor(stringArgs[0])) subAnd := graph.NewAndIterator() subAnd.AddSubIterator(graph.NewLinksToIterator(ts, predFixed, graph.Predicate)) subAnd.AddSubIterator(graph.NewLinksToIterator(ts, all, graph.Object)) hasa := graph.NewHasaIterator(ts, subAnd, graph.Subject) and := graph.NewAndIterator() and.AddSubIterator(hasa) and.AddSubIterator(subIt) it = and case "saver": all := ts.GetNodesAllIterator() if len(stringArgs) > 2 || len(stringArgs) == 0 { return graph.NewNullIterator() } if len(stringArgs) == 2 { all.AddTag(stringArgs[1]) } else { all.AddTag(stringArgs[0]) } predFixed := ts.MakeFixed() predFixed.AddValue(ts.GetIdFor(stringArgs[0])) subAnd := graph.NewAndIterator() subAnd.AddSubIterator(graph.NewLinksToIterator(ts, predFixed, graph.Predicate)) subAnd.AddSubIterator(graph.NewLinksToIterator(ts, all, graph.Subject)) hasa := graph.NewHasaIterator(ts, subAnd, graph.Object) and := graph.NewAndIterator() and.AddSubIterator(hasa) and.AddSubIterator(subIt) it = and case "has": fixed := ts.MakeFixed() if len(stringArgs) < 2 { return graph.NewNullIterator() } for _, name := range stringArgs[1:] { fixed.AddValue(ts.GetIdFor(name)) } predFixed := ts.MakeFixed() predFixed.AddValue(ts.GetIdFor(stringArgs[0])) subAnd := graph.NewAndIterator() subAnd.AddSubIterator(graph.NewLinksToIterator(ts, predFixed, graph.Predicate)) subAnd.AddSubIterator(graph.NewLinksToIterator(ts, fixed, graph.Object)) hasa := graph.NewHasaIterator(ts, subAnd, graph.Subject) and := graph.NewAndIterator() and.AddSubIterator(hasa) and.AddSubIterator(subIt) it = and case "morphism": it = base case "and": arg, _ := obj.Get("_gremlin_values") firstArg, _ := arg.Object().Get("0") if !isVertexChain(firstArg.Object()) { return graph.NewNullIterator() } argIt := buildIteratorTree(firstArg.Object(), ts) and := graph.NewAndIterator() and.AddSubIterator(subIt) and.AddSubIterator(argIt) it = and case "back": arg, _ := obj.Get("_gremlin_back_chain") argIt := buildIteratorTree(arg.Object(), ts) and := graph.NewAndIterator() and.AddSubIterator(subIt) and.AddSubIterator(argIt) it = and case "is": fixed := ts.MakeFixed() for _, name := range stringArgs { fixed.AddValue(ts.GetIdFor(name)) } and := graph.NewAndIterator() and.AddSubIterator(fixed) and.AddSubIterator(subIt) it = and case "or": arg, _ := obj.Get("_gremlin_values") firstArg, _ := arg.Object().Get("0") if !isVertexChain(firstArg.Object()) { return graph.NewNullIterator() } argIt := buildIteratorTree(firstArg.Object(), ts) or := graph.NewOrIterator() or.AddSubIterator(subIt) or.AddSubIterator(argIt) it = or case "both": // Hardly the most efficient pattern, but the most general. // Worth looking into an Optimize() optimization here. clone := subIt.Clone() it1 := buildInOutIterator(obj, ts, subIt, false) it2 := buildInOutIterator(obj, ts, clone, true) or := graph.NewOrIterator() or.AddSubIterator(it1) or.AddSubIterator(it2) it = or case "out": it = buildInOutIterator(obj, ts, subIt, false) case "follow": // Follow a morphism arg, _ := obj.Get("_gremlin_values") firstArg, _ := arg.Object().Get("0") if isVertexChain(firstArg.Object()) { return graph.NewNullIterator() } it = buildIteratorTreeHelper(firstArg.Object(), ts, subIt) case "followr": // Follow a morphism arg, _ := obj.Get("_gremlin_followr") if isVertexChain(arg.Object()) { return graph.NewNullIterator() } it = buildIteratorTreeHelper(arg.Object(), ts, subIt) case "in": it = buildInOutIterator(obj, ts, subIt, true) } return it }
func buildIteratorTreeHelper(obj *otto.Object, qs graph.QuadStore, base graph.Iterator) graph.Iterator { it := base // TODO: Better error handling var subIt graph.Iterator if prev, _ := obj.Get("_gremlin_prev"); !prev.IsObject() { subIt = base } else { subIt = buildIteratorTreeHelper(prev.Object(), qs, base) } stringArgs := propertiesOf(obj, "string_args") val, _ := obj.Get("_gremlin_type") switch val.String() { case "vertex": if len(stringArgs) == 0 { it = qs.NodesAllIterator() } else { fixed := qs.FixedIterator() for _, name := range stringArgs { fixed.Add(qs.ValueOf(name)) } it = fixed } case "tag": it = subIt for _, tag := range stringArgs { it.Tagger().Add(tag) } case "save": all := qs.NodesAllIterator() if len(stringArgs) > 2 || len(stringArgs) == 0 { return iterator.NewNull() } if len(stringArgs) == 2 { all.Tagger().Add(stringArgs[1]) } else { all.Tagger().Add(stringArgs[0]) } predFixed := qs.FixedIterator() predFixed.Add(qs.ValueOf(stringArgs[0])) subAnd := iterator.NewAnd() subAnd.AddSubIterator(iterator.NewLinksTo(qs, predFixed, quad.Predicate)) subAnd.AddSubIterator(iterator.NewLinksTo(qs, all, quad.Object)) hasa := iterator.NewHasA(qs, subAnd, quad.Subject) and := iterator.NewAnd() and.AddSubIterator(hasa) and.AddSubIterator(subIt) it = and case "saver": all := qs.NodesAllIterator() if len(stringArgs) > 2 || len(stringArgs) == 0 { return iterator.NewNull() } if len(stringArgs) == 2 { all.Tagger().Add(stringArgs[1]) } else { all.Tagger().Add(stringArgs[0]) } predFixed := qs.FixedIterator() predFixed.Add(qs.ValueOf(stringArgs[0])) subAnd := iterator.NewAnd() subAnd.AddSubIterator(iterator.NewLinksTo(qs, predFixed, quad.Predicate)) subAnd.AddSubIterator(iterator.NewLinksTo(qs, all, quad.Subject)) hasa := iterator.NewHasA(qs, subAnd, quad.Object) and := iterator.NewAnd() and.AddSubIterator(hasa) and.AddSubIterator(subIt) it = and case "has": fixed := qs.FixedIterator() if len(stringArgs) < 2 { return iterator.NewNull() } for _, name := range stringArgs[1:] { fixed.Add(qs.ValueOf(name)) } predFixed := qs.FixedIterator() predFixed.Add(qs.ValueOf(stringArgs[0])) subAnd := iterator.NewAnd() subAnd.AddSubIterator(iterator.NewLinksTo(qs, predFixed, quad.Predicate)) subAnd.AddSubIterator(iterator.NewLinksTo(qs, fixed, quad.Object)) hasa := iterator.NewHasA(qs, subAnd, quad.Subject) and := iterator.NewAnd() and.AddSubIterator(hasa) and.AddSubIterator(subIt) it = and case "morphism": it = base case "and": arg, _ := obj.Get("_gremlin_values") firstArg, _ := arg.Object().Get("0") if !isVertexChain(firstArg.Object()) { return iterator.NewNull() } argIt := buildIteratorTree(firstArg.Object(), qs) and := iterator.NewAnd() and.AddSubIterator(subIt) and.AddSubIterator(argIt) it = and case "back": arg, _ := obj.Get("_gremlin_back_chain") argIt := buildIteratorTree(arg.Object(), qs) and := iterator.NewAnd() and.AddSubIterator(subIt) and.AddSubIterator(argIt) it = and case "is": fixed := qs.FixedIterator() for _, name := range stringArgs { fixed.Add(qs.ValueOf(name)) } and := iterator.NewAnd() and.AddSubIterator(fixed) and.AddSubIterator(subIt) it = and case "or": arg, _ := obj.Get("_gremlin_values") firstArg, _ := arg.Object().Get("0") if !isVertexChain(firstArg.Object()) { return iterator.NewNull() } argIt := buildIteratorTree(firstArg.Object(), qs) or := iterator.NewOr() or.AddSubIterator(subIt) or.AddSubIterator(argIt) it = or case "both": // Hardly the most efficient pattern, but the most general. // Worth looking into an Optimize() optimization here. clone := subIt.Clone() it1 := buildInOutIterator(obj, qs, subIt, false) it2 := buildInOutIterator(obj, qs, clone, true) or := iterator.NewOr() or.AddSubIterator(it1) or.AddSubIterator(it2) it = or case "out": it = buildInOutIterator(obj, qs, subIt, false) case "follow": // Follow a morphism arg, _ := obj.Get("_gremlin_values") firstArg, _ := arg.Object().Get("0") if isVertexChain(firstArg.Object()) { return iterator.NewNull() } it = buildIteratorTreeHelper(firstArg.Object(), qs, subIt) case "followr": // Follow a morphism arg, _ := obj.Get("_gremlin_followr") if isVertexChain(arg.Object()) { return iterator.NewNull() } it = buildIteratorTreeHelper(arg.Object(), qs, subIt) case "in": it = buildInOutIterator(obj, qs, subIt, true) } return it }