Enumerate iterator types
This commit is contained in:
parent
1f67913ed9
commit
cd46452b63
23 changed files with 145 additions and 68 deletions
|
|
@ -101,7 +101,7 @@ func (it *Int64) Check(tsv graph.Value) bool {
|
|||
|
||||
// The type of this iterator is an "all". This is important, as it puts it in
|
||||
// the class of "all iterators.
|
||||
func (it *Int64) Type() string { return "all" }
|
||||
func (it *Int64) Type() graph.Type { return graph.All }
|
||||
|
||||
// There's nothing to optimize about this little iterator.
|
||||
func (it *Int64) Optimize() (graph.Iterator, bool) { return it, false }
|
||||
|
|
|
|||
|
|
@ -246,4 +246,4 @@ func (it *And) Close() {
|
|||
}
|
||||
|
||||
// Register this as an "and" iterator.
|
||||
func (it *And) Type() string { return "and" }
|
||||
func (it *And) Type() graph.Type { return graph.And }
|
||||
|
|
|
|||
|
|
@ -134,7 +134,7 @@ func (_ *And) optimizeReplacement(its []graph.Iterator) graph.Iterator {
|
|||
func optimizeOrder(its []graph.Iterator) []graph.Iterator {
|
||||
var (
|
||||
// bad contains iterators that can't be (efficiently) nexted, such as
|
||||
// "optional" or "not". Separate them out and tack them on at the end.
|
||||
// graph.Optional or graph.Not. Separate them out and tack them on at the end.
|
||||
out, bad []graph.Iterator
|
||||
best graph.Iterator
|
||||
bestCost = int64(1 << 62)
|
||||
|
|
@ -257,25 +257,25 @@ func optimizeSubIterators(its []graph.Iterator) []graph.Iterator {
|
|||
// Check a list of iterators for any Null iterators.
|
||||
func hasAnyNullIterators(its []graph.Iterator) bool {
|
||||
for _, it := range its {
|
||||
if it.Type() == "null" {
|
||||
if it.Type() == graph.Null {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// There are two "not-useful" iterators -- namely "null" which returns
|
||||
// nothing, and "all" which returns everything. Particularly, we want
|
||||
// to see if we're intersecting with a bunch of "all" iterators, and,
|
||||
// There are two "not-useful" iterators -- namely graph.Null which returns
|
||||
// nothing, and graph.All which returns everything. Particularly, we want
|
||||
// to see if we're intersecting with a bunch of graph.All iterators, and,
|
||||
// if we are, then we have only one useful iterator.
|
||||
func hasOneUsefulIterator(its []graph.Iterator) graph.Iterator {
|
||||
usefulCount := 0
|
||||
var usefulIt graph.Iterator
|
||||
for _, it := range its {
|
||||
switch it.Type() {
|
||||
case "null", "all":
|
||||
case graph.Null, graph.All:
|
||||
continue
|
||||
case "optional":
|
||||
case graph.Optional:
|
||||
// Optional is weird -- it's not useful, but we can't optimize
|
||||
// away from it. Therefore, we skip this optimization
|
||||
// if we see one.
|
||||
|
|
|
|||
|
|
@ -21,6 +21,8 @@ import (
|
|||
"reflect"
|
||||
"sort"
|
||||
"testing"
|
||||
|
||||
"github.com/google/cayley/graph"
|
||||
)
|
||||
|
||||
func TestIteratorPromotion(t *testing.T) {
|
||||
|
|
@ -37,7 +39,7 @@ func TestIteratorPromotion(t *testing.T) {
|
|||
if !changed {
|
||||
t.Error("Iterator didn't optimize")
|
||||
}
|
||||
if newIt.Type() != "fixed" {
|
||||
if newIt.Type() != graph.Fixed {
|
||||
t.Error("Expected fixed iterator")
|
||||
}
|
||||
tagsExpected := []string{"a", "b", "c"}
|
||||
|
|
@ -58,7 +60,7 @@ func TestNullIteratorAnd(t *testing.T) {
|
|||
if !changed {
|
||||
t.Error("Didn't change")
|
||||
}
|
||||
if newIt.Type() != "null" {
|
||||
if newIt.Type() != graph.Null {
|
||||
t.Error("Expected null iterator, got ", newIt.Type())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -99,9 +99,7 @@ func (it *Fixed) DebugString(indent int) string {
|
|||
}
|
||||
|
||||
// Register this iterator as a Fixed iterator.
|
||||
func (it *Fixed) Type() string {
|
||||
return "fixed"
|
||||
}
|
||||
func (it *Fixed) Type() graph.Type { return graph.Fixed }
|
||||
|
||||
// Check if the passed value is equal to one of the values stored in the iterator.
|
||||
func (it *Fixed) Check(v graph.Value) bool {
|
||||
|
|
|
|||
|
|
@ -91,7 +91,7 @@ func (it *HasA) Optimize() (graph.Iterator, bool) {
|
|||
newPrimary, changed := it.primaryIt.Optimize()
|
||||
if changed {
|
||||
it.primaryIt = newPrimary
|
||||
if it.primaryIt.Type() == "null" {
|
||||
if it.primaryIt.Type() == graph.Null {
|
||||
return it.primaryIt, true
|
||||
}
|
||||
}
|
||||
|
|
@ -220,4 +220,4 @@ func (it *HasA) Close() {
|
|||
}
|
||||
|
||||
// Register this iterator as a HasA.
|
||||
func (it *HasA) Type() string { return "hasa" }
|
||||
func (it *HasA) Type() graph.Type { return graph.HasA }
|
||||
|
|
|
|||
|
|
@ -174,7 +174,7 @@ func NewNull() *Null {
|
|||
func (it *Null) Clone() graph.Iterator { return NewNull() }
|
||||
|
||||
// Name the null iterator.
|
||||
func (it *Null) Type() string { return "null" }
|
||||
func (it *Null) Type() graph.Type { return graph.Null }
|
||||
|
||||
// A good iterator will close itself when it returns true.
|
||||
// Null has nothing it needs to do.
|
||||
|
|
|
|||
|
|
@ -118,7 +118,7 @@ func (it *LinksTo) Optimize() (graph.Iterator, bool) {
|
|||
newPrimary, changed := it.primaryIt.Optimize()
|
||||
if changed {
|
||||
it.primaryIt = newPrimary
|
||||
if it.primaryIt.Type() == "null" {
|
||||
if it.primaryIt.Type() == graph.Null {
|
||||
it.nextIt.Close()
|
||||
return it.primaryIt, true
|
||||
}
|
||||
|
|
@ -166,7 +166,7 @@ func (it *LinksTo) NextResult() bool {
|
|||
}
|
||||
|
||||
// Register the LinksTo.
|
||||
func (it *LinksTo) Type() string { return "linksto" }
|
||||
func (it *LinksTo) Type() graph.Type { return graph.LinksTo }
|
||||
|
||||
// Return a guess as to how big or costly it is to next the iterator.
|
||||
func (it *LinksTo) Stats() graph.IteratorStats {
|
||||
|
|
|
|||
|
|
@ -104,7 +104,7 @@ func (it *Optional) TagResults(dst map[string]graph.Value) {
|
|||
}
|
||||
|
||||
// Registers the optional iterator.
|
||||
func (it *Optional) Type() string { return "optional" }
|
||||
func (it *Optional) Type() graph.Type { return graph.Optional }
|
||||
|
||||
// Prints the optional and it's subiterator.
|
||||
func (it *Optional) DebugString(indent int) string {
|
||||
|
|
|
|||
|
|
@ -281,4 +281,4 @@ func (it *Or) Stats() graph.IteratorStats {
|
|||
}
|
||||
|
||||
// Register this as an "or" graph.iterator.
|
||||
func (it *Or) Type() string { return "or" }
|
||||
func (it *Or) Type() graph.Type { return graph.Or }
|
||||
|
|
|
|||
|
|
@ -115,18 +115,18 @@ func (qs *queryShape) MakeNode(it graph.Iterator) *Node {
|
|||
}
|
||||
|
||||
switch it.Type() {
|
||||
case "and":
|
||||
case graph.And:
|
||||
for _, sub := range it.SubIterators() {
|
||||
qs.nodeId++
|
||||
newNode := qs.MakeNode(sub)
|
||||
if sub.Type() != "or" {
|
||||
if sub.Type() != graph.Or {
|
||||
qs.StealNode(&n, newNode)
|
||||
} else {
|
||||
qs.AddNode(newNode)
|
||||
qs.AddLink(&Link{n.Id, newNode.Id, 0, 0})
|
||||
}
|
||||
}
|
||||
case "fixed":
|
||||
case graph.Fixed:
|
||||
n.IsFixed = true
|
||||
for {
|
||||
val, more := it.Next()
|
||||
|
|
@ -135,25 +135,25 @@ func (qs *queryShape) MakeNode(it graph.Iterator) *Node {
|
|||
}
|
||||
n.Values = append(n.Values, qs.ts.NameOf(val))
|
||||
}
|
||||
case "hasa":
|
||||
case graph.HasA:
|
||||
hasa := it.(*HasA)
|
||||
qs.PushHasa(n.Id, hasa.dir)
|
||||
qs.nodeId++
|
||||
newNode := qs.MakeNode(hasa.primaryIt)
|
||||
qs.AddNode(newNode)
|
||||
qs.RemoveHasa()
|
||||
case "or":
|
||||
case graph.Or:
|
||||
for _, sub := range it.SubIterators() {
|
||||
qs.nodeId++
|
||||
newNode := qs.MakeNode(sub)
|
||||
if sub.Type() == "or" {
|
||||
if sub.Type() == graph.Or {
|
||||
qs.StealNode(&n, newNode)
|
||||
} else {
|
||||
qs.AddNode(newNode)
|
||||
qs.AddLink(&Link{n.Id, newNode.Id, 0, 0})
|
||||
}
|
||||
}
|
||||
case "linksto":
|
||||
case graph.LinksTo:
|
||||
n.IsLinkNode = true
|
||||
lto := it.(*LinksTo)
|
||||
qs.nodeId++
|
||||
|
|
@ -167,15 +167,15 @@ func (qs *queryShape) MakeNode(it graph.Iterator) *Node {
|
|||
} else {
|
||||
qs.AddLink(&Link{newNode.Id, hasaID, 0, n.Id})
|
||||
}
|
||||
} else if lto.primaryIt.Type() == "fixed" {
|
||||
} else if lto.primaryIt.Type() == graph.Fixed {
|
||||
qs.StealNode(&n, newNode)
|
||||
} else {
|
||||
qs.AddNode(newNode)
|
||||
}
|
||||
case "optional":
|
||||
case graph.Optional:
|
||||
// Unsupported, for the moment
|
||||
fallthrough
|
||||
case "all":
|
||||
case graph.All:
|
||||
}
|
||||
return &n
|
||||
}
|
||||
|
|
|
|||
|
|
@ -162,7 +162,7 @@ func (it *Comparison) TagResults(dst map[string]graph.Value) {
|
|||
}
|
||||
|
||||
// Registers the value-comparison iterator.
|
||||
func (it *Comparison) Type() string { return "value-comparison" }
|
||||
func (it *Comparison) Type() graph.Type { return graph.Comparison }
|
||||
|
||||
// Prints the value-comparison and its subiterator.
|
||||
func (it *Comparison) DebugString(indent int) string {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue