Don't indirect map values

We already have reference behaviour, so this is not necessary.

This change highlighted fairly baroque architecture in mql that deserves
some attention; the use of channels is somewhat confusing.

Also rename LastResult to Result.
This commit is contained in:
kortschak 2014-07-02 12:08:49 +09:30
parent b89d4f392c
commit a1453da84e
15 changed files with 59 additions and 57 deletions

View file

@ -37,9 +37,10 @@ type Iterator interface {
CopyTagsFrom(Iterator) CopyTagsFrom(Iterator)
// Fills a tag-to-result-value map. // Fills a tag-to-result-value map.
TagResults(*map[string]TSVal) TagResults(map[string]TSVal)
// Returns the current result. // Returns the current result.
LastResult() TSVal Result() TSVal
// DEPRECATED -- Fills a ResultTree struct with Result(). // DEPRECATED -- Fills a ResultTree struct with Result().
ResultTree() *ResultTree ResultTree() *ResultTree
@ -78,15 +79,16 @@ type Iterator interface {
// Create a new iterator just like this one // Create a new iterator just like this one
Clone() Iterator Clone() Iterator
// These methods relate to choosing the right iterator, or optimizing an // These methods relate to choosing the right iterator, or optimizing an
// iterator tree // iterator tree
// //
// GetStats() returns the relative costs of calling the iteration methods for // Stats() returns the relative costs of calling the iteration methods for
// this iterator, as well as the size. Roughly, it will take NextCost * Size // this iterator, as well as the size. Roughly, it will take NextCost * Size
// "cost units" to get everything out of the iterator. This is a wibbly-wobbly // "cost units" to get everything out of the iterator. This is a wibbly-wobbly
// thing, and not exact, but a useful heuristic. // thing, and not exact, but a useful heuristic.
Stats() IteratorStats Stats() IteratorStats
// Helpful accessor for the number of things in the iterator. The first return // Helpful accessor for the number of things in the iterator. The first return
// value is the size, and the second return value is whether that number is exact, // value is the size, and the second return value is whether that number is exact,
// or a conservative estimate. // or a conservative estimate.

View file

@ -73,19 +73,19 @@ func (it *And) SubIterators() []graph.Iterator {
// Overrides Base TagResults, as it needs to add it's own results and // Overrides Base TagResults, as it needs to add it's own results and
// recurse down it's subiterators. // recurse down it's subiterators.
func (it *And) TagResults(out *map[string]graph.TSVal) { func (it *And) TagResults(dst map[string]graph.TSVal) {
it.Base.TagResults(out) it.Base.TagResults(dst)
if it.primaryIt != nil { if it.primaryIt != nil {
it.primaryIt.TagResults(out) it.primaryIt.TagResults(dst)
} }
for _, sub := range it.internalIterators { for _, sub := range it.internalIterators {
sub.TagResults(out) sub.TagResults(dst)
} }
} }
// DEPRECATED Returns the ResultTree for this iterator, recurses to it's subiterators. // DEPRECATED Returns the ResultTree for this iterator, recurses to it's subiterators.
func (it *And) ResultTree() *graph.ResultTree { func (it *And) ResultTree() *graph.ResultTree {
tree := graph.NewResultTree(it.LastResult()) tree := graph.NewResultTree(it.Result())
tree.AddSubtree(it.primaryIt.ResultTree()) tree.AddSubtree(it.primaryIt.ResultTree())
for _, sub := range it.internalIterators { for _, sub := range it.internalIterators {
tree.AddSubtree(sub.ResultTree()) tree.AddSubtree(sub.ResultTree())

View file

@ -44,7 +44,7 @@ func TestTag(t *testing.T) {
t.Errorf("Unexpected value") t.Errorf("Unexpected value")
} }
tags := make(map[string]graph.TSVal) tags := make(map[string]graph.TSVal)
and.TagResults(&tags) and.TagResults(tags)
if tags["bar"] != 234 { if tags["bar"] != 234 {
t.Errorf("no bar tag") t.Errorf("no bar tag")
} }

View file

@ -99,14 +99,14 @@ func (it *HasA) Optimize() (graph.Iterator, bool) {
} }
// Pass the TagResults down the chain. // Pass the TagResults down the chain.
func (it *HasA) TagResults(out *map[string]graph.TSVal) { func (it *HasA) TagResults(dst map[string]graph.TSVal) {
it.Base.TagResults(out) it.Base.TagResults(dst)
it.primaryIt.TagResults(out) it.primaryIt.TagResults(dst)
} }
// DEPRECATED Return results in a ResultTree. // DEPRECATED Return results in a ResultTree.
func (it *HasA) ResultTree() *graph.ResultTree { func (it *HasA) ResultTree() *graph.ResultTree {
tree := graph.NewResultTree(it.LastResult()) tree := graph.NewResultTree(it.Result())
tree.AddSubtree(it.primaryIt.ResultTree()) tree.AddSubtree(it.primaryIt.ResultTree())
return tree return tree
} }

View file

@ -109,7 +109,7 @@ func (it *Base) Stats() graph.IteratorStats {
// DEPRECATED // DEPRECATED
func (it *Base) ResultTree() *graph.ResultTree { func (it *Base) ResultTree() *graph.ResultTree {
tree := graph.NewResultTree(it.LastResult()) tree := graph.NewResultTree(it.Result())
return tree return tree
} }
@ -123,7 +123,7 @@ func (it *Base) NextResult() bool {
} }
// Returns the last result of an iterator. // Returns the last result of an iterator.
func (it *Base) LastResult() graph.TSVal { func (it *Base) Result() graph.TSVal {
return it.Last return it.Last
} }
@ -142,13 +142,13 @@ func (it *Base) CanNext() bool { return it.canNext }
// Fill the map based on the tags assigned to this iterator. Default // Fill the map based on the tags assigned to this iterator. Default
// functionality works well for most iterators. // functionality works well for most iterators.
func (it *Base) TagResults(out_map *map[string]graph.TSVal) { func (it *Base) TagResults(dst map[string]graph.TSVal) {
for _, tag := range it.Tags() { for _, tag := range it.Tags() {
(*out_map)[tag] = it.LastResult() dst[tag] = it.Result()
} }
for tag, value := range it.FixedTags() { for tag, value := range it.FixedTags() {
(*out_map)[tag] = value dst[tag] = value
} }
} }

View file

@ -77,14 +77,14 @@ func (it *LinksTo) Clone() graph.Iterator {
func (it *LinksTo) Direction() graph.Direction { return it.dir } func (it *LinksTo) Direction() graph.Direction { return it.dir }
// Tag these results, and our subiterator's results. // Tag these results, and our subiterator's results.
func (it *LinksTo) TagResults(out *map[string]graph.TSVal) { func (it *LinksTo) TagResults(dst map[string]graph.TSVal) {
it.Base.TagResults(out) it.Base.TagResults(dst)
it.primaryIt.TagResults(out) it.primaryIt.TagResults(dst)
} }
// DEPRECATED // DEPRECATED
func (it *LinksTo) ResultTree() *graph.ResultTree { func (it *LinksTo) ResultTree() *graph.ResultTree {
tree := graph.NewResultTree(it.LastResult()) tree := graph.NewResultTree(it.Result())
tree.AddSubtree(it.primaryIt.ResultTree()) tree.AddSubtree(it.primaryIt.ResultTree())
return tree return tree
} }

View file

@ -96,11 +96,11 @@ func (it *Optional) Check(val graph.TSVal) bool {
// If we failed the check, then the subiterator should not contribute to the result // If we failed the check, then the subiterator should not contribute to the result
// set. Otherwise, go ahead and tag it. // set. Otherwise, go ahead and tag it.
func (it *Optional) TagResults(out *map[string]graph.TSVal) { func (it *Optional) TagResults(dst map[string]graph.TSVal) {
if it.lastCheck == false { if it.lastCheck == false {
return return
} }
it.subIt.TagResults(out) it.subIt.TagResults(dst)
} }
// Registers the optional iterator. // Registers the optional iterator.

View file

@ -83,14 +83,14 @@ func (it *Or) SubIterators() []graph.Iterator {
// Overrides BaseIterator TagResults, as it needs to add it's own results and // Overrides BaseIterator TagResults, as it needs to add it's own results and
// recurse down it's subiterators. // recurse down it's subiterators.
func (it *Or) TagResults(out *map[string]graph.TSVal) { func (it *Or) TagResults(dst map[string]graph.TSVal) {
it.Base.TagResults(out) it.Base.TagResults(dst)
it.internalIterators[it.currentIterator].TagResults(out) it.internalIterators[it.currentIterator].TagResults(dst)
} }
// DEPRECATED Returns the ResultTree for this graph.iterator, recurses to it's subiterators. // DEPRECATED Returns the ResultTree for this graph.iterator, recurses to it's subiterators.
func (it *Or) ResultTree() *graph.ResultTree { func (it *Or) ResultTree() *graph.ResultTree {
tree := graph.NewResultTree(it.LastResult()) tree := graph.NewResultTree(it.Result())
for _, sub := range it.internalIterators { for _, sub := range it.internalIterators {
tree.AddSubtree(sub.ResultTree()) tree.AddSubtree(sub.ResultTree())
} }

View file

@ -139,11 +139,11 @@ func (it *Comparison) NextResult() bool {
if !hasNext { if !hasNext {
return false return false
} }
if it.doComparison(it.subIt.LastResult()) { if it.doComparison(it.subIt.Result()) {
return true return true
} }
} }
it.Last = it.subIt.LastResult() it.Last = it.subIt.Result()
return true return true
} }
@ -156,9 +156,9 @@ func (it *Comparison) Check(val graph.TSVal) bool {
// If we failed the check, then the subiterator should not contribute to the result // If we failed the check, then the subiterator should not contribute to the result
// set. Otherwise, go ahead and tag it. // set. Otherwise, go ahead and tag it.
func (it *Comparison) TagResults(out *map[string]graph.TSVal) { func (it *Comparison) TagResults(dst map[string]graph.TSVal) {
it.Base.TagResults(out) it.Base.TagResults(dst)
it.subIt.TagResults(out) it.subIt.TagResults(dst)
} }
// Registers the value-comparison iterator. // Registers the value-comparison iterator.

View file

@ -421,9 +421,9 @@ func TestOptimize(t *testing.T) {
oldIt.Next() oldIt.Next()
newIt.Next() newIt.Next()
oldResults := make(map[string]graph.TSVal) oldResults := make(map[string]graph.TSVal)
oldIt.TagResults(&oldResults) oldIt.TagResults(oldResults)
newResults := make(map[string]graph.TSVal) newResults := make(map[string]graph.TSVal)
oldIt.TagResults(&newResults) oldIt.TagResults(newResults)
So(newResults, ShouldResemble, oldResults) So(newResults, ShouldResemble, oldResults)
}) })

View file

@ -65,12 +65,12 @@ func TestIteratorsAndNextResultOrderA(t *testing.T) {
expected[0] = "B" expected[0] = "B"
expected[1] = "D" expected[1] = "D"
actualOut := make([]string, 2) actualOut := make([]string, 2)
actualOut[0] = ts.NameOf(all.LastResult()) actualOut[0] = ts.NameOf(all.Result())
nresultOk := outerAnd.NextResult() nresultOk := outerAnd.NextResult()
if !nresultOk { if !nresultOk {
t.Error("Expected two results got one") t.Error("Expected two results got one")
} }
actualOut[1] = ts.NameOf(all.LastResult()) actualOut[1] = ts.NameOf(all.Result())
nresultOk = outerAnd.NextResult() nresultOk = outerAnd.NextResult()
if nresultOk { if nresultOk {
t.Error("Expected two results got three") t.Error("Expected two results got three")

View file

@ -96,7 +96,7 @@ func TestTreeConstraintTagParse(t *testing.T) {
t.Error("Got no results") t.Error("Got no results")
} }
tags := make(map[string]graph.TSVal) tags := make(map[string]graph.TSVal)
it.TagResults(&tags) it.TagResults(tags)
if ts.NameOf(tags["$a"]) != "food" { if ts.NameOf(tags["$a"]) != "food" {
t.Errorf("Got %s, expected food", ts.NameOf(tags["$a"])) t.Errorf("Got %s, expected food", ts.NameOf(tags["$a"]))
} }

View file

@ -82,7 +82,7 @@ func (s *Session) ExecInput(input string, out chan interface{}, limit int) {
break break
} }
tags := make(map[string]graph.TSVal) tags := make(map[string]graph.TSVal)
it.TagResults(&tags) it.TagResults(tags)
out <- &tags out <- &tags
nResults++ nResults++
if nResults > limit && limit != -1 { if nResults > limit && limit != -1 {
@ -90,7 +90,7 @@ func (s *Session) ExecInput(input string, out chan interface{}, limit int) {
} }
for it.NextResult() == true { for it.NextResult() == true {
tags := make(map[string]graph.TSVal) tags := make(map[string]graph.TSVal)
it.TagResults(&tags) it.TagResults(tags)
out <- &tags out <- &tags
nResults++ nResults++
if nResults > limit && limit != -1 { if nResults > limit && limit != -1 {
@ -103,10 +103,10 @@ func (s *Session) ExecInput(input string, out chan interface{}, limit int) {
func (s *Session) ToText(result interface{}) string { func (s *Session) ToText(result interface{}) string {
out := fmt.Sprintln("****") out := fmt.Sprintln("****")
tags := result.(*map[string]graph.TSVal) tags := result.(map[string]graph.TSVal)
tagKeys := make([]string, len(*tags)) tagKeys := make([]string, len(tags))
i := 0 i := 0
for k, _ := range *tags { for k := range tags {
tagKeys[i] = k tagKeys[i] = k
i++ i++
} }
@ -115,7 +115,7 @@ func (s *Session) ToText(result interface{}) string {
if k == "$_" { if k == "$_" {
continue continue
} }
out += fmt.Sprintf("%s : %s\n", k, s.ts.NameOf((*tags)[k])) out += fmt.Sprintf("%s : %s\n", k, s.ts.NameOf(tags[k]))
} }
return out return out
} }

View file

@ -156,7 +156,7 @@ func runIteratorToArray(it graph.Iterator, ses *Session, limit int) []map[string
break break
} }
tags := make(map[string]graph.TSVal) tags := make(map[string]graph.TSVal)
it.TagResults(&tags) it.TagResults(tags)
output = append(output, tagsToValueMap(tags, ses)) output = append(output, tagsToValueMap(tags, ses))
count++ count++
if limit >= 0 && count >= limit { if limit >= 0 && count >= limit {
@ -167,7 +167,7 @@ func runIteratorToArray(it graph.Iterator, ses *Session, limit int) []map[string
return nil return nil
} }
tags := make(map[string]graph.TSVal) tags := make(map[string]graph.TSVal)
it.TagResults(&tags) it.TagResults(tags)
output = append(output, tagsToValueMap(tags, ses)) output = append(output, tagsToValueMap(tags, ses))
count++ count++
if limit >= 0 && count >= limit { if limit >= 0 && count >= limit {
@ -213,7 +213,7 @@ func runIteratorWithCallback(it graph.Iterator, ses *Session, callback otto.Valu
break break
} }
tags := make(map[string]graph.TSVal) tags := make(map[string]graph.TSVal)
it.TagResults(&tags) it.TagResults(tags)
val, _ := this.Otto.ToValue(tagsToValueMap(tags, ses)) val, _ := this.Otto.ToValue(tagsToValueMap(tags, ses))
val, _ = callback.Call(this.This, val) val, _ = callback.Call(this.This, val)
count++ count++
@ -225,7 +225,7 @@ func runIteratorWithCallback(it graph.Iterator, ses *Session, callback otto.Valu
return return
} }
tags := make(map[string]graph.TSVal) tags := make(map[string]graph.TSVal)
it.TagResults(&tags) it.TagResults(tags)
val, _ := this.Otto.ToValue(tagsToValueMap(tags, ses)) val, _ := this.Otto.ToValue(tagsToValueMap(tags, ses))
val, _ = callback.Call(this.This, val) val, _ = callback.Call(this.This, val)
count++ count++
@ -254,7 +254,7 @@ func runIteratorOnSession(it graph.Iterator, ses *Session) {
break break
} }
tags := make(map[string]graph.TSVal) tags := make(map[string]graph.TSVal)
it.TagResults(&tags) it.TagResults(tags)
cont := ses.SendResult(&GremlinResult{metaresult: false, err: "", val: nil, actualResults: &tags}) cont := ses.SendResult(&GremlinResult{metaresult: false, err: "", val: nil, actualResults: &tags})
if !cont { if !cont {
break break
@ -264,7 +264,7 @@ func runIteratorOnSession(it graph.Iterator, ses *Session) {
return return
} }
tags := make(map[string]graph.TSVal) tags := make(map[string]graph.TSVal)
it.TagResults(&tags) it.TagResults(tags)
cont := ses.SendResult(&GremlinResult{metaresult: false, err: "", val: nil, actualResults: &tags}) cont := ses.SendResult(&GremlinResult{metaresult: false, err: "", val: nil, actualResults: &tags})
if !cont { if !cont {
break break

View file

@ -93,18 +93,18 @@ func (s *Session) ExecInput(input string, c chan interface{}, limit int) {
break break
} }
tags := make(map[string]graph.TSVal) tags := make(map[string]graph.TSVal)
it.TagResults(&tags) it.TagResults(tags)
c <- &tags c <- tags
for it.NextResult() == true { for it.NextResult() == true {
tags := make(map[string]graph.TSVal) tags := make(map[string]graph.TSVal)
it.TagResults(&tags) it.TagResults(tags)
c <- &tags c <- tags
} }
} }
} }
func (s *Session) ToText(result interface{}) string { func (s *Session) ToText(result interface{}) string {
tags := *(result.(*map[string]graph.TSVal)) tags := result.(map[string]graph.TSVal)
out := fmt.Sprintln("****") out := fmt.Sprintln("****")
tagKeys := make([]string, len(tags)) tagKeys := make([]string, len(tags))
s.currentQuery.treeifyResult(tags) s.currentQuery.treeifyResult(tags)
@ -127,7 +127,7 @@ func (s *Session) ToText(result interface{}) string {
} }
func (s *Session) BuildJson(result interface{}) { func (s *Session) BuildJson(result interface{}) {
s.currentQuery.treeifyResult(*(result.(*map[string]graph.TSVal))) s.currentQuery.treeifyResult(result.(map[string]graph.TSVal))
} }
func (s *Session) GetJson() (interface{}, error) { func (s *Session) GetJson() (interface{}, error) {