diff --git a/graph/iterator/and_iterator.go b/graph/iterator/and_iterator.go index f7da02f..2cf8691 100644 --- a/graph/iterator/and_iterator.go +++ b/graph/iterator/and_iterator.go @@ -190,8 +190,13 @@ func (it *And) checkContainsList(val graph.Value, lastResult graph.Value) bool { for i, c := range it.checkList { ok = c.Contains(val) if !ok { + if err := c.Err(); err != nil { + it.err = err + return false + } if lastResult != nil { for j := 0; j < i; j++ { + // TODO(andrew-d): Should this result actually be used? it.checkList[j].Contains(lastResult) } } @@ -249,10 +254,18 @@ func (it *And) NextPath() bool { if it.primaryIt.NextPath() { return true } + if err := it.primaryIt.Err(); err != nil { + it.err = err + return false + } for _, sub := range it.internalIterators { if sub.NextPath() { return true } + if err := sub.Err(); err != nil { + it.err = err + return false + } } return false } diff --git a/graph/iterator/hasa_iterator.go b/graph/iterator/hasa_iterator.go index 037772b..8647dbd 100644 --- a/graph/iterator/hasa_iterator.go +++ b/graph/iterator/hasa_iterator.go @@ -193,11 +193,16 @@ func (it *HasA) NextPath() bool { if it.primaryIt.NextPath() { return true } - result := it.NextContains() - glog.V(4).Infoln("HASA", it.UID(), "NextPath Returns", result, "") + if err := it.primaryIt.Err(); err != nil { + it.err = err + return false + } + + result := it.NextContains() // Sets it.err if there's an error if it.err != nil { return false } + glog.V(4).Infoln("HASA", it.UID(), "NextPath Returns", result, "") return result } diff --git a/graph/iterator/linksto_iterator.go b/graph/iterator/linksto_iterator.go index 16affac..0eebe78 100644 --- a/graph/iterator/linksto_iterator.go +++ b/graph/iterator/linksto_iterator.go @@ -126,6 +126,9 @@ func (it *LinksTo) Contains(val graph.Value) bool { it.result = val return graph.ContainsLogOut(it, val, true) } + if err := it.primaryIt.Err(); err != nil { + it.err = err + } return graph.ContainsLogOut(it, val, false) } @@ -213,7 +216,11 @@ func (it *LinksTo) Close() error { // We won't ever have a new result, but our subiterators might. func (it *LinksTo) NextPath() bool { - return it.primaryIt.NextPath() + ret := it.primaryIt.NextPath() + if !ret { + it.err = it.primaryIt.Err() + } + return ret } // Register the LinksTo. diff --git a/graph/iterator/materialize_iterator.go b/graph/iterator/materialize_iterator.go index cff1c88..e38ac58 100644 --- a/graph/iterator/materialize_iterator.go +++ b/graph/iterator/materialize_iterator.go @@ -230,6 +230,9 @@ func (it *Materialize) Contains(v graph.Value) bool { if !it.hasRun { it.materializeSet() } + if it.err != nil { + return false + } if it.aborted { return it.subIt.Contains(v) } @@ -249,6 +252,9 @@ func (it *Materialize) NextPath() bool { if !it.hasRun { it.materializeSet() } + if it.err != nil { + return false + } if it.aborted { return it.subIt.NextPath() } diff --git a/graph/iterator/not_iterator.go b/graph/iterator/not_iterator.go index 2617a98..a54b4bb 100644 --- a/graph/iterator/not_iterator.go +++ b/graph/iterator/not_iterator.go @@ -113,6 +113,13 @@ func (it *Not) Contains(val graph.Value) bool { return graph.ContainsLogOut(it, val, false) } + if err := it.primaryIt.Err(); err != nil { + it.err = err + + // Explicitly return 'false', since an error occurred. + return false + } + it.result = val return graph.ContainsLogOut(it, val, true) } diff --git a/graph/iterator/optional_iterator.go b/graph/iterator/optional_iterator.go index 84e7154..d645dc7 100644 --- a/graph/iterator/optional_iterator.go +++ b/graph/iterator/optional_iterator.go @@ -38,6 +38,7 @@ type Optional struct { subIt graph.Iterator lastCheck bool result graph.Value + err error } // Creates a new optional iterator. @@ -77,7 +78,7 @@ func (it *Optional) ResultTree() *graph.ResultTree { } func (it *Optional) Err() error { - return it.subIt.Err() + return it.err } func (it *Optional) Result() graph.Value { @@ -89,7 +90,11 @@ func (it *Optional) Result() graph.Value { // optional subbranch. func (it *Optional) NextPath() bool { if it.lastCheck { - return it.subIt.NextPath() + ret := it.subIt.NextPath() + if !ret { + it.err = it.subIt.Err() + } + return ret } return false } @@ -105,6 +110,7 @@ func (it *Optional) SubIterators() []graph.Iterator { func (it *Optional) Contains(val graph.Value) bool { checked := it.subIt.Contains(val) it.lastCheck = checked + it.err = it.subIt.Err() it.result = val return true } diff --git a/graph/iterator/or_iterator.go b/graph/iterator/or_iterator.go index e5b4e09..024ce74 100644 --- a/graph/iterator/or_iterator.go +++ b/graph/iterator/or_iterator.go @@ -174,7 +174,7 @@ func (it *Or) Result() graph.Value { } // Checks a value against the iterators, in order. -func (it *Or) subItsContain(val graph.Value) bool { +func (it *Or) subItsContain(val graph.Value) (bool, error) { var subIsGood = false for i, sub := range it.internalIterators { subIsGood = sub.Contains(val) @@ -182,15 +182,21 @@ func (it *Or) subItsContain(val graph.Value) bool { it.currentIterator = i break } + if err := sub.Err(); err != nil { + return false, err + } } - return subIsGood + return subIsGood, nil } // Check a value against the entire graph.iterator, in order. func (it *Or) Contains(val graph.Value) bool { graph.ContainsLogIn(it, val) - anyGood := it.subItsContain(val) - if !anyGood { + anyGood, err := it.subItsContain(val) + if err != nil { + it.err = err + return false + } else if !anyGood { return graph.ContainsLogOut(it, val, false) } it.result = val @@ -231,7 +237,12 @@ func (it *Or) Size() (int64, bool) { // shortcircuiting, only allow new results from the currently checked graph.iterator func (it *Or) NextPath() bool { if it.currentIterator != -1 { - return it.internalIterators[it.currentIterator].NextPath() + currIt := it.internalIterators[it.currentIterator] + ret := currIt.NextPath() + if !ret { + it.err = currIt.Err() + } + return ret } return false } diff --git a/graph/iterator/value_comparison_iterator.go b/graph/iterator/value_comparison_iterator.go index bffd640..84d949d 100644 --- a/graph/iterator/value_comparison_iterator.go +++ b/graph/iterator/value_comparison_iterator.go @@ -155,6 +155,7 @@ func (it *Comparison) NextPath() bool { for { hasNext := it.subIt.NextPath() if !hasNext { + it.err = it.subIt.Err() return false } if it.doComparison(it.subIt.Result()) { @@ -174,7 +175,11 @@ func (it *Comparison) Contains(val graph.Value) bool { if !it.doComparison(val) { return false } - return it.subIt.Contains(val) + ret := it.subIt.Contains(val) + if !ret { + it.err = it.subIt.Err() + } + return ret } // If we failed the check, then the subiterator should not contribute to the result