// processPredicate updates the working graph clause if there is an available // predicate. func processPredicate(c *GraphClause, ce ConsumedElement, lastNopToken *lexer.Token) (*predicate.Predicate, string, string, bool, error) { var ( nP *predicate.Predicate pID string pAnchorBinding string temporal bool ) raw := ce.Token().Text p, err := predicate.Parse(raw) if err == nil { // A fully specified predicate was provided. nP = p return nP, pID, pAnchorBinding, nP.Type() == predicate.Temporal, nil } // The predicate may have a binding on the anchor. cmps := predicateRegexp.FindAllStringSubmatch(raw, 2) if len(cmps) != 1 || (len(cmps) == 1 && len(cmps[0]) != 3) { return nil, "", "", false, fmt.Errorf("failed to extract partialy defined predicate %q, got %v instead", raw, cmps) } id, ta := cmps[0][1], cmps[0][2] pID = id if ta != "" { pAnchorBinding = ta temporal = true } return nil, pID, pAnchorBinding, temporal, nil }
// TriplesForPredicate returns all triples available for the given predicate. func (m *memory) TriplesForPredicate(p *predicate.Predicate, lo *storage.LookupOptions) (storage.Triples, error) { pGUID := p.GUID() m.rwmu.RLock() triples := make(chan *triple.Triple, len(m.idxP[pGUID])) go func() { ckr := newChecker(lo) for _, t := range m.idxP[pGUID] { if ckr.CheckAndUpdate(t.Predicate()) { triples <- t } } m.rwmu.RUnlock() close(triples) }() return triples, nil }
// TriplesForPredicateAndObject returns all triples available for the given // predicate and object. func (m *memory) TriplesForPredicateAndObject(p *predicate.Predicate, o *triple.Object, lo *storage.LookupOptions) (storage.Triples, error) { pGUID := p.GUID() oGUID := o.GUID() poIdx := strings.Join([]string{pGUID, oGUID}, ":") m.rwmu.RLock() triples := make(chan *triple.Triple, len(m.idxPO[poIdx])) go func() { ckr := newChecker(lo) for _, t := range m.idxPO[poIdx] { if ckr.CheckAndUpdate(t.P()) { triples <- t } } m.rwmu.RUnlock() close(triples) }() return triples, nil }
// TriplesForSubjectAndPredicate returns all triples available for the given // subject and predicate. func (m *memory) TriplesForSubjectAndPredicate(s *node.Node, p *predicate.Predicate, lo *storage.LookupOptions) (storage.Triples, error) { sGUID := s.GUID() pGUID := p.GUID() spIdx := strings.Join([]string{sGUID, pGUID}, ":") m.rwmu.RLock() triples := make(chan *triple.Triple, len(m.idxSP[spIdx])) go func() { ckr := newChecker(lo) for _, t := range m.idxSP[spIdx] { if ckr.CheckAndUpdate(t.P()) { triples <- t } } m.rwmu.RUnlock() close(triples) }() return triples, nil }
// Subject returns the subjects for the give predicate and object. func (m *memory) Subjects(p *predicate.Predicate, o *triple.Object, lo *storage.LookupOptions) (storage.Nodes, error) { pGUID := p.GUID() oGUID := o.GUID() poIdx := strings.Join([]string{pGUID, oGUID}, ":") m.rwmu.RLock() subs := make(chan *node.Node, len(m.idxPO[poIdx])) go func() { ckr := newChecker(lo) for _, t := range m.idxPO[poIdx] { if ckr.CheckAndUpdate(t.P()) { subs <- t.S() } } m.rwmu.RUnlock() close(subs) }() return subs, nil }
// Objects returns the objects for the give object and predicate. func (m *memory) Objects(ctx context.Context, s *node.Node, p *predicate.Predicate, lo *storage.LookupOptions) (storage.Objects, error) { sGUID := s.GUID() pGUID := p.GUID() spIdx := strings.Join([]string{sGUID, pGUID}, ":") m.rwmu.RLock() objs := make(chan *triple.Object, len(m.idxSP[spIdx])) go func() { ckr := newChecker(lo) for _, t := range m.idxSP[spIdx] { if ckr.CheckAndUpdate(t.Predicate()) { objs <- t.Object() } } m.rwmu.RUnlock() close(objs) }() return objs, nil }
// CheckAndUpdate checks if a predicate should be considered and it also updates // the internal state in case counts are needed. func (c *checker) CheckAndUpdate(p *predicate.Predicate) bool { if c.max { if c.c <= 0 { return false } c.c-- } if p.Type() == predicate.Immutable { return true } t, _ := p.TimeAnchor() if c.o.LowerAnchor != nil && t.Before(*c.o.LowerAnchor) { return false } if c.o.UpperAnchor != nil && t.After(*c.o.UpperAnchor) { return false } return true }
// CheckAndUpdate checks if a predicate should be considered and it also updates // the internal state in case counts are needed. func (c *checker) CheckAndUpdate(p *predicate.Predicate) bool { if c.max { if c.c <= 0 { return false } // TODO: Should it be decremented if later function returns false? c.c-- } if p.Type() == predicate.Immutable { return true } t, _ := p.TimeAnchor() if c.o.LowerAnchor != nil && t.Before(*c.o.LowerAnchor) { return false } if c.o.UpperAnchor != nil && t.After(*c.o.UpperAnchor) { return false } return true }