diff --git a/graph/iterator.go b/graph/iterator.go index 5b3cd8a..a6b315c 100644 --- a/graph/iterator.go +++ b/graph/iterator.go @@ -77,10 +77,14 @@ type Iterator interface { // the iteration interface. // // To get the full results of iteration, do the following: - // while (!Next()): - // emit result - // while (!NextPath()): - // emit result + // + // for graph.Next(it) { + // val := it.Result() + // ... do things with val. + // for it.NextPath() { + // ... find other paths to iterate + // } + // } // // All of them should set iterator.Last to be the last returned value, to // make results work. @@ -135,22 +139,22 @@ type Iterator interface { } type Nexter interface { - // Next() advances the iterator and returns the next valid result. Returns - // (, true) or (nil, false) - Next() (Value, bool) + // Next advances the iterator to the next value, which will then be available through + // the Result method. It returns false if no further advancement is possible. + Next() bool Iterator } // Next is a convenience function that conditionally calls the Next method // of an Iterator if it is a Nexter. If the Iterator is not a Nexter, Next -// return a nil Value and false. -func Next(it Iterator) (Value, bool) { +// returns false. +func Next(it Iterator) bool { if n, ok := it.(Nexter); ok { return n.Next() } glog.Errorln("Nexting an un-nextable iterator") - return nil, false + return false } // FixedIterator wraps iterators that are modifiable by addition of fixed value sets. @@ -253,7 +257,7 @@ func NextLogIn(it Iterator) { } } -func NextLogOut(it Iterator, val Value, ok bool) (Value, bool) { +func NextLogOut(it Iterator, val Value, ok bool) bool { if glog.V(4) { if ok { glog.V(4).Infof("%s %d NEXT IS %d", strings.ToUpper(it.Type().String()), it.UID(), val) @@ -261,5 +265,5 @@ func NextLogOut(it Iterator, val Value, ok bool) (Value, bool) { glog.V(4).Infof("%s %d NEXT DONE", strings.ToUpper(it.Type().String()), it.UID()) } } - return val, ok + return ok } diff --git a/graph/iterator/all_iterator.go b/graph/iterator/all_iterator.go index 79f4057..80e471c 100644 --- a/graph/iterator/all_iterator.go +++ b/graph/iterator/all_iterator.go @@ -87,7 +87,7 @@ func (it *Int64) DebugString(indent int) string { // Next() on an Int64 all iterator is a simple incrementing counter. // Return the next integer, and mark it as the result. -func (it *Int64) Next() (graph.Value, bool) { +func (it *Int64) Next() bool { graph.NextLogIn(it) if it.at == -1 { return graph.NextLogOut(it, nil, false) diff --git a/graph/iterator/and_iterator.go b/graph/iterator/and_iterator.go index 3fba7d1..7cb7577 100644 --- a/graph/iterator/and_iterator.go +++ b/graph/iterator/and_iterator.go @@ -151,25 +151,20 @@ func (it *And) AddSubIterator(sub graph.Iterator) { it.itCount++ } -// Returns the Next value from the And iterator. Because the And is the -// intersection of its subiterators, it must choose one subiterator to produce a -// candidate, and check this value against the subiterators. A productive choice -// of primary iterator is therefore very important. -func (it *And) Next() (graph.Value, bool) { +// Returns advances the And iterator. Because the And is the intersection of its +// subiterators, it must choose one subiterator to produce a candidate, and check +// this value against the subiterators. A productive choice of primary iterator +// is therefore very important. +func (it *And) Next() bool { graph.NextLogIn(it) - var curr graph.Value - var exists bool - for { - curr, exists = graph.Next(it.primaryIt) - if !exists { - return graph.NextLogOut(it, nil, false) - } + for graph.Next(it.primaryIt) { + curr := it.primaryIt.Result() if it.subItsContain(curr) { it.result = curr return graph.NextLogOut(it, curr, true) } } - panic("unreachable") + return graph.NextLogOut(it, nil, false) } func (it *And) Result() graph.Value { diff --git a/graph/iterator/and_iterator_test.go b/graph/iterator/and_iterator_test.go index 82d290a..3023bfd 100644 --- a/graph/iterator/and_iterator_test.go +++ b/graph/iterator/and_iterator_test.go @@ -36,10 +36,10 @@ func TestTag(t *testing.T) { t.Errorf("Cannot get tag back, got %s", out[0]) } - val, ok := and.Next() - if !ok { + if !and.Next() { t.Errorf("And did not next") } + val := and.Result() if val != 234 { t.Errorf("Unexpected value") } @@ -76,18 +76,15 @@ func TestAndAndFixedIterators(t *testing.T) { t.Error("not accurate") } - val, ok := and.Next() - if val != 3 || ok == false { + if !and.Next() || and.Result() != 3 { t.Error("Incorrect first value") } - val, ok = and.Next() - if val != 4 || ok == false { + if !and.Next() || and.Result() != 4 { t.Error("Incorrect second value") } - val, ok = and.Next() - if ok { + if and.Next() { t.Error("Too many values") } @@ -117,8 +114,7 @@ func TestNonOverlappingFixedIterators(t *testing.T) { t.Error("not accurate") } - _, ok := and.Next() - if ok { + if and.Next() { t.Error("Too many values") } @@ -131,18 +127,15 @@ func TestAllIterators(t *testing.T) { and.AddSubIterator(all2) and.AddSubIterator(all1) - val, ok := and.Next() - if val.(int64) != 4 || ok == false { + if !and.Next() || and.Result() != int64(4) { t.Error("Incorrect first value") } - val, ok = and.Next() - if val.(int64) != 5 || ok == false { + if !and.Next() || and.Result() != int64(5) { t.Error("Incorrect second value") } - val, ok = and.Next() - if ok { + if and.Next() { t.Error("Too many values") } diff --git a/graph/iterator/fixed_iterator.go b/graph/iterator/fixed_iterator.go index 4fbcf08..a2d57b1 100644 --- a/graph/iterator/fixed_iterator.go +++ b/graph/iterator/fixed_iterator.go @@ -135,8 +135,8 @@ func (it *Fixed) Contains(v graph.Value) bool { return graph.ContainsLogOut(it, v, false) } -// Return the next stored value from the iterator. -func (it *Fixed) Next() (graph.Value, bool) { +// Next advances the iterator. +func (it *Fixed) Next() bool { graph.NextLogIn(it) if it.lastIndex == len(it.values) { return graph.NextLogOut(it, nil, false) diff --git a/graph/iterator/hasa_iterator.go b/graph/iterator/hasa_iterator.go index 93305e7..93e224a 100644 --- a/graph/iterator/hasa_iterator.go +++ b/graph/iterator/hasa_iterator.go @@ -158,16 +158,13 @@ func (it *HasA) Contains(val graph.Value) bool { // result iterator (a triple iterator based on the last checked value) and returns true if // another match is made. func (it *HasA) NextContains() bool { - for { - linkVal, ok := graph.Next(it.resultIt) - if !ok { - break - } + for graph.Next(it.resultIt) { + link := it.resultIt.Result() if glog.V(4) { - glog.V(4).Infoln("Quad is", it.ts.Quad(linkVal)) + glog.V(4).Infoln("Quad is", it.ts.Quad(link)) } - if it.primaryIt.Contains(linkVal) { - it.result = it.ts.TripleDirection(linkVal, it.dir) + if it.primaryIt.Contains(link) { + it.result = it.ts.TripleDirection(link, it.dir) return true } } @@ -188,20 +185,20 @@ func (it *HasA) NextPath() bool { return it.NextContains() } -// Get the next result from this iterator. This is simpler than Contains. We have a +// Next advances the iterator. This is simpler than Contains. We have a // subiterator we can get a value from, and we can take that resultant triple, // pull our direction out of it, and return that. -func (it *HasA) Next() (graph.Value, bool) { +func (it *HasA) Next() bool { graph.NextLogIn(it) if it.resultIt != nil { it.resultIt.Close() } it.resultIt = &Null{} - tID, ok := graph.Next(it.primaryIt) - if !ok { + if !graph.Next(it.primaryIt) { return graph.NextLogOut(it, 0, false) } + tID := it.primaryIt.Result() name := it.ts.Quad(tID).Get(it.dir) val := it.ts.ValueOf(name) it.result = val diff --git a/graph/iterator/iterator.go b/graph/iterator/iterator.go index 582991f..67d8a80 100644 --- a/graph/iterator/iterator.go +++ b/graph/iterator/iterator.go @@ -79,8 +79,8 @@ func (it *Null) DebugString(indent int) string { return strings.Repeat(" ", indent) + "(null)" } -func (it *Null) Next() (graph.Value, bool) { - return nil, false +func (it *Null) Next() bool { + return false } func (it *Null) Result() graph.Value { diff --git a/graph/iterator/linksto_iterator.go b/graph/iterator/linksto_iterator.go index 8148aa4..517fc11 100644 --- a/graph/iterator/linksto_iterator.go +++ b/graph/iterator/linksto_iterator.go @@ -153,23 +153,23 @@ func (it *LinksTo) Optimize() (graph.Iterator, bool) { } // Next()ing a LinksTo operates as described above. -func (it *LinksTo) Next() (graph.Value, bool) { +func (it *LinksTo) Next() bool { graph.NextLogIn(it) - val, ok := graph.Next(it.nextIt) - if !ok { - // Subiterator is empty, get another one - candidate, ok := graph.Next(it.primaryIt) - if !ok { - // We're out of nodes in our subiterator, so we're done as well. - return graph.NextLogOut(it, 0, false) - } - it.nextIt.Close() - it.nextIt = it.ts.TripleIterator(it.dir, candidate) - // Recurse -- return the first in the next set. - return it.Next() + if graph.Next(it.nextIt) { + it.result = it.nextIt.Result() + return graph.NextLogOut(it, it.nextIt, true) } - it.result = val - return graph.NextLogOut(it, val, ok) + + // Subiterator is empty, get another one + if !graph.Next(it.primaryIt) { + // We're out of nodes in our subiterator, so we're done as well. + return graph.NextLogOut(it, 0, false) + } + it.nextIt.Close() + it.nextIt = it.ts.TripleIterator(it.dir, it.primaryIt.Result()) + + // Recurse -- return the first in the next set. + return it.Next() } func (it *LinksTo) Result() graph.Value { diff --git a/graph/iterator/linksto_iterator_test.go b/graph/iterator/linksto_iterator_test.go index 797ce6e..b1eb1fa 100644 --- a/graph/iterator/linksto_iterator_test.go +++ b/graph/iterator/linksto_iterator_test.go @@ -33,10 +33,10 @@ func TestLinksTo(t *testing.T) { } fixed.Add(val) lto := NewLinksTo(ts, fixed, quad.Object) - val, ok := lto.Next() - if !ok { + if !lto.Next() { t.Error("At least one triple matches the fixed object") } + val = lto.Result() if val != 2 { t.Errorf("Quad index 2, such as %s, should match %s", ts.Quad(2), ts.Quad(val)) } diff --git a/graph/iterator/optional_iterator.go b/graph/iterator/optional_iterator.go index 0cd7eb5..2432390 100644 --- a/graph/iterator/optional_iterator.go +++ b/graph/iterator/optional_iterator.go @@ -51,8 +51,6 @@ func NewOptional(it graph.Iterator) *Optional { } } -func (it *Optional) CanNext() bool { return false } - func (it *Optional) UID() uint64 { return it.uid } diff --git a/graph/iterator/or_iterator.go b/graph/iterator/or_iterator.go index b1b8100..ddff768 100644 --- a/graph/iterator/or_iterator.go +++ b/graph/iterator/or_iterator.go @@ -141,35 +141,34 @@ func (it *Or) AddSubIterator(sub graph.Iterator) { it.itCount++ } -// Returns the Next value from the Or graph.iterator. Because the Or is the -// union of its subiterators, it must produce from all subiterators -- unless -// it's shortcircuiting, in which case, it's the first one that returns anything. -func (it *Or) Next() (graph.Value, bool) { +// Next advances the Or graph.iterator. Because the Or is the union of its +// subiterators, it must produce from all subiterators -- unless it it +// shortcircuiting, in which case, it is the first one that returns anything. +func (it *Or) Next() bool { graph.NextLogIn(it) - var curr graph.Value - var exists bool - firstTime := false + var first bool for { if it.currentIterator == -1 { it.currentIterator = 0 - firstTime = true + first = true } curIt := it.internalIterators[it.currentIterator] - curr, exists = graph.Next(curIt) - if !exists { - if it.isShortCircuiting && !firstTime { - return graph.NextLogOut(it, nil, false) - } - it.currentIterator++ - if it.currentIterator == it.itCount { - return graph.NextLogOut(it, nil, false) - } - } else { - it.result = curr - return graph.NextLogOut(it, curr, true) + + if graph.Next(curIt) { + it.result = curIt.Result() + return graph.NextLogOut(it, it.result, true) + } + + if it.isShortCircuiting && !first { + break + } + it.currentIterator++ + if it.currentIterator == it.itCount { + break } } - panic("unreachable") + + return graph.NextLogOut(it, nil, false) } func (it *Or) Result() graph.Value { diff --git a/graph/iterator/or_iterator_test.go b/graph/iterator/or_iterator_test.go index bbd5de6..b147d56 100644 --- a/graph/iterator/or_iterator_test.go +++ b/graph/iterator/or_iterator_test.go @@ -23,12 +23,8 @@ import ( func iterated(it graph.Iterator) []int { var res []int - for { - val, ok := graph.Next(it) - if !ok { - break - } - res = append(res, val.(int)) + for graph.Next(it) { + res = append(res, it.Result().(int)) } return res } diff --git a/graph/iterator/query_shape.go b/graph/iterator/query_shape.go index 973f6db..77e10eb 100644 --- a/graph/iterator/query_shape.go +++ b/graph/iterator/query_shape.go @@ -129,12 +129,8 @@ func (qs *queryShape) MakeNode(it graph.Iterator) *Node { } case graph.Fixed: n.IsFixed = true - for { - val, more := graph.Next(it) - if !more { - break - } - n.Values = append(n.Values, qs.ts.NameOf(val)) + for graph.Next(it) { + n.Values = append(n.Values, qs.ts.NameOf(it.Result())) } case graph.HasA: hasa := it.(*HasA) diff --git a/graph/iterator/value_comparison_iterator.go b/graph/iterator/value_comparison_iterator.go index 405d152..91b1985 100644 --- a/graph/iterator/value_comparison_iterator.go +++ b/graph/iterator/value_comparison_iterator.go @@ -127,20 +127,15 @@ func (it *Comparison) Clone() graph.Iterator { return out } -func (it *Comparison) Next() (graph.Value, bool) { - var val graph.Value - var ok bool - for { - val, ok = graph.Next(it.subIt) - if !ok { - return nil, false - } +func (it *Comparison) Next() bool { + for graph.Next(it.subIt) { + val := it.subIt.Result() if it.doComparison(val) { - break + it.result = val + return true } } - it.result = val - return val, ok + return false } // DEPRECATED diff --git a/graph/iterator/value_comparison_iterator_test.go b/graph/iterator/value_comparison_iterator_test.go index e7482e8..a2bb108 100644 --- a/graph/iterator/value_comparison_iterator_test.go +++ b/graph/iterator/value_comparison_iterator_test.go @@ -69,12 +69,8 @@ func TestValueComparison(t *testing.T) { vc := NewComparison(simpleFixedIterator(), test.operator, test.operand, ts) var got []string - for { - val, ok := vc.Next() - if !ok { - break - } - got = append(got, ts.NameOf(val)) + for vc.Next() { + got = append(got, ts.NameOf(vc.Result())) } if !reflect.DeepEqual(got, test.expect) { t.Errorf("Failed to show %s, got:%q expect:%q", test.message, got, test.expect) diff --git a/graph/leveldb/all_iterator.go b/graph/leveldb/all_iterator.go index f0504f1..15c8882 100644 --- a/graph/leveldb/all_iterator.go +++ b/graph/leveldb/all_iterator.go @@ -101,10 +101,10 @@ func (it *AllIterator) Clone() graph.Iterator { return out } -func (it *AllIterator) Next() (graph.Value, bool) { +func (it *AllIterator) Next() bool { if !it.open { it.result = nil - return nil, false + return false } var out []byte out = make([]byte, len(it.iter.Key())) @@ -115,10 +115,10 @@ func (it *AllIterator) Next() (graph.Value, bool) { } if !bytes.HasPrefix(out, it.prefix) { it.Close() - return nil, false + return false } it.result = out - return out, true + return true } func (it *AllIterator) ResultTree() *graph.ResultTree { diff --git a/graph/leveldb/iterator.go b/graph/leveldb/iterator.go index 01e2ba8..13e3ed3 100644 --- a/graph/leveldb/iterator.go +++ b/graph/leveldb/iterator.go @@ -117,19 +117,19 @@ func (it *Iterator) Close() { } } -func (it *Iterator) Next() (graph.Value, bool) { +func (it *Iterator) Next() bool { if it.iter == nil { it.result = nil - return nil, false + return false } if !it.open { it.result = nil - return nil, false + return false } if !it.iter.Valid() { it.result = nil it.Close() - return nil, false + return false } if bytes.HasPrefix(it.iter.Key(), it.nextPrefix) { out := make([]byte, len(it.iter.Key())) @@ -139,11 +139,11 @@ func (it *Iterator) Next() (graph.Value, bool) { if !ok { it.Close() } - return out, true + return true } it.Close() it.result = nil - return nil, false + return false } func (it *Iterator) ResultTree() *graph.ResultTree { diff --git a/graph/leveldb/leveldb_test.go b/graph/leveldb/leveldb_test.go index 0e6772a..c6f3653 100644 --- a/graph/leveldb/leveldb_test.go +++ b/graph/leveldb/leveldb_test.go @@ -45,12 +45,8 @@ func makeTripleSet() []*quad.Quad { func iteratedTriples(qs graph.TripleStore, it graph.Iterator) []*quad.Quad { var res ordered - for { - val, ok := graph.Next(it) - if !ok { - break - } - res = append(res, qs.Quad(val)) + for graph.Next(it) { + res = append(res, qs.Quad(it.Result())) } sort.Sort(res) return res @@ -85,12 +81,8 @@ func (o ordered) Swap(i, j int) { o[i], o[j] = o[j], o[i] } func iteratedNames(qs graph.TripleStore, it graph.Iterator) []string { var res []string - for { - val, ok := graph.Next(it) - if !ok { - break - } - res = append(res, qs.NameOf(val)) + for graph.Next(it) { + res = append(res, qs.NameOf(it.Result())) } sort.Strings(res) return res @@ -266,8 +258,8 @@ func TestIterator(t *testing.T) { it.Reset() it = qs.TriplesAllIterator() - edge, _ := graph.Next(it) - triple := qs.Quad(edge) + graph.Next(it) + triple := qs.Quad(it.Result()) set := makeTripleSet() var ok bool for _, t := range set { diff --git a/graph/leveldb/triplestore_iterator_optimize.go b/graph/leveldb/triplestore_iterator_optimize.go index 9aab0f2..31b7f7d 100644 --- a/graph/leveldb/triplestore_iterator_optimize.go +++ b/graph/leveldb/triplestore_iterator_optimize.go @@ -37,10 +37,10 @@ func (ts *TripleStore) optimizeLinksTo(it *iterator.LinksTo) (graph.Iterator, bo if primary.Type() == graph.Fixed { size, _ := primary.Size() if size == 1 { - val, ok := graph.Next(primary) - if !ok { - panic("Sizes lie") + if !graph.Next(primary) { + panic("unexpected size during optimize") } + val := primary.Result() newIt := ts.TripleIterator(it.Direction(), val) nt := newIt.Tagger() nt.CopyFrom(it) diff --git a/graph/memstore/all_iterator.go b/graph/memstore/all_iterator.go index 658a4a1..658254e 100644 --- a/graph/memstore/all_iterator.go +++ b/graph/memstore/all_iterator.go @@ -36,15 +36,13 @@ func (it *AllIterator) SubIterators() []graph.Iterator { return nil } -func (it *AllIterator) Next() (graph.Value, bool) { - next, out := it.Int64.Next() - if !out { - return next, out +func (it *AllIterator) Next() bool { + if !it.Int64.Next() { + return false } - i64 := next.(int64) - _, ok := it.ts.revIdMap[i64] + _, ok := it.ts.revIdMap[it.Int64.Result().(int64)] if !ok { return it.Next() } - return next, out + return true } diff --git a/graph/memstore/iterator.go b/graph/memstore/iterator.go index a84b069..24dda19 100644 --- a/graph/memstore/iterator.go +++ b/graph/memstore/iterator.go @@ -93,7 +93,7 @@ func (it *Iterator) Clone() graph.Iterator { func (it *Iterator) Close() {} -func (it *Iterator) Next() (graph.Value, bool) { +func (it *Iterator) Next() bool { graph.NextLogIn(it) if it.tree.Max() == nil || it.result == int64(it.tree.Max().(Int64)) { return graph.NextLogOut(it, nil, false) diff --git a/graph/memstore/triplestore.go b/graph/memstore/triplestore.go index 23eb11a..7199fdf 100644 --- a/graph/memstore/triplestore.go +++ b/graph/memstore/triplestore.go @@ -132,11 +132,8 @@ func (ts *TripleStore) tripleExists(t *quad.Quad) (bool, int64) { } it := NewLlrbIterator(smallest_tree, "") - for { - val, ok := it.Next() - if !ok { - break - } + for it.Next() { + val := it.Result() if t.Equals(&ts.triples[val.(int64)]) { return true, val.(int64) } diff --git a/graph/memstore/triplestore_iterator_optimize.go b/graph/memstore/triplestore_iterator_optimize.go index 3dc2c2c..ae5628f 100644 --- a/graph/memstore/triplestore_iterator_optimize.go +++ b/graph/memstore/triplestore_iterator_optimize.go @@ -37,10 +37,10 @@ func (ts *TripleStore) optimizeLinksTo(it *iterator.LinksTo) (graph.Iterator, bo if primary.Type() == graph.Fixed { size, _ := primary.Size() if size == 1 { - val, ok := graph.Next(primary) - if !ok { - panic("Sizes lie") + if !graph.Next(primary) { + panic("unexpected size during optimize") } + val := primary.Result() newIt := ts.TripleIterator(it.Direction(), val) nt := newIt.Tagger() nt.CopyFrom(it) diff --git a/graph/memstore/triplestore_test.go b/graph/memstore/triplestore_test.go index 80d25f0..b790140 100644 --- a/graph/memstore/triplestore_test.go +++ b/graph/memstore/triplestore_test.go @@ -114,10 +114,10 @@ func TestIteratorsAndNextResultOrderA(t *testing.T) { outerAnd.AddSubIterator(fixed) outerAnd.AddSubIterator(hasa) - val, ok := outerAnd.Next() - if !ok { + if !outerAnd.Next() { t.Error("Expected one matching subtree") } + val := outerAnd.Result() if ts.NameOf(val) != "C" { t.Errorf("Matching subtree should be %s, got %s", "barak", ts.NameOf(val)) } @@ -138,8 +138,7 @@ func TestIteratorsAndNextResultOrderA(t *testing.T) { t.Errorf("Unexpected result, got:%q expect:%q", got, expect) } - val, ok = outerAnd.Next() - if ok { + if outerAnd.Next() { t.Error("More than one possible top level output?") } } @@ -190,8 +189,7 @@ func TestRemoveTriple(t *testing.T) { hasa := iterator.NewHasA(ts, innerAnd, quad.Object) newIt, _ := hasa.Optimize() - _, ok := graph.Next(newIt) - if ok { + if graph.Next(newIt) { t.Error("E should not have any followers.") } } diff --git a/graph/mongo/iterator.go b/graph/mongo/iterator.go index 59444b7..9e37089 100644 --- a/graph/mongo/iterator.go +++ b/graph/mongo/iterator.go @@ -138,7 +138,7 @@ func (it *Iterator) Clone() graph.Iterator { return m } -func (it *Iterator) Next() (graph.Value, bool) { +func (it *Iterator) Next() bool { var result struct { Id string "_id" //Sub string "Sub" @@ -151,10 +151,10 @@ func (it *Iterator) Next() (graph.Value, bool) { if err != nil { glog.Errorln("Error Nexting Iterator: ", err) } - return nil, false + return false } it.result = result.Id - return result.Id, true + return true } func (it *Iterator) ResultTree() *graph.ResultTree { diff --git a/graph/mongo/triplestore_iterator_optimize.go b/graph/mongo/triplestore_iterator_optimize.go index d2d1a05..99fb25b 100644 --- a/graph/mongo/triplestore_iterator_optimize.go +++ b/graph/mongo/triplestore_iterator_optimize.go @@ -37,10 +37,10 @@ func (ts *TripleStore) optimizeLinksTo(it *iterator.LinksTo) (graph.Iterator, bo if primary.Type() == graph.Fixed { size, _ := primary.Size() if size == 1 { - val, ok := graph.Next(primary) - if !ok { - panic("Sizes lie") + if !graph.Next(primary) { + panic("unexpected size during optimize") } + val := primary.Result() newIt := ts.TripleIterator(it.Direction(), val) nt := newIt.Tagger() nt.CopyFrom(it) diff --git a/graph/result_tree_evaluator.go b/graph/result_tree_evaluator.go index dfa988a..56947d4 100644 --- a/graph/result_tree_evaluator.go +++ b/graph/result_tree_evaluator.go @@ -14,7 +14,10 @@ package graph -import "fmt" +import ( + "bytes" + "fmt" +) type ResultTree struct { result Value @@ -26,14 +29,13 @@ func NewResultTree(result Value) *ResultTree { } func (t *ResultTree) String() string { - base := fmt.Sprintf("(%d", t.result) - if len(t.subtrees) != 0 { - for _, sub := range t.subtrees { - base += fmt.Sprintf(" %s", sub) - } + var buf bytes.Buffer + fmt.Fprintf(&buf, "(%d", t.result) + for _, sub := range t.subtrees { + fmt.Fprintf(&buf, " %s", sub) } - base += ")" - return base + buf.WriteByte(')') + return buf.String() } func (t *ResultTree) AddSubtree(sub *ResultTree) { @@ -41,22 +43,15 @@ func (t *ResultTree) AddSubtree(sub *ResultTree) { } func StringResultTreeEvaluator(it Nexter) string { - ok := true - out := "" - for { - _, ok = it.Next() - if !ok { - break - } - out += it.ResultTree().String() - out += "\n" - for it.NextPath() == true { - out += " " - out += it.ResultTree().String() - out += "\n" + var buf bytes.Buffer + for it.Next() { + fmt.Fprintln(&buf, it.ResultTree()) + for it.NextPath() { + buf.WriteByte(' ') + fmt.Fprintln(&buf, it.ResultTree()) } } - return out + return buf.String() } func PrintResultTreeEvaluator(it Nexter) { diff --git a/query/gremlin/finals.go b/query/gremlin/finals.go index dd9b2f0..12f07e6 100644 --- a/query/gremlin/finals.go +++ b/query/gremlin/finals.go @@ -151,8 +151,7 @@ func runIteratorToArray(it graph.Iterator, ses *Session, limit int) []map[string if ses.doHalt { return nil } - _, ok := graph.Next(it) - if !ok { + if !graph.Next(it) { break } tags := make(map[string]graph.Value) @@ -187,11 +186,10 @@ func runIteratorToArrayNoTags(it graph.Iterator, ses *Session, limit int) []stri if ses.doHalt { return nil } - val, ok := graph.Next(it) - if !ok { + if !graph.Next(it) { break } - output = append(output, ses.ts.NameOf(val)) + output = append(output, ses.ts.NameOf(it.Result())) count++ if limit >= 0 && count >= limit { break @@ -208,8 +206,7 @@ func runIteratorWithCallback(it graph.Iterator, ses *Session, callback otto.Valu if ses.doHalt { return } - _, ok := graph.Next(it) - if !ok { + if !graph.Next(it) { break } tags := make(map[string]graph.Value) @@ -249,8 +246,7 @@ func runIteratorOnSession(it graph.Iterator, ses *Session) { if ses.doHalt { return } - _, ok := graph.Next(it) - if !ok { + if !graph.Next(it) { break } tags := make(map[string]graph.Value) diff --git a/query/mql/session.go b/query/mql/session.go index 3c6d1b1..63aa6ba 100644 --- a/query/mql/session.go +++ b/query/mql/session.go @@ -88,11 +88,7 @@ func (s *Session) ExecInput(input string, c chan interface{}, limit int) { if glog.V(2) { glog.V(2).Infoln(it.DebugString(0)) } - for { - _, ok := graph.Next(it) - if !ok { - break - } + for graph.Next(it) { tags := make(map[string]graph.Value) it.TagResults(tags) c <- tags diff --git a/query/sexp/parser_test.go b/query/sexp/parser_test.go index e7e66bf..d74e546 100644 --- a/query/sexp/parser_test.go +++ b/query/sexp/parser_test.go @@ -67,10 +67,10 @@ func TestMemstoreBackedSexp(t *testing.T) { if it.Type() != test.typ { t.Errorf("Incorrect type for %s, got:%q expect %q", test.message, it.Type(), test.expect) } - got, ok := graph.Next(it) - if !ok { + if !graph.Next(it) { t.Errorf("Failed to %s", test.message) } + got := it.Result() if expect := ts.ValueOf(test.expect); got != expect { t.Errorf("Incorrect result for %s, got:%v expect %v", test.message, got, expect) } @@ -88,10 +88,10 @@ func TestTreeConstraintParse(t *testing.T) { if it.Type() != graph.And { t.Error("Odd iterator tree. Got: %s", it.DebugString(0)) } - out, ok := graph.Next(it) - if !ok { + if !graph.Next(it) { t.Error("Got no results") } + out := it.Result() if out != ts.ValueOf("i") { t.Errorf("Got %d, expected %d", out, ts.ValueOf("i")) } @@ -105,8 +105,7 @@ func TestTreeConstraintTagParse(t *testing.T) { "(:like\n" + "($a (:is :good))))" it := BuildIteratorTreeForQuery(ts, query) - _, ok := graph.Next(it) - if !ok { + if !graph.Next(it) { t.Error("Got no results") } tags := make(map[string]graph.Value) @@ -135,15 +134,14 @@ func TestMultipleConstraintParse(t *testing.T) { if it.Type() != graph.And { t.Error("Odd iterator tree. Got: %s", it.DebugString(0)) } - out, ok := graph.Next(it) - if !ok { + if !graph.Next(it) { t.Error("Got no results") } + out := it.Result() if out != ts.ValueOf("i") { t.Errorf("Got %d, expected %d", out, ts.ValueOf("i")) } - _, ok = graph.Next(it) - if ok { + if graph.Next(it) { t.Error("Too many results") } } diff --git a/query/sexp/session.go b/query/sexp/session.go index 2a3671a..eea974f 100644 --- a/query/sexp/session.go +++ b/query/sexp/session.go @@ -77,11 +77,7 @@ func (s *Session) ExecInput(input string, out chan interface{}, limit int) { fmt.Println(it.DebugString(0)) } nResults := 0 - for { - _, ok := graph.Next(it) - if !ok { - break - } + for graph.Next(it) { tags := make(map[string]graph.Value) it.TagResults(tags) out <- &tags