From 375d953d9341f4de161f60231df5161d69bc5416 Mon Sep 17 00:00:00 2001 From: kortschak Date: Wed, 30 Jul 2014 15:01:09 +0930 Subject: [PATCH] Move current result handling out of Base Delete majority of Base functionality. --- graph/iterator/all_iterator.go | 14 ++++++++-- graph/iterator/and_iterator.go | 13 ++++++--- graph/iterator/fixed_iterator.go | 14 ++++++++-- graph/iterator/hasa_iterator.go | 9 +++++-- graph/iterator/iterator.go | 42 +---------------------------- graph/iterator/linksto_iterator.go | 9 +++++-- graph/iterator/optional_iterator.go | 15 ++++++++++- graph/iterator/or_iterator.go | 11 +++++--- graph/iterator/value_comparison_iterator.go | 28 ++++++++++++------- graph/leveldb/all_iterator.go | 15 ++++++++--- graph/leveldb/iterator.go | 19 +++++++++---- graph/memstore/all_iterator.go | 1 - graph/memstore/iterator.go | 17 +++++++++--- graph/mongo/iterator.go | 15 ++++++++--- 14 files changed, 140 insertions(+), 82 deletions(-) diff --git a/graph/iterator/all_iterator.go b/graph/iterator/all_iterator.go index 004bc68..9466cb4 100644 --- a/graph/iterator/all_iterator.go +++ b/graph/iterator/all_iterator.go @@ -36,6 +36,7 @@ type Int64 struct { tags graph.Tagger max, min int64 at int64 + result graph.Value } // Creates a new Int64 with the given range. @@ -99,10 +100,19 @@ func (it *Int64) Next() (graph.Value, bool) { if it.at > it.max { it.at = -1 } - it.Last = val + it.result = val return graph.NextLogOut(it, val, true) } +// DEPRECATED +func (it *Int64) ResultTree() *graph.ResultTree { + return graph.NewResultTree(it.Result()) +} + +func (it *Int64) Result() graph.Value { + return it.result +} + // No sub-iterators. func (it *Int64) SubIterators() []graph.Iterator { return nil @@ -121,7 +131,7 @@ func (it *Int64) Check(tsv graph.Value) bool { graph.CheckLogIn(it, tsv) v := tsv.(int64) if it.min <= v && v <= it.max { - it.Last = v + it.result = v return graph.CheckLogOut(it, v, true) } return graph.CheckLogOut(it, v, false) diff --git a/graph/iterator/and_iterator.go b/graph/iterator/and_iterator.go index a7dce74..938d9f8 100644 --- a/graph/iterator/and_iterator.go +++ b/graph/iterator/and_iterator.go @@ -32,6 +32,7 @@ type And struct { itCount int primaryIt graph.Iterator checkList []graph.Iterator + result graph.Value } // Creates a new And iterator. @@ -167,11 +168,15 @@ func (it *And) Next() (graph.Value, bool) { return graph.NextLogOut(it, nil, false) } if it.checkSubIts(curr) { - it.Last = curr + it.result = curr return graph.NextLogOut(it, curr, true) } } - panic("Somehow broke out of Next() loop in And") + panic("unreachable") +} + +func (it *And) Result() graph.Value { + return it.result } // Checks a value against the non-primary iterators, in order. @@ -195,7 +200,7 @@ func (it *And) checkCheckList(val graph.Value) bool { } } if ok { - it.Last = val + it.result = val } return graph.CheckLogOut(it, val, ok) } @@ -214,7 +219,7 @@ func (it *And) Check(val graph.Value) bool { if !othersGood { return graph.CheckLogOut(it, val, false) } - it.Last = val + it.result = val return graph.CheckLogOut(it, val, true) } diff --git a/graph/iterator/fixed_iterator.go b/graph/iterator/fixed_iterator.go index 23bf177..82e308a 100644 --- a/graph/iterator/fixed_iterator.go +++ b/graph/iterator/fixed_iterator.go @@ -36,6 +36,7 @@ type Fixed struct { values []graph.Value lastIndex int cmp Equality + result graph.Value } // Define the signature of an equality function. @@ -130,7 +131,7 @@ func (it *Fixed) Check(v graph.Value) bool { graph.CheckLogIn(it, v) for _, x := range it.values { if it.cmp(x, v) { - it.Last = x + it.result = x return graph.CheckLogOut(it, v, true) } } @@ -144,11 +145,20 @@ func (it *Fixed) Next() (graph.Value, bool) { return graph.NextLogOut(it, nil, false) } out := it.values[it.lastIndex] - it.Last = out + it.result = out it.lastIndex++ return graph.NextLogOut(it, out, true) } +// DEPRECATED +func (it *Fixed) ResultTree() *graph.ResultTree { + return graph.NewResultTree(it.Result()) +} + +func (it *Fixed) Result() graph.Value { + return it.result +} + // No sub-iterators. func (it *Fixed) SubIterators() []graph.Iterator { return nil diff --git a/graph/iterator/hasa_iterator.go b/graph/iterator/hasa_iterator.go index dc6eb66..ea9d2cc 100644 --- a/graph/iterator/hasa_iterator.go +++ b/graph/iterator/hasa_iterator.go @@ -53,6 +53,7 @@ type HasA struct { primaryIt graph.Iterator dir graph.Direction resultIt graph.Iterator + result graph.Value } // Construct a new HasA iterator, given the triple subiterator, and the triple @@ -168,7 +169,7 @@ func (it *HasA) GetCheckResult() bool { glog.V(4).Infoln("Triple is", it.ts.Triple(linkVal)) } if it.primaryIt.Check(linkVal) { - it.Last = it.ts.TripleDirection(linkVal, it.dir) + it.result = it.ts.TripleDirection(linkVal, it.dir) return true } } @@ -205,10 +206,14 @@ func (it *HasA) Next() (graph.Value, bool) { } name := it.ts.Triple(tID).Get(it.dir) val := it.ts.ValueOf(name) - it.Last = val + it.result = val return graph.NextLogOut(it, val, true) } +func (it *HasA) Result() graph.Value { + return it.result +} + // GetStats() returns the statistics on the HasA iterator. This is curious. Next // cost is easy, it's an extra call or so on top of the subiterator Next cost. // CheckCost involves going to the graph.TripleStore, iterating out values, and hoping diff --git a/graph/iterator/iterator.go b/graph/iterator/iterator.go index 96153a2..cb06965 100644 --- a/graph/iterator/iterator.go +++ b/graph/iterator/iterator.go @@ -18,7 +18,6 @@ package iterator // iterators can "inherit" from to get default iterator functionality. import ( - "fmt" "strings" "sync/atomic" @@ -34,7 +33,6 @@ func NextUID() uint64 { // The Base iterator is the iterator other iterators inherit from to get some // default functionality. type Base struct { - Last graph.Value canNext bool } @@ -44,50 +42,13 @@ func BaseInit(it *Base) { it.canNext = true } -// Prints a silly debug string. Most classes override. -func (it *Base) DebugString(indent int) string { - return fmt.Sprintf("%s(base)", strings.Repeat(" ", indent)) -} - -// Nothing in a base iterator. -func (it *Base) Check(v graph.Value) bool { - return false -} - -// Base iterators should never appear in a tree if they are, select against -// them. -func (it *Base) Stats() graph.IteratorStats { - return graph.IteratorStats{100000, 100000, 100000} -} - -// DEPRECATED -func (it *Base) ResultTree() *graph.ResultTree { - tree := graph.NewResultTree(it.Result()) - return tree -} - -// Nothing in a base iterator. -func (it *Base) Next() (graph.Value, bool) { - return nil, false -} - func (it *Base) NextResult() bool { return false } -// Returns the last result of an iterator. -func (it *Base) Result() graph.Value { - return it.Last -} - // Accessor func (it *Base) CanNext() bool { return it.canNext } -// Nothing to clean up. -// func (it *Base) Close() {} - -func (it *Base) Reset() {} - // Here we define the simplest iterator -- the Null iterator. It contains nothing. // It is the empty set. Often times, queries that contain one of these match nothing, // so it's important to give it a special iterator. @@ -149,8 +110,7 @@ func (it *Null) Result() graph.Value { } func (it *Null) ResultTree() *graph.ResultTree { - tree := graph.NewResultTree(it.Result()) - return tree + return graph.NewResultTree(it.Result()) } func (it *Null) SubIterators() []graph.Iterator { diff --git a/graph/iterator/linksto_iterator.go b/graph/iterator/linksto_iterator.go index 403a799..80071c4 100644 --- a/graph/iterator/linksto_iterator.go +++ b/graph/iterator/linksto_iterator.go @@ -47,6 +47,7 @@ type LinksTo struct { primaryIt graph.Iterator dir graph.Direction nextIt graph.Iterator + result graph.Value } // Construct a new LinksTo iterator around a direction and a subiterator of @@ -121,7 +122,7 @@ func (it *LinksTo) Check(val graph.Value) bool { graph.CheckLogIn(it, val) node := it.ts.TripleDirection(val, it.dir) if it.primaryIt.Check(node) { - it.Last = val + it.result = val return graph.CheckLogOut(it, val, true) } return graph.CheckLogOut(it, val, false) @@ -169,10 +170,14 @@ func (it *LinksTo) Next() (graph.Value, bool) { // Recurse -- return the first in the next set. return it.Next() } - it.Last = val + it.result = val return graph.NextLogOut(it, val, ok) } +func (it *LinksTo) Result() graph.Value { + return it.result +} + // Close our subiterators. func (it *LinksTo) Close() { it.nextIt.Close() diff --git a/graph/iterator/optional_iterator.go b/graph/iterator/optional_iterator.go index 5dec887..e87549b 100644 --- a/graph/iterator/optional_iterator.go +++ b/graph/iterator/optional_iterator.go @@ -43,6 +43,7 @@ type Optional struct { tags graph.Tagger subIt graph.Iterator lastCheck bool + result graph.Value } // Creates a new optional iterator. @@ -78,6 +79,9 @@ func (it *Optional) Clone() graph.Iterator { return out } +// FIXME(kortschak) When we create a Nexter interface the +// following two methods need to go away. + // Nexting the iterator is unsupported -- error and return an empty set. // (As above, a reasonable alternative would be to Next() an all iterator) func (it *Optional) Next() (graph.Value, bool) { @@ -85,6 +89,15 @@ func (it *Optional) Next() (graph.Value, bool) { return nil, false } +// DEPRECATED +func (it *Optional) ResultTree() *graph.ResultTree { + return graph.NewResultTree(it.Result()) +} + +func (it *Optional) Result() graph.Value { + return it.result +} + // An optional iterator only has a next result if, (a) last time we checked // we had any results whatsoever, and (b) there was another subresult in our // optional subbranch. @@ -106,7 +119,7 @@ func (it *Optional) SubIterators() []graph.Iterator { func (it *Optional) Check(val graph.Value) bool { checked := it.subIt.Check(val) it.lastCheck = checked - it.Last = val + it.result = val return true } diff --git a/graph/iterator/or_iterator.go b/graph/iterator/or_iterator.go index e84c629..20318bf 100644 --- a/graph/iterator/or_iterator.go +++ b/graph/iterator/or_iterator.go @@ -36,6 +36,7 @@ type Or struct { internalIterators []graph.Iterator itCount int currentIterator int + result graph.Value } func NewOr() *Or { @@ -169,11 +170,15 @@ func (it *Or) Next() (graph.Value, bool) { return graph.NextLogOut(it, nil, false) } } else { - it.Last = curr + it.result = curr return graph.NextLogOut(it, curr, true) } } - panic("Somehow broke out of Next() loop in Or") + panic("unreachable") +} + +func (it *Or) Result() graph.Value { + return it.result } // Checks a value against the iterators, in order. @@ -196,7 +201,7 @@ func (it *Or) Check(val graph.Value) bool { if !anyGood { return graph.CheckLogOut(it, val, false) } - it.Last = val + it.result = val return graph.CheckLogOut(it, val, true) } diff --git a/graph/iterator/value_comparison_iterator.go b/graph/iterator/value_comparison_iterator.go index e75e658..6dfd7c5 100644 --- a/graph/iterator/value_comparison_iterator.go +++ b/graph/iterator/value_comparison_iterator.go @@ -47,12 +47,13 @@ const ( type Comparison struct { Base - uid uint64 - tags graph.Tagger - subIt graph.Iterator - op Operator - val interface{} - ts graph.TripleStore + uid uint64 + tags graph.Tagger + subIt graph.Iterator + op Operator + val interface{} + ts graph.TripleStore + result graph.Value } func NewComparison(sub graph.Iterator, op Operator, val interface{}, ts graph.TripleStore) *Comparison { @@ -141,10 +142,19 @@ func (it *Comparison) Next() (graph.Value, bool) { break } } - it.Last = val + it.result = val return val, ok } +// DEPRECATED +func (it *Comparison) ResultTree() *graph.ResultTree { + return graph.NewResultTree(it.Result()) +} + +func (it *Comparison) Result() graph.Value { + return it.result +} + func (it *Comparison) NextResult() bool { for { hasNext := it.subIt.NextResult() @@ -155,7 +165,7 @@ func (it *Comparison) NextResult() bool { return true } } - it.Last = it.subIt.Result() + it.result = it.subIt.Result() return true } @@ -213,6 +223,6 @@ func (it *Comparison) Stats() graph.IteratorStats { return it.subIt.Stats() } -func (it *Base) Size() (int64, bool) { +func (it *Comparison) Size() (int64, bool) { return 0, true } diff --git a/graph/leveldb/all_iterator.go b/graph/leveldb/all_iterator.go index 80046c3..27cb144 100644 --- a/graph/leveldb/all_iterator.go +++ b/graph/leveldb/all_iterator.go @@ -36,6 +36,7 @@ type AllIterator struct { iter ldbit.Iterator ts *TripleStore ro *opt.ReadOptions + result graph.Value } func NewAllIterator(prefix string, d graph.Direction, ts *TripleStore) *AllIterator { @@ -103,7 +104,7 @@ func (it *AllIterator) Clone() graph.Iterator { func (it *AllIterator) Next() (graph.Value, bool) { if !it.open { - it.Last = nil + it.result = nil return nil, false } var out []byte @@ -117,17 +118,25 @@ func (it *AllIterator) Next() (graph.Value, bool) { it.Close() return nil, false } - it.Last = out + it.result = out return out, true } +func (it *AllIterator) ResultTree() *graph.ResultTree { + return graph.NewResultTree(it.Result()) +} + +func (it *AllIterator) Result() graph.Value { + return it.result +} + // No subiterators. func (it *AllIterator) SubIterators() []graph.Iterator { return nil } func (it *AllIterator) Check(v graph.Value) bool { - it.Last = v + it.result = v return true } diff --git a/graph/leveldb/iterator.go b/graph/leveldb/iterator.go index d677bcb..1b6771e 100644 --- a/graph/leveldb/iterator.go +++ b/graph/leveldb/iterator.go @@ -38,6 +38,7 @@ type Iterator struct { ts *TripleStore ro *opt.ReadOptions originalPrefix string + result graph.Value } func NewIterator(prefix string, d graph.Direction, value graph.Value, ts *TripleStore) *Iterator { @@ -119,22 +120,22 @@ func (it *Iterator) Close() { func (it *Iterator) Next() (graph.Value, bool) { if it.iter == nil { - it.Last = nil + it.result = nil return nil, false } if !it.open { - it.Last = nil + it.result = nil return nil, false } if !it.iter.Valid() { - it.Last = nil + it.result = nil it.Close() return nil, false } if bytes.HasPrefix(it.iter.Key(), it.nextPrefix) { out := make([]byte, len(it.iter.Key())) copy(out, it.iter.Key()) - it.Last = out + it.result = out ok := it.iter.Next() if !ok { it.Close() @@ -142,10 +143,18 @@ func (it *Iterator) Next() (graph.Value, bool) { return out, true } it.Close() - it.Last = nil + it.result = nil return nil, false } +func (it *Iterator) ResultTree() *graph.ResultTree { + return graph.NewResultTree(it.Result()) +} + +func (it *Iterator) Result() graph.Value { + return it.result +} + // No subiterators. func (it *Iterator) SubIterators() []graph.Iterator { return nil diff --git a/graph/memstore/all_iterator.go b/graph/memstore/all_iterator.go index 204a015..658a4a1 100644 --- a/graph/memstore/all_iterator.go +++ b/graph/memstore/all_iterator.go @@ -46,6 +46,5 @@ func (it *AllIterator) Next() (graph.Value, bool) { if !ok { return it.Next() } - it.Last = next return next, out } diff --git a/graph/memstore/iterator.go b/graph/memstore/iterator.go index 290fef6..be6d1ff 100644 --- a/graph/memstore/iterator.go +++ b/graph/memstore/iterator.go @@ -33,6 +33,7 @@ type Iterator struct { data string isRunning bool iterLast Int64 + result graph.Value } type Int64 int64 @@ -97,12 +98,20 @@ func (it *Iterator) Close() {} func (it *Iterator) Next() (graph.Value, bool) { graph.NextLogIn(it) - if it.tree.Max() == nil || it.Last == int64(it.tree.Max().(Int64)) { + if it.tree.Max() == nil || it.result == int64(it.tree.Max().(Int64)) { return graph.NextLogOut(it, nil, false) } it.iterLast = IterateOne(it.tree, it.iterLast) - it.Last = int64(it.iterLast) - return graph.NextLogOut(it, it.Last, true) + it.result = int64(it.iterLast) + return graph.NextLogOut(it, it.result, true) +} + +func (it *Iterator) ResultTree() *graph.ResultTree { + return graph.NewResultTree(it.Result()) +} + +func (it *Iterator) Result() graph.Value { + return it.result } // No subiterators. @@ -117,7 +126,7 @@ func (it *Iterator) Size() (int64, bool) { func (it *Iterator) Check(v graph.Value) bool { graph.CheckLogIn(it, v) if it.tree.Has(Int64(v.(int64))) { - it.Last = v + it.result = v return graph.CheckLogOut(it, v, true) } return graph.CheckLogOut(it, v, false) diff --git a/graph/mongo/iterator.go b/graph/mongo/iterator.go index 3afe77e..ab752ef 100644 --- a/graph/mongo/iterator.go +++ b/graph/mongo/iterator.go @@ -39,6 +39,7 @@ type Iterator struct { isAll bool constraint bson.M collection string + result graph.Value } func NewIterator(ts *TripleStore, collection string, d graph.Direction, val graph.Value) *Iterator { @@ -158,10 +159,18 @@ func (it *Iterator) Next() (graph.Value, bool) { } return nil, false } - it.Last = result.Id + it.result = result.Id return result.Id, true } +func (it *Iterator) ResultTree() *graph.ResultTree { + return graph.NewResultTree(it.Result()) +} + +func (it *Iterator) Result() graph.Value { + return it.result +} + // No subiterators. func (it *Iterator) SubIterators() []graph.Iterator { return nil @@ -170,7 +179,7 @@ func (it *Iterator) SubIterators() []graph.Iterator { func (it *Iterator) Check(v graph.Value) bool { graph.CheckLogIn(it, v) if it.isAll { - it.Last = v + it.result = v return graph.CheckLogOut(it, v, true) } var offset int @@ -186,7 +195,7 @@ func (it *Iterator) Check(v graph.Value) bool { } val := v.(string)[offset : it.ts.hasher.Size()*2+offset] if val == it.hash { - it.Last = v + it.result = v return graph.CheckLogOut(it, v, true) } return graph.CheckLogOut(it, v, false)