Improvements to the Not iterator:

- Pass the all iterator as an argument
 - Fixed next method (call all.Next() ).
This commit is contained in:
Matei Chiperi 2014-08-28 16:02:21 -07:00
parent def70ca12e
commit a5fd1905d0
2 changed files with 51 additions and 21 deletions

View file

@ -1,25 +1,28 @@
package iterator package iterator
import "github.com/google/cayley/graph" import (
"fmt"
"strings"
// Not iterator acts like a set difference between the primary iterator "github.com/google/cayley/graph"
// and the forbidden iterator. )
// Not iterator acts like a complement for the primary iterator.
// It will return all the vertices which are not part of the primary iterator.
type Not struct { type Not struct {
uid uint64 uid uint64
tags graph.Tagger tags graph.Tagger
ts graph.TripleStore
primaryIt graph.Iterator primaryIt graph.Iterator
allIt graph.Iterator allIt graph.Iterator
result graph.Value result graph.Value
runstats graph.IteratorStats runstats graph.IteratorStats
} }
func NewNot(ts graph.TripleStore, primaryIt graph.Iterator) *Not { func NewNot(primaryIt, allIt graph.Iterator) *Not {
return &Not{ return &Not{
uid: NextUID(), uid: NextUID(),
ts: ts,
allIt: ts.NodesAllIterator(),
primaryIt: primaryIt, primaryIt: primaryIt,
allIt: allIt,
} }
} }
@ -27,10 +30,11 @@ func (it *Not) UID() uint64 {
return it.uid return it.uid
} }
// Reset resets the internal iterators and the iterator itself.
func (it *Not) Reset() { func (it *Not) Reset() {
it.result = nil it.result = nil
it.primaryIt.Reset() it.primaryIt.Reset()
it.allIt = it.ts.NodesAllIterator() it.allIt.Reset()
} }
func (it *Not) Tagger() *graph.Tagger { func (it *Not) Tagger() *graph.Tagger {
@ -52,15 +56,19 @@ func (it *Not) TagResults(dst map[string]graph.Value) {
} }
func (it *Not) Clone() graph.Iterator { func (it *Not) Clone() graph.Iterator {
not := NewNot(it.ts, it.primaryIt.Clone()) not := NewNot(it.primaryIt.Clone(), it.allIt.Clone())
not.tags.CopyFrom(it) not.tags.CopyFrom(it)
return not return not
} }
// SubIterators returns a slice of the sub iterators.
// The first iterator is the primary iterator, for which the complement
// is generated.
func (it *Not) SubIterators() []graph.Iterator { func (it *Not) SubIterators() []graph.Iterator {
return []graph.Iterator{it.primaryIt, it.allIt} return []graph.Iterator{it.primaryIt, it.allIt}
} }
// DEPRECATED
func (it *Not) ResultTree() *graph.ResultTree { func (it *Not) ResultTree() *graph.ResultTree {
tree := graph.NewResultTree(it.Result()) tree := graph.NewResultTree(it.Result())
tree.AddSubtree(it.primaryIt.ResultTree()) tree.AddSubtree(it.primaryIt.ResultTree())
@ -68,15 +76,33 @@ func (it *Not) ResultTree() *graph.ResultTree {
return tree return tree
} }
// DebugString prints information about the iterator.
func (it *Not) DebugString(indent int) string { func (it *Not) DebugString(indent int) string {
return "todo" var tags string
for _, k := range it.tags.Tags() {
tags += fmt.Sprintf("%s;", k)
}
spaces := strings.Repeat(" ", indent+2)
return fmt.Sprintf("%s(%s %d\n%stags:%v\n%sprimary_it:\n%s\n)",
strings.Repeat(" ", indent),
it.Type(),
it.UID(),
spaces,
it.tags.Tags(),
spaces,
it.primaryIt.DebugString(indent+4),
)
} }
// Next advances the Not iterator. It returns whether there is another valid
// new value. It fetches the next value of the all iterator which is not
// contained by the primary iterator.
func (it *Not) Next() bool { func (it *Not) Next() bool {
graph.NextLogIn(it) graph.NextLogIn(it)
it.runstats.Next += 1 it.runstats.Next += 1
for graph.Next(it.primaryIt) { for graph.Next(it.allIt) {
if curr := it.allIt.Result(); !it.primaryIt.Contains(curr) { if curr := it.allIt.Result(); !it.primaryIt.Contains(curr) {
it.result = curr it.result = curr
it.runstats.ContainsNext += 1 it.runstats.ContainsNext += 1
@ -90,6 +116,9 @@ func (it *Not) Result() graph.Value {
return it.result return it.result
} }
// Contains checks whether the passed value is part of the primary iterator's
// complement. For a valid value, it updates the Result returned by the iterator
// to the value itself.
func (it *Not) Contains(val graph.Value) bool { func (it *Not) Contains(val graph.Value) bool {
graph.ContainsLogIn(it, val) graph.ContainsLogIn(it, val)
it.runstats.Contains += 1 it.runstats.Contains += 1
@ -98,15 +127,13 @@ func (it *Not) Contains(val graph.Value) bool {
return graph.ContainsLogOut(it, val, false) return graph.ContainsLogOut(it, val, false)
} }
// TODO - figure out if this really needs to be checked or it's safe to return true directly it.result = val
return graph.ContainsLogOut(it, val, it.allIt.Contains(val)) return graph.ContainsLogOut(it, val, true)
} }
// TODO // NextPath checks whether there is another path. Not applicable, hence it will
// return false.
func (it *Not) NextPath() bool { func (it *Not) NextPath() bool {
if it.primaryIt.NextPath() {
return true
}
return false return false
} }
@ -117,13 +144,15 @@ func (it *Not) Close() {
func (it *Not) Type() graph.Type { return graph.Not } func (it *Not) Type() graph.Type { return graph.Not }
// TODO - call optimize for the primaryIt and allIt?
func (it *Not) Optimize() (graph.Iterator, bool) { func (it *Not) Optimize() (graph.Iterator, bool) {
//it.forbiddenIt = NewMaterialize(it.forbiddenIt) // TODO - consider wrapping the primaryIt with a MaterializeIt
if optimizedPrimaryIt, optimized := it.primaryIt.Optimize(); optimized {
it.primaryIt = optimizedPrimaryIt
return it, true
}
return it, false return it, false
} }
// TODO
func (it *Not) Stats() graph.IteratorStats { func (it *Not) Stats() graph.IteratorStats {
subitStats := it.primaryIt.Stats() subitStats := it.primaryIt.Stats()
// TODO(barakmich): These should really come from the triplestore itself // TODO(barakmich): These should really come from the triplestore itself

View file

@ -305,8 +305,9 @@ func buildIteratorTreeHelper(obj *otto.Object, ts graph.TripleStore, base graph.
return iterator.NewNull() return iterator.NewNull()
} }
allIt := ts.NodesAllIterator()
toComplementIt := buildIteratorTree(firstArg.Object(), ts) toComplementIt := buildIteratorTree(firstArg.Object(), ts)
notIt := iterator.NewNot(ts, toComplementIt) notIt := iterator.NewNot(toComplementIt, allIt)
and := iterator.NewAnd() and := iterator.NewAnd()
and.AddSubIterator(subIt) and.AddSubIterator(subIt)