Converted the Not operator to a complement operator in terms of functionality.
This commit is contained in:
parent
a0318aa7b2
commit
5d4e22498d
3 changed files with 35 additions and 48 deletions
|
|
@ -7,17 +7,19 @@ import "github.com/google/cayley/graph"
|
||||||
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
|
||||||
forbiddenIt graph.Iterator
|
allIt graph.Iterator
|
||||||
result graph.Value
|
result graph.Value
|
||||||
runstats graph.IteratorStats
|
runstats graph.IteratorStats
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewNot(primaryIt, forbiddenIt graph.Iterator) *Not {
|
func NewNot(ts graph.TripleStore, primaryIt graph.Iterator) *Not {
|
||||||
return &Not{
|
return &Not{
|
||||||
uid: NextUID(),
|
uid: NextUID(),
|
||||||
|
ts: ts,
|
||||||
|
allIt: ts.NodesAllIterator(),
|
||||||
primaryIt: primaryIt,
|
primaryIt: primaryIt,
|
||||||
forbiddenIt: forbiddenIt,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -28,14 +30,13 @@ func (it *Not) UID() uint64 {
|
||||||
func (it *Not) Reset() {
|
func (it *Not) Reset() {
|
||||||
it.result = nil
|
it.result = nil
|
||||||
it.primaryIt.Reset()
|
it.primaryIt.Reset()
|
||||||
it.forbiddenIt.Reset()
|
it.allIt = it.ts.NodesAllIterator()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (it *Not) Tagger() *graph.Tagger {
|
func (it *Not) Tagger() *graph.Tagger {
|
||||||
return &it.tags
|
return &it.tags
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO
|
|
||||||
func (it *Not) TagResults(dst map[string]graph.Value) {
|
func (it *Not) TagResults(dst map[string]graph.Value) {
|
||||||
for _, tag := range it.tags.Tags() {
|
for _, tag := range it.tags.Tags() {
|
||||||
dst[tag] = it.Result()
|
dst[tag] = it.Result()
|
||||||
|
|
@ -51,19 +52,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.primaryIt.Clone(), it.forbiddenIt.Clone())
|
not := NewNot(it.ts, it.primaryIt.Clone())
|
||||||
not.tags.CopyFrom(it)
|
not.tags.CopyFrom(it)
|
||||||
return not
|
return not
|
||||||
}
|
}
|
||||||
|
|
||||||
func (it *Not) SubIterators() []graph.Iterator {
|
func (it *Not) SubIterators() []graph.Iterator {
|
||||||
return []graph.Iterator{it.primaryIt, it.forbiddenIt}
|
return []graph.Iterator{it.primaryIt, it.allIt}
|
||||||
}
|
}
|
||||||
|
|
||||||
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())
|
||||||
tree.AddSubtree(it.forbiddenIt.ResultTree())
|
tree.AddSubtree(it.allIt.ResultTree())
|
||||||
return tree
|
return tree
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -76,9 +77,7 @@ func (it *Not) Next() bool {
|
||||||
it.runstats.Next += 1
|
it.runstats.Next += 1
|
||||||
|
|
||||||
for graph.Next(it.primaryIt) {
|
for graph.Next(it.primaryIt) {
|
||||||
// Consider only the elements from the primary set which are not
|
if curr := it.allIt.Result(); !it.primaryIt.Contains(curr) {
|
||||||
// contained in the forbidden set.
|
|
||||||
if curr := it.primaryIt.Result(); !it.forbiddenIt.Contains(curr) {
|
|
||||||
it.result = curr
|
it.result = curr
|
||||||
it.runstats.ContainsNext += 1
|
it.runstats.ContainsNext += 1
|
||||||
return graph.NextLogOut(it, curr, true)
|
return graph.NextLogOut(it, curr, true)
|
||||||
|
|
@ -95,28 +94,30 @@ func (it *Not) Contains(val graph.Value) bool {
|
||||||
graph.ContainsLogIn(it, val)
|
graph.ContainsLogIn(it, val)
|
||||||
it.runstats.Contains += 1
|
it.runstats.Contains += 1
|
||||||
|
|
||||||
mainGood := it.primaryIt.Contains(val)
|
if it.primaryIt.Contains(val) {
|
||||||
if mainGood {
|
return graph.ContainsLogOut(it, val, false)
|
||||||
mainGood = !it.forbiddenIt.Contains(val)
|
|
||||||
}
|
}
|
||||||
return graph.ContainsLogOut(it, val, mainGood)
|
|
||||||
|
// TODO - figure out if this really needs to be checked or it's safe to return true directly
|
||||||
|
return graph.ContainsLogOut(it, val, it.allIt.Contains(val))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO
|
||||||
func (it *Not) NextPath() bool {
|
func (it *Not) NextPath() bool {
|
||||||
if it.primaryIt.NextPath() {
|
if it.primaryIt.NextPath() {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return it.forbiddenIt.NextPath()
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (it *Not) Close() {
|
func (it *Not) Close() {
|
||||||
it.primaryIt.Close()
|
it.primaryIt.Close()
|
||||||
it.forbiddenIt.Close()
|
it.allIt.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (it *Not) Type() graph.Type { return graph.Not }
|
func (it *Not) Type() graph.Type { return graph.Not }
|
||||||
|
|
||||||
// TODO
|
// 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)
|
//it.forbiddenIt = NewMaterialize(it.forbiddenIt)
|
||||||
return it, false
|
return it, false
|
||||||
|
|
|
||||||
|
|
@ -299,28 +299,14 @@ func buildIteratorTreeHelper(obj *otto.Object, ts graph.TripleStore, base graph.
|
||||||
case "in":
|
case "in":
|
||||||
it = buildInOutIterator(obj, ts, subIt, true)
|
it = buildInOutIterator(obj, ts, subIt, true)
|
||||||
case "not":
|
case "not":
|
||||||
// Not is implemented as the difference between the primary iterator
|
// arg, _ := obj.Get("_gremlin_values")
|
||||||
// and the iterator chain composed of (primaryIt->Follow->FollowR).
|
// firstArg, _ := arg.Object().Get("0")
|
||||||
|
// if !isVertexChain(firstArg.Object()) {
|
||||||
|
// return iterator.NewNull()
|
||||||
|
// }
|
||||||
|
// forbiddenIt := buildIteratorTree(firstArg.Object(), ts)
|
||||||
|
|
||||||
// Arguments for follow iterator
|
it = iterator.NewNot(ts, subIt)
|
||||||
arg, _ := obj.Get("_gremlin_values")
|
|
||||||
firstArg, _ := arg.Object().Get("0")
|
|
||||||
if isVertexChain(firstArg.Object()) {
|
|
||||||
return iterator.NewNull()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Arguments for followR iterator
|
|
||||||
revArg, _ := obj.Get("_gremlin_followr")
|
|
||||||
if isVertexChain(revArg.Object()) {
|
|
||||||
return iterator.NewNull()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Build the primaryIt->Follow iterator
|
|
||||||
followIt := buildIteratorTreeHelper(firstArg.Object(), ts, subIt)
|
|
||||||
// Build the primaryIt->Follow->FollowR iterator
|
|
||||||
forbiddenIt := buildIteratorTreeHelper(revArg.Object(), ts, followIt)
|
|
||||||
|
|
||||||
it = iterator.NewNot(subIt, forbiddenIt)
|
|
||||||
case "loop":
|
case "loop":
|
||||||
arg, _ := obj.Get("_gremlin_values")
|
arg, _ := obj.Get("_gremlin_values")
|
||||||
firstArg, _ := arg.Object().Get("0")
|
firstArg, _ := arg.Object().Get("0")
|
||||||
|
|
|
||||||
|
|
@ -38,8 +38,8 @@ func (wk *worker) embedTraversals(env *otto.Otto, obj *otto.Object) {
|
||||||
obj.Set("Has", wk.gremlinFunc("has", obj, env))
|
obj.Set("Has", wk.gremlinFunc("has", obj, env))
|
||||||
obj.Set("Save", wk.gremlinFunc("save", obj, env))
|
obj.Set("Save", wk.gremlinFunc("save", obj, env))
|
||||||
obj.Set("SaveR", wk.gremlinFunc("saver", obj, env))
|
obj.Set("SaveR", wk.gremlinFunc("saver", obj, env))
|
||||||
obj.Set("Loop", gremlinFunc("loop", obj, env, ses))
|
obj.Set("Loop", wk.gremlinFunc("loop", obj, env))
|
||||||
obj.Set("Not", gremlinFollowR("not", obj, env, ses))
|
obj.Set("Not", wk.gremlinFunc("not", obj, env))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (wk *worker) gremlinFunc(kind string, prev *otto.Object, env *otto.Otto) func(otto.FunctionCall) otto.Value {
|
func (wk *worker) gremlinFunc(kind string, prev *otto.Object, env *otto.Otto) func(otto.FunctionCall) otto.Value {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue