func hasaWithTag(qs graph.QuadStore, tag string, target string) *HasA { and := NewAnd(qs) obj := qs.FixedIterator() obj.Add(qs.ValueOf(quad.Raw(target))) obj.Tagger().Add(tag) and.AddSubIterator(NewLinksTo(qs, obj, quad.Object)) pred := qs.FixedIterator() pred.Add(qs.ValueOf(quad.Raw("status"))) and.AddSubIterator(NewLinksTo(qs, pred, quad.Predicate)) return NewHasA(qs, and, quad.Subject) }
func buildHas(qs graph.QuadStore, via interface{}, in graph.Iterator, reverse bool, nodes []string) graph.Iterator { viaIter := buildViaPath(qs, via). BuildIterator() ends := func() graph.Iterator { if len(nodes) == 0 { return qs.NodesAllIterator() } fixed := qs.FixedIterator() for _, n := range nodes { fixed.Add(qs.ValueOf(n)) } return fixed }() start, goal := quad.Subject, quad.Object if reverse { start, goal = goal, start } trail := iterator.NewLinksTo(qs, viaIter, quad.Predicate) dest := iterator.NewLinksTo(qs, ends, goal) // If we were given nodes, intersecting with them first will // be extremely cheap-- otherwise, it will be the most expensive // (requiring iteration over all nodes). We have enough info to // make this optimization now since intersections are commutative if len(nodes) == 0 { // Where dest involves an All iterator. route := join(qs, trail, dest) has := iterator.NewHasA(qs, route, start) return join(qs, in, has) } // This looks backwards. That's OK-- see the note above. route := join(qs, dest, trail) has := iterator.NewHasA(qs, route, start) return join(qs, has, in) }
func buildIteratorTree(tree *peg.ExpressionTree, qs graph.QuadStore) graph.Iterator { switch tree.Name { case "Start": return buildIteratorTree(tree.Children[0], qs) case "NodeIdentifier": var out graph.Iterator nodeID := getIdentString(tree) if tree.Children[0].Name == "Variable" { allIt := qs.NodesAllIterator() allIt.Tagger().Add(nodeID) out = allIt } else { n := nodeID if tree.Children[0].Children[0].Name == "ColonIdentifier" { n = nodeID[1:] } fixed := qs.FixedIterator() fixed.Add(qs.ValueOf(n)) out = fixed } return out case "PredIdentifier": i := 0 if tree.Children[0].Name == "Reverse" { //Taken care of below i++ } it := buildIteratorTree(tree.Children[i], qs) lto := iterator.NewLinksTo(qs, it, quad.Predicate) return lto case "RootConstraint": constraintCount := 0 and := iterator.NewAnd(qs) for _, c := range tree.Children { switch c.Name { case "NodeIdentifier": fallthrough case "Constraint": it := buildIteratorTree(c, qs) and.AddSubIterator(it) constraintCount++ continue default: continue } } return and case "Constraint": var hasa *iterator.HasA topLevelDir := quad.Subject subItDir := quad.Object subAnd := iterator.NewAnd(qs) isOptional := false for _, c := range tree.Children { switch c.Name { case "PredIdentifier": if c.Children[0].Name == "Reverse" { topLevelDir = quad.Object subItDir = quad.Subject } it := buildIteratorTree(c, qs) subAnd.AddSubIterator(it) continue case "PredicateKeyword": switch c.Children[0].Name { case "OptionalKeyword": isOptional = true } case "NodeIdentifier": fallthrough case "RootConstraint": it := buildIteratorTree(c, qs) l := iterator.NewLinksTo(qs, it, subItDir) subAnd.AddSubIterator(l) continue default: continue } } hasa = iterator.NewHasA(qs, subAnd, topLevelDir) if isOptional { optional := iterator.NewOptional(hasa) return optional } return hasa default: return &iterator.Null{} } }