Move tag handling out into graph.Tagger
This commit is contained in:
parent
0238332ca3
commit
1604dca737
28 changed files with 315 additions and 159 deletions
|
|
@ -24,18 +24,46 @@ import (
|
||||||
"github.com/barakmich/glog"
|
"github.com/barakmich/glog"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type Tagger struct {
|
||||||
|
tags []string
|
||||||
|
fixedTags map[string]Value
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adds a tag to the iterator.
|
||||||
|
func (t *Tagger) Add(tag string) {
|
||||||
|
t.tags = append(t.tags, tag)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Tagger) AddFixed(tag string, value Value) {
|
||||||
|
if t.fixedTags == nil {
|
||||||
|
t.fixedTags = make(map[string]Value)
|
||||||
|
}
|
||||||
|
t.fixedTags[tag] = value
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the tags. The returned value must not be mutated.
|
||||||
|
func (t *Tagger) Tags() []string {
|
||||||
|
return t.tags
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the fixed tags. The returned value must not be mutated.
|
||||||
|
func (t *Tagger) Fixed() map[string]Value {
|
||||||
|
return t.fixedTags
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Tagger) CopyFrom(src Iterator) {
|
||||||
|
for _, tag := range src.Tagger().Tags() {
|
||||||
|
t.Add(tag)
|
||||||
|
}
|
||||||
|
|
||||||
|
for k, v := range src.Tagger().Fixed() {
|
||||||
|
t.AddFixed(k, v)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
type Iterator interface {
|
type Iterator interface {
|
||||||
// Tags are the way we handle results. By adding a tag to an iterator, we can
|
Tagger() *Tagger
|
||||||
// "name" it, in a sense, and at each step of iteration, get a named result.
|
|
||||||
// TagResults() is therefore the handy way of walking an iterator tree and
|
|
||||||
// getting the named results.
|
|
||||||
//
|
|
||||||
// Tag Accessors.
|
|
||||||
AddTag(string)
|
|
||||||
Tags() []string
|
|
||||||
AddFixedTag(string, Value)
|
|
||||||
FixedTags() map[string]Value
|
|
||||||
CopyTagsFrom(Iterator)
|
|
||||||
|
|
||||||
// Fills a tag-to-result-value map.
|
// Fills a tag-to-result-value map.
|
||||||
TagResults(map[string]Value)
|
TagResults(map[string]Value)
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,7 @@ import (
|
||||||
// An All iterator across a range of int64 values, from `max` to `min`.
|
// An All iterator across a range of int64 values, from `max` to `min`.
|
||||||
type Int64 struct {
|
type Int64 struct {
|
||||||
Base
|
Base
|
||||||
|
tags graph.Tagger
|
||||||
max, min int64
|
max, min int64
|
||||||
at int64
|
at int64
|
||||||
}
|
}
|
||||||
|
|
@ -55,13 +56,28 @@ func (it *Int64) Close() {}
|
||||||
|
|
||||||
func (it *Int64) Clone() graph.Iterator {
|
func (it *Int64) Clone() graph.Iterator {
|
||||||
out := NewInt64(it.min, it.max)
|
out := NewInt64(it.min, it.max)
|
||||||
out.CopyTagsFrom(it)
|
out.tags.CopyFrom(it)
|
||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (it *Int64) Tagger() *graph.Tagger {
|
||||||
|
return &it.tags
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fill the map based on the tags assigned to this iterator.
|
||||||
|
func (it *Int64) TagResults(dst map[string]graph.Value) {
|
||||||
|
for _, tag := range it.tags.Tags() {
|
||||||
|
dst[tag] = it.Result()
|
||||||
|
}
|
||||||
|
|
||||||
|
for tag, value := range it.tags.Fixed() {
|
||||||
|
dst[tag] = value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Prints the All iterator as just an "all".
|
// Prints the All iterator as just an "all".
|
||||||
func (it *Int64) DebugString(indent int) string {
|
func (it *Int64) DebugString(indent int) string {
|
||||||
return fmt.Sprintf("%s(%s tags: %v)", strings.Repeat(" ", indent), it.Type(), it.Tags())
|
return fmt.Sprintf("%s(%s tags: %v)", strings.Repeat(" ", indent), it.Type(), it.tags.Tags())
|
||||||
}
|
}
|
||||||
|
|
||||||
// Next() on an Int64 all iterator is a simple incrementing counter.
|
// Next() on an Int64 all iterator is a simple incrementing counter.
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@ import (
|
||||||
// be Next()ed if next is called.
|
// be Next()ed if next is called.
|
||||||
type And struct {
|
type And struct {
|
||||||
Base
|
Base
|
||||||
|
tags graph.Tagger
|
||||||
internalIterators []graph.Iterator
|
internalIterators []graph.Iterator
|
||||||
itCount int
|
itCount int
|
||||||
primaryIt graph.Iterator
|
primaryIt graph.Iterator
|
||||||
|
|
@ -50,10 +51,33 @@ func (it *And) Reset() {
|
||||||
it.checkList = nil
|
it.checkList = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (it *And) Tagger() *graph.Tagger {
|
||||||
|
return &it.tags
|
||||||
|
}
|
||||||
|
|
||||||
|
// Overrides Base TagResults, as it needs to add it's own results and
|
||||||
|
// recurse down it's subiterators.
|
||||||
|
func (it *And) TagResults(dst map[string]graph.Value) {
|
||||||
|
for _, tag := range it.tags.Tags() {
|
||||||
|
dst[tag] = it.Result()
|
||||||
|
}
|
||||||
|
|
||||||
|
for tag, value := range it.tags.Fixed() {
|
||||||
|
dst[tag] = value
|
||||||
|
}
|
||||||
|
|
||||||
|
if it.primaryIt != nil {
|
||||||
|
it.primaryIt.TagResults(dst)
|
||||||
|
}
|
||||||
|
for _, sub := range it.internalIterators {
|
||||||
|
sub.TagResults(dst)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (it *And) Clone() graph.Iterator {
|
func (it *And) Clone() graph.Iterator {
|
||||||
and := NewAnd()
|
and := NewAnd()
|
||||||
and.AddSubIterator(it.primaryIt.Clone())
|
and.AddSubIterator(it.primaryIt.Clone())
|
||||||
and.CopyTagsFrom(it)
|
and.tags.CopyFrom(it)
|
||||||
for _, sub := range it.internalIterators {
|
for _, sub := range it.internalIterators {
|
||||||
and.AddSubIterator(sub.Clone())
|
and.AddSubIterator(sub.Clone())
|
||||||
}
|
}
|
||||||
|
|
@ -71,18 +95,6 @@ func (it *And) SubIterators() []graph.Iterator {
|
||||||
return iters
|
return iters
|
||||||
}
|
}
|
||||||
|
|
||||||
// Overrides Base TagResults, as it needs to add it's own results and
|
|
||||||
// recurse down it's subiterators.
|
|
||||||
func (it *And) TagResults(dst map[string]graph.Value) {
|
|
||||||
it.Base.TagResults(dst)
|
|
||||||
if it.primaryIt != nil {
|
|
||||||
it.primaryIt.TagResults(dst)
|
|
||||||
}
|
|
||||||
for _, sub := range it.internalIterators {
|
|
||||||
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.Result())
|
tree := graph.NewResultTree(it.Result())
|
||||||
|
|
@ -101,7 +113,7 @@ func (it *And) DebugString(indent int) string {
|
||||||
total += fmt.Sprintf("%d:\n%s\n", i, sub.DebugString(indent+4))
|
total += fmt.Sprintf("%d:\n%s\n", i, sub.DebugString(indent+4))
|
||||||
}
|
}
|
||||||
var tags string
|
var tags string
|
||||||
for _, k := range it.Tags() {
|
for _, k := range it.tags.Tags() {
|
||||||
tags += fmt.Sprintf("%s;", k)
|
tags += fmt.Sprintf("%s;", k)
|
||||||
}
|
}
|
||||||
spaces := strings.Repeat(" ", indent+2)
|
spaces := strings.Repeat(" ", indent+2)
|
||||||
|
|
|
||||||
|
|
@ -82,7 +82,7 @@ func (it *And) Optimize() (graph.Iterator, bool) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Move the tags hanging on us (like any good replacement).
|
// Move the tags hanging on us (like any good replacement).
|
||||||
newAnd.CopyTagsFrom(it)
|
newAnd.tags.CopyFrom(it)
|
||||||
|
|
||||||
newAnd.optimizeCheck()
|
newAnd.optimizeCheck()
|
||||||
|
|
||||||
|
|
@ -213,11 +213,11 @@ func (it *And) optimizeCheck() {
|
||||||
func (it *And) getSubTags() map[string]struct{} {
|
func (it *And) getSubTags() map[string]struct{} {
|
||||||
tags := make(map[string]struct{})
|
tags := make(map[string]struct{})
|
||||||
for _, sub := range it.SubIterators() {
|
for _, sub := range it.SubIterators() {
|
||||||
for _, tag := range sub.Tags() {
|
for _, tag := range sub.Tagger().Tags() {
|
||||||
tags[tag] = struct{}{}
|
tags[tag] = struct{}{}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, tag := range it.Tags() {
|
for _, tag := range it.tags.Tags() {
|
||||||
tags[tag] = struct{}{}
|
tags[tag] = struct{}{}
|
||||||
}
|
}
|
||||||
return tags
|
return tags
|
||||||
|
|
@ -227,13 +227,14 @@ func (it *And) getSubTags() map[string]struct{} {
|
||||||
// src itself, and moves them to dst.
|
// src itself, and moves them to dst.
|
||||||
func moveTagsTo(dst graph.Iterator, src *And) {
|
func moveTagsTo(dst graph.Iterator, src *And) {
|
||||||
tags := src.getSubTags()
|
tags := src.getSubTags()
|
||||||
for _, tag := range dst.Tags() {
|
for _, tag := range dst.Tagger().Tags() {
|
||||||
if _, ok := tags[tag]; ok {
|
if _, ok := tags[tag]; ok {
|
||||||
delete(tags, tag)
|
delete(tags, tag)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
dt := dst.Tagger()
|
||||||
for k := range tags {
|
for k := range tags {
|
||||||
dst.AddTag(k)
|
dt.Add(k)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -32,9 +32,9 @@ func TestIteratorPromotion(t *testing.T) {
|
||||||
a := NewAnd()
|
a := NewAnd()
|
||||||
a.AddSubIterator(all)
|
a.AddSubIterator(all)
|
||||||
a.AddSubIterator(fixed)
|
a.AddSubIterator(fixed)
|
||||||
all.AddTag("a")
|
all.Tagger().Add("a")
|
||||||
fixed.AddTag("b")
|
fixed.Tagger().Add("b")
|
||||||
a.AddTag("c")
|
a.Tagger().Add("c")
|
||||||
newIt, changed := a.Optimize()
|
newIt, changed := a.Optimize()
|
||||||
if !changed {
|
if !changed {
|
||||||
t.Error("Iterator didn't optimize")
|
t.Error("Iterator didn't optimize")
|
||||||
|
|
@ -43,7 +43,7 @@ func TestIteratorPromotion(t *testing.T) {
|
||||||
t.Error("Expected fixed iterator")
|
t.Error("Expected fixed iterator")
|
||||||
}
|
}
|
||||||
tagsExpected := []string{"a", "b", "c"}
|
tagsExpected := []string{"a", "b", "c"}
|
||||||
tags := newIt.Tags()
|
tags := newIt.Tagger().Tags()
|
||||||
sort.Strings(tags)
|
sort.Strings(tags)
|
||||||
if !reflect.DeepEqual(tags, tagsExpected) {
|
if !reflect.DeepEqual(tags, tagsExpected) {
|
||||||
t.Fatal("Tags don't match")
|
t.Fatal("Tags don't match")
|
||||||
|
|
@ -67,9 +67,9 @@ func TestNullIteratorAnd(t *testing.T) {
|
||||||
|
|
||||||
func TestReorderWithTag(t *testing.T) {
|
func TestReorderWithTag(t *testing.T) {
|
||||||
all := NewInt64(100, 300)
|
all := NewInt64(100, 300)
|
||||||
all.AddTag("good")
|
all.Tagger().Add("good")
|
||||||
all2 := NewInt64(1, 30000)
|
all2 := NewInt64(1, 30000)
|
||||||
all2.AddTag("slow")
|
all2.Tagger().Add("slow")
|
||||||
a := NewAnd()
|
a := NewAnd()
|
||||||
// Make all2 the default iterator
|
// Make all2 the default iterator
|
||||||
a.AddSubIterator(all2)
|
a.AddSubIterator(all2)
|
||||||
|
|
@ -82,7 +82,7 @@ func TestReorderWithTag(t *testing.T) {
|
||||||
expectedTags := []string{"good", "slow"}
|
expectedTags := []string{"good", "slow"}
|
||||||
tagsOut := make([]string, 0)
|
tagsOut := make([]string, 0)
|
||||||
for _, sub := range newIt.SubIterators() {
|
for _, sub := range newIt.SubIterators() {
|
||||||
for _, x := range sub.Tags() {
|
for _, x := range sub.Tagger().Tags() {
|
||||||
tagsOut = append(tagsOut, x)
|
tagsOut = append(tagsOut, x)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -93,9 +93,9 @@ func TestReorderWithTag(t *testing.T) {
|
||||||
|
|
||||||
func TestAndStatistics(t *testing.T) {
|
func TestAndStatistics(t *testing.T) {
|
||||||
all := NewInt64(100, 300)
|
all := NewInt64(100, 300)
|
||||||
all.AddTag("good")
|
all.Tagger().Add("good")
|
||||||
all2 := NewInt64(1, 30000)
|
all2 := NewInt64(1, 30000)
|
||||||
all2.AddTag("slow")
|
all2.Tagger().Add("slow")
|
||||||
a := NewAnd()
|
a := NewAnd()
|
||||||
// Make all2 the default iterator
|
// Make all2 the default iterator
|
||||||
a.AddSubIterator(all2)
|
a.AddSubIterator(all2)
|
||||||
|
|
|
||||||
|
|
@ -24,11 +24,11 @@ import (
|
||||||
func TestTag(t *testing.T) {
|
func TestTag(t *testing.T) {
|
||||||
fix1 := newFixed()
|
fix1 := newFixed()
|
||||||
fix1.Add(234)
|
fix1.Add(234)
|
||||||
fix1.AddTag("foo")
|
fix1.Tagger().Add("foo")
|
||||||
and := NewAnd()
|
and := NewAnd()
|
||||||
and.AddSubIterator(fix1)
|
and.AddSubIterator(fix1)
|
||||||
and.AddTag("bar")
|
and.Tagger().Add("bar")
|
||||||
out := fix1.Tags()
|
out := fix1.Tagger().Tags()
|
||||||
if len(out) != 1 {
|
if len(out) != 1 {
|
||||||
t.Errorf("Expected length 1, got %d", len(out))
|
t.Errorf("Expected length 1, got %d", len(out))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@ import (
|
||||||
// an equality function.
|
// an equality function.
|
||||||
type Fixed struct {
|
type Fixed struct {
|
||||||
Base
|
Base
|
||||||
|
tags graph.Tagger
|
||||||
values []graph.Value
|
values []graph.Value
|
||||||
lastIndex int
|
lastIndex int
|
||||||
cmp Equality
|
cmp Equality
|
||||||
|
|
@ -68,12 +69,26 @@ func (it *Fixed) Reset() {
|
||||||
|
|
||||||
func (it *Fixed) Close() {}
|
func (it *Fixed) Close() {}
|
||||||
|
|
||||||
|
func (it *Fixed) Tagger() *graph.Tagger {
|
||||||
|
return &it.tags
|
||||||
|
}
|
||||||
|
|
||||||
|
func (it *Fixed) TagResults(dst map[string]graph.Value) {
|
||||||
|
for _, tag := range it.tags.Tags() {
|
||||||
|
dst[tag] = it.Result()
|
||||||
|
}
|
||||||
|
|
||||||
|
for tag, value := range it.tags.Fixed() {
|
||||||
|
dst[tag] = value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (it *Fixed) Clone() graph.Iterator {
|
func (it *Fixed) Clone() graph.Iterator {
|
||||||
out := NewFixedIteratorWithCompare(it.cmp)
|
out := NewFixedIteratorWithCompare(it.cmp)
|
||||||
for _, val := range it.values {
|
for _, val := range it.values {
|
||||||
out.Add(val)
|
out.Add(val)
|
||||||
}
|
}
|
||||||
out.CopyTagsFrom(it)
|
out.tags.CopyFrom(it)
|
||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -92,7 +107,7 @@ func (it *Fixed) DebugString(indent int) string {
|
||||||
return fmt.Sprintf("%s(%s tags: %s Size: %d id0: %d)",
|
return fmt.Sprintf("%s(%s tags: %s Size: %d id0: %d)",
|
||||||
strings.Repeat(" ", indent),
|
strings.Repeat(" ", indent),
|
||||||
it.Type(),
|
it.Type(),
|
||||||
it.FixedTags(),
|
it.tags.Fixed(),
|
||||||
len(it.values),
|
len(it.values),
|
||||||
value,
|
value,
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,7 @@ import (
|
||||||
// and a temporary holder for the iterator generated on Check().
|
// and a temporary holder for the iterator generated on Check().
|
||||||
type HasA struct {
|
type HasA struct {
|
||||||
Base
|
Base
|
||||||
|
tags graph.Tagger
|
||||||
ts graph.TripleStore
|
ts graph.TripleStore
|
||||||
primaryIt graph.Iterator
|
primaryIt graph.Iterator
|
||||||
dir graph.Direction
|
dir graph.Direction
|
||||||
|
|
@ -76,9 +77,13 @@ func (it *HasA) Reset() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (it *HasA) Tagger() *graph.Tagger {
|
||||||
|
return &it.tags
|
||||||
|
}
|
||||||
|
|
||||||
func (it *HasA) Clone() graph.Iterator {
|
func (it *HasA) Clone() graph.Iterator {
|
||||||
out := NewHasA(it.ts, it.primaryIt.Clone(), it.dir)
|
out := NewHasA(it.ts, it.primaryIt.Clone(), it.dir)
|
||||||
out.CopyTagsFrom(it)
|
out.tags.CopyFrom(it)
|
||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -100,7 +105,14 @@ func (it *HasA) Optimize() (graph.Iterator, bool) {
|
||||||
|
|
||||||
// Pass the TagResults down the chain.
|
// Pass the TagResults down the chain.
|
||||||
func (it *HasA) TagResults(dst map[string]graph.Value) {
|
func (it *HasA) TagResults(dst map[string]graph.Value) {
|
||||||
it.Base.TagResults(dst)
|
for _, tag := range it.tags.Tags() {
|
||||||
|
dst[tag] = it.Result()
|
||||||
|
}
|
||||||
|
|
||||||
|
for tag, value := range it.tags.Fixed() {
|
||||||
|
dst[tag] = value
|
||||||
|
}
|
||||||
|
|
||||||
it.primaryIt.TagResults(dst)
|
it.primaryIt.TagResults(dst)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -114,7 +126,7 @@ func (it *HasA) ResultTree() *graph.ResultTree {
|
||||||
// Print some information about this iterator.
|
// Print some information about this iterator.
|
||||||
func (it *HasA) DebugString(indent int) string {
|
func (it *HasA) DebugString(indent int) string {
|
||||||
var tags string
|
var tags string
|
||||||
for _, k := range it.Tags() {
|
for _, k := range it.tags.Tags() {
|
||||||
tags += fmt.Sprintf("%s;", k)
|
tags += fmt.Sprintf("%s;", k)
|
||||||
}
|
}
|
||||||
return fmt.Sprintf("%s(%s %d tags:%s direction:%s\n%s)", strings.Repeat(" ", indent), it.Type(), it.UID(), tags, it.dir, it.primaryIt.DebugString(indent+4))
|
return fmt.Sprintf("%s(%s %d tags:%s direction:%s\n%s)", strings.Repeat(" ", indent), it.Type(), it.UID(), tags, it.dir, it.primaryIt.DebugString(indent+4))
|
||||||
|
|
|
||||||
|
|
@ -36,11 +36,9 @@ func NextUID() uint64 {
|
||||||
// The Base iterator is the iterator other iterators inherit from to get some
|
// The Base iterator is the iterator other iterators inherit from to get some
|
||||||
// default functionality.
|
// default functionality.
|
||||||
type Base struct {
|
type Base struct {
|
||||||
Last graph.Value
|
Last graph.Value
|
||||||
tags []string
|
canNext bool
|
||||||
fixedTags map[string]graph.Value
|
uid uint64
|
||||||
canNext bool
|
|
||||||
uid uint64
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called by subclases.
|
// Called by subclases.
|
||||||
|
|
@ -56,41 +54,6 @@ func (it *Base) UID() uint64 {
|
||||||
return it.uid
|
return it.uid
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adds a tag to the iterator. Most iterators don't need to override.
|
|
||||||
func (it *Base) AddTag(tag string) {
|
|
||||||
if it.tags == nil {
|
|
||||||
it.tags = make([]string, 0)
|
|
||||||
}
|
|
||||||
it.tags = append(it.tags, tag)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (it *Base) AddFixedTag(tag string, value graph.Value) {
|
|
||||||
if it.fixedTags == nil {
|
|
||||||
it.fixedTags = make(map[string]graph.Value)
|
|
||||||
}
|
|
||||||
it.fixedTags[tag] = value
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns the tags.
|
|
||||||
func (it *Base) Tags() []string {
|
|
||||||
return it.tags
|
|
||||||
}
|
|
||||||
|
|
||||||
func (it *Base) FixedTags() map[string]graph.Value {
|
|
||||||
return it.fixedTags
|
|
||||||
}
|
|
||||||
|
|
||||||
func (it *Base) CopyTagsFrom(other_it graph.Iterator) {
|
|
||||||
for _, tag := range other_it.Tags() {
|
|
||||||
it.AddTag(tag)
|
|
||||||
}
|
|
||||||
|
|
||||||
for k, v := range other_it.FixedTags() {
|
|
||||||
it.AddFixedTag(k, v)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prints a silly debug string. Most classes override.
|
// Prints a silly debug string. Most classes override.
|
||||||
func (it *Base) DebugString(indent int) string {
|
func (it *Base) DebugString(indent int) string {
|
||||||
return fmt.Sprintf("%s(base)", strings.Repeat(" ", indent))
|
return fmt.Sprintf("%s(base)", strings.Repeat(" ", indent))
|
||||||
|
|
@ -140,18 +103,6 @@ func (it *Base) SubIterators() []graph.Iterator {
|
||||||
// Accessor
|
// Accessor
|
||||||
func (it *Base) CanNext() bool { return it.canNext }
|
func (it *Base) CanNext() bool { return it.canNext }
|
||||||
|
|
||||||
// Fill the map based on the tags assigned to this iterator. Default
|
|
||||||
// functionality works well for most iterators.
|
|
||||||
func (it *Base) TagResults(dst map[string]graph.Value) {
|
|
||||||
for _, tag := range it.Tags() {
|
|
||||||
dst[tag] = it.Result()
|
|
||||||
}
|
|
||||||
|
|
||||||
for tag, value := range it.FixedTags() {
|
|
||||||
dst[tag] = value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Nothing to clean up.
|
// Nothing to clean up.
|
||||||
// func (it *Base) Close() {}
|
// func (it *Base) Close() {}
|
||||||
|
|
||||||
|
|
@ -164,6 +115,7 @@ func (it *Base) Reset() {}
|
||||||
// so it's important to give it a special iterator.
|
// so it's important to give it a special iterator.
|
||||||
type Null struct {
|
type Null struct {
|
||||||
Base
|
Base
|
||||||
|
tags graph.Tagger
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fairly useless New function.
|
// Fairly useless New function.
|
||||||
|
|
@ -171,6 +123,21 @@ func NewNull() *Null {
|
||||||
return &Null{}
|
return &Null{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (it *Null) Tagger() *graph.Tagger {
|
||||||
|
return &it.tags
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fill the map based on the tags assigned to this iterator.
|
||||||
|
func (it *Null) TagResults(dst map[string]graph.Value) {
|
||||||
|
for _, tag := range it.tags.Tags() {
|
||||||
|
dst[tag] = it.Result()
|
||||||
|
}
|
||||||
|
|
||||||
|
for tag, value := range it.tags.Fixed() {
|
||||||
|
dst[tag] = value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (it *Null) Clone() graph.Iterator { return NewNull() }
|
func (it *Null) Clone() graph.Iterator { return NewNull() }
|
||||||
|
|
||||||
// Name the null iterator.
|
// Name the null iterator.
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,7 @@ import (
|
||||||
// `next_it` is the tempoarary iterator held per result in `primary_it`.
|
// `next_it` is the tempoarary iterator held per result in `primary_it`.
|
||||||
type LinksTo struct {
|
type LinksTo struct {
|
||||||
Base
|
Base
|
||||||
|
tags graph.Tagger
|
||||||
ts graph.TripleStore
|
ts graph.TripleStore
|
||||||
primaryIt graph.Iterator
|
primaryIt graph.Iterator
|
||||||
dir graph.Direction
|
dir graph.Direction
|
||||||
|
|
@ -67,9 +68,13 @@ func (it *LinksTo) Reset() {
|
||||||
it.nextIt = &Null{}
|
it.nextIt = &Null{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (it *LinksTo) Tagger() *graph.Tagger {
|
||||||
|
return &it.tags
|
||||||
|
}
|
||||||
|
|
||||||
func (it *LinksTo) Clone() graph.Iterator {
|
func (it *LinksTo) Clone() graph.Iterator {
|
||||||
out := NewLinksTo(it.ts, it.primaryIt.Clone(), it.dir)
|
out := NewLinksTo(it.ts, it.primaryIt.Clone(), it.dir)
|
||||||
out.CopyTagsFrom(it)
|
out.tags.CopyFrom(it)
|
||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -78,7 +83,14 @@ 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(dst map[string]graph.Value) {
|
func (it *LinksTo) TagResults(dst map[string]graph.Value) {
|
||||||
it.Base.TagResults(dst)
|
for _, tag := range it.tags.Tags() {
|
||||||
|
dst[tag] = it.Result()
|
||||||
|
}
|
||||||
|
|
||||||
|
for tag, value := range it.tags.Fixed() {
|
||||||
|
dst[tag] = value
|
||||||
|
}
|
||||||
|
|
||||||
it.primaryIt.TagResults(dst)
|
it.primaryIt.TagResults(dst)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,7 @@ import (
|
||||||
// and whether the last check we received was true or false.
|
// and whether the last check we received was true or false.
|
||||||
type Optional struct {
|
type Optional struct {
|
||||||
Base
|
Base
|
||||||
|
tags graph.Tagger
|
||||||
subIt graph.Iterator
|
subIt graph.Iterator
|
||||||
lastCheck bool
|
lastCheck bool
|
||||||
}
|
}
|
||||||
|
|
@ -61,9 +62,13 @@ func (it *Optional) Close() {
|
||||||
it.subIt.Close()
|
it.subIt.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (it *Optional) Tagger() *graph.Tagger {
|
||||||
|
return &it.tags
|
||||||
|
}
|
||||||
|
|
||||||
func (it *Optional) Clone() graph.Iterator {
|
func (it *Optional) Clone() graph.Iterator {
|
||||||
out := NewOptional(it.subIt.Clone())
|
out := NewOptional(it.subIt.Clone())
|
||||||
out.CopyTagsFrom(it)
|
out.tags.CopyFrom(it)
|
||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -111,7 +116,7 @@ func (it *Optional) DebugString(indent int) string {
|
||||||
return fmt.Sprintf("%s(%s tags:%s\n%s)",
|
return fmt.Sprintf("%s(%s tags:%s\n%s)",
|
||||||
strings.Repeat(" ", indent),
|
strings.Repeat(" ", indent),
|
||||||
it.Type(),
|
it.Type(),
|
||||||
it.Tags(),
|
it.tags.Tags(),
|
||||||
it.subIt.DebugString(indent+4))
|
it.subIt.DebugString(indent+4))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@ import (
|
||||||
|
|
||||||
type Or struct {
|
type Or struct {
|
||||||
Base
|
Base
|
||||||
|
tags graph.Tagger
|
||||||
isShortCircuiting bool
|
isShortCircuiting bool
|
||||||
internalIterators []graph.Iterator
|
internalIterators []graph.Iterator
|
||||||
itCount int
|
itCount int
|
||||||
|
|
@ -62,6 +63,10 @@ func (it *Or) Reset() {
|
||||||
it.currentIterator = -1
|
it.currentIterator = -1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (it *Or) Tagger() *graph.Tagger {
|
||||||
|
return &it.tags
|
||||||
|
}
|
||||||
|
|
||||||
func (it *Or) Clone() graph.Iterator {
|
func (it *Or) Clone() graph.Iterator {
|
||||||
var or *Or
|
var or *Or
|
||||||
if it.isShortCircuiting {
|
if it.isShortCircuiting {
|
||||||
|
|
@ -72,7 +77,7 @@ func (it *Or) Clone() graph.Iterator {
|
||||||
for _, sub := range it.internalIterators {
|
for _, sub := range it.internalIterators {
|
||||||
or.AddSubIterator(sub.Clone())
|
or.AddSubIterator(sub.Clone())
|
||||||
}
|
}
|
||||||
or.CopyTagsFrom(it)
|
or.tags.CopyFrom(it)
|
||||||
return or
|
return or
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -84,7 +89,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(dst map[string]graph.Value) {
|
func (it *Or) TagResults(dst map[string]graph.Value) {
|
||||||
it.Base.TagResults(dst)
|
for _, tag := range it.tags.Tags() {
|
||||||
|
dst[tag] = it.Result()
|
||||||
|
}
|
||||||
|
|
||||||
|
for tag, value := range it.tags.Fixed() {
|
||||||
|
dst[tag] = value
|
||||||
|
}
|
||||||
|
|
||||||
it.internalIterators[it.currentIterator].TagResults(dst)
|
it.internalIterators[it.currentIterator].TagResults(dst)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -105,7 +117,7 @@ func (it *Or) DebugString(indent int) string {
|
||||||
total += fmt.Sprintf("%d:\n%s\n", i, sub.DebugString(indent+4))
|
total += fmt.Sprintf("%d:\n%s\n", i, sub.DebugString(indent+4))
|
||||||
}
|
}
|
||||||
var tags string
|
var tags string
|
||||||
for _, k := range it.Tags() {
|
for _, k := range it.tags.Tags() {
|
||||||
tags += fmt.Sprintf("%s;", k)
|
tags += fmt.Sprintf("%s;", k)
|
||||||
}
|
}
|
||||||
spaces := strings.Repeat(" ", indent+2)
|
spaces := strings.Repeat(" ", indent+2)
|
||||||
|
|
@ -247,7 +259,7 @@ func (it *Or) Optimize() (graph.Iterator, bool) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Move the tags hanging on us (like any good replacement).
|
// Move the tags hanging on us (like any good replacement).
|
||||||
newOr.CopyTagsFrom(it)
|
newOr.tags.CopyFrom(it)
|
||||||
|
|
||||||
// And close ourselves but not our subiterators -- some may still be alive in
|
// And close ourselves but not our subiterators -- some may still be alive in
|
||||||
// the new And (they were unchanged upon calling Optimize() on them, at the
|
// the new And (they were unchanged upon calling Optimize() on them, at the
|
||||||
|
|
|
||||||
|
|
@ -107,10 +107,10 @@ func (qs *queryShape) StealNode(left *Node, right *Node) {
|
||||||
|
|
||||||
func (qs *queryShape) MakeNode(it graph.Iterator) *Node {
|
func (qs *queryShape) MakeNode(it graph.Iterator) *Node {
|
||||||
n := Node{Id: qs.nodeId}
|
n := Node{Id: qs.nodeId}
|
||||||
for _, tag := range it.Tags() {
|
for _, tag := range it.Tagger().Tags() {
|
||||||
n.Tags = append(n.Tags, tag)
|
n.Tags = append(n.Tags, tag)
|
||||||
}
|
}
|
||||||
for k, _ := range it.FixedTags() {
|
for k, _ := range it.Tagger().Fixed() {
|
||||||
n.Tags = append(n.Tags, k)
|
n.Tags = append(n.Tags, k)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ func hasaWithTag(ts graph.TripleStore, tag string, target string) *HasA {
|
||||||
|
|
||||||
obj := ts.FixedIterator()
|
obj := ts.FixedIterator()
|
||||||
obj.Add(ts.ValueOf(target))
|
obj.Add(ts.ValueOf(target))
|
||||||
obj.AddTag(tag)
|
obj.Tagger().Add(tag)
|
||||||
and.AddSubIterator(NewLinksTo(ts, obj, graph.Object))
|
and.AddSubIterator(NewLinksTo(ts, obj, graph.Object))
|
||||||
|
|
||||||
pred := ts.FixedIterator()
|
pred := ts.FixedIterator()
|
||||||
|
|
@ -48,7 +48,7 @@ func TestQueryShape(t *testing.T) {
|
||||||
|
|
||||||
// Given a single linkage iterator's shape.
|
// Given a single linkage iterator's shape.
|
||||||
hasa := hasaWithTag(ts, "tag", "cool")
|
hasa := hasaWithTag(ts, "tag", "cool")
|
||||||
hasa.AddTag("top")
|
hasa.Tagger().Add("top")
|
||||||
|
|
||||||
shape := make(map[string]interface{})
|
shape := make(map[string]interface{})
|
||||||
OutputQueryShapeForIterator(hasa, ts, shape)
|
OutputQueryShapeForIterator(hasa, ts, shape)
|
||||||
|
|
@ -93,11 +93,11 @@ func TestQueryShape(t *testing.T) {
|
||||||
andInternal := NewAnd()
|
andInternal := NewAnd()
|
||||||
|
|
||||||
hasa1 := hasaWithTag(ts, "tag1", "cool")
|
hasa1 := hasaWithTag(ts, "tag1", "cool")
|
||||||
hasa1.AddTag("hasa1")
|
hasa1.Tagger().Add("hasa1")
|
||||||
andInternal.AddSubIterator(hasa1)
|
andInternal.AddSubIterator(hasa1)
|
||||||
|
|
||||||
hasa2 := hasaWithTag(ts, "tag2", "fun")
|
hasa2 := hasaWithTag(ts, "tag2", "fun")
|
||||||
hasa2.AddTag("hasa2")
|
hasa2.Tagger().Add("hasa2")
|
||||||
andInternal.AddSubIterator(hasa2)
|
andInternal.AddSubIterator(hasa2)
|
||||||
|
|
||||||
pred := ts.FixedIterator()
|
pred := ts.FixedIterator()
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,7 @@ const (
|
||||||
|
|
||||||
type Comparison struct {
|
type Comparison struct {
|
||||||
Base
|
Base
|
||||||
|
tags graph.Tagger
|
||||||
subIt graph.Iterator
|
subIt graph.Iterator
|
||||||
op Operator
|
op Operator
|
||||||
val interface{}
|
val interface{}
|
||||||
|
|
@ -111,9 +112,13 @@ func (it *Comparison) Reset() {
|
||||||
it.subIt.Reset()
|
it.subIt.Reset()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (it *Comparison) Tagger() *graph.Tagger {
|
||||||
|
return &it.tags
|
||||||
|
}
|
||||||
|
|
||||||
func (it *Comparison) Clone() graph.Iterator {
|
func (it *Comparison) Clone() graph.Iterator {
|
||||||
out := NewComparison(it.subIt.Clone(), it.op, it.val, it.ts)
|
out := NewComparison(it.subIt.Clone(), it.op, it.val, it.ts)
|
||||||
out.CopyTagsFrom(it)
|
out.tags.CopyFrom(it)
|
||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -157,7 +162,14 @@ func (it *Comparison) Check(val graph.Value) 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(dst map[string]graph.Value) {
|
func (it *Comparison) TagResults(dst map[string]graph.Value) {
|
||||||
it.Base.TagResults(dst)
|
for _, tag := range it.tags.Tags() {
|
||||||
|
dst[tag] = it.Result()
|
||||||
|
}
|
||||||
|
|
||||||
|
for tag, value := range it.tags.Fixed() {
|
||||||
|
dst[tag] = value
|
||||||
|
}
|
||||||
|
|
||||||
it.subIt.TagResults(dst)
|
it.subIt.TagResults(dst)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@ import (
|
||||||
|
|
||||||
type AllIterator struct {
|
type AllIterator struct {
|
||||||
iterator.Base
|
iterator.Base
|
||||||
|
tags graph.Tagger
|
||||||
prefix []byte
|
prefix []byte
|
||||||
dir graph.Direction
|
dir graph.Direction
|
||||||
open bool
|
open bool
|
||||||
|
|
@ -66,9 +67,23 @@ func (it *AllIterator) Reset() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (it *AllIterator) Tagger() *graph.Tagger {
|
||||||
|
return &it.tags
|
||||||
|
}
|
||||||
|
|
||||||
|
func (it *AllIterator) TagResults(dst map[string]graph.Value) {
|
||||||
|
for _, tag := range it.tags.Tags() {
|
||||||
|
dst[tag] = it.Result()
|
||||||
|
}
|
||||||
|
|
||||||
|
for tag, value := range it.tags.Fixed() {
|
||||||
|
dst[tag] = value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (it *AllIterator) Clone() graph.Iterator {
|
func (it *AllIterator) Clone() graph.Iterator {
|
||||||
out := NewAllIterator(string(it.prefix), it.dir, it.ts)
|
out := NewAllIterator(string(it.prefix), it.dir, it.ts)
|
||||||
out.CopyTagsFrom(it)
|
out.tags.CopyFrom(it)
|
||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -115,7 +130,7 @@ func (it *AllIterator) Size() (int64, bool) {
|
||||||
|
|
||||||
func (it *AllIterator) DebugString(indent int) string {
|
func (it *AllIterator) DebugString(indent int) string {
|
||||||
size, _ := it.Size()
|
size, _ := it.Size()
|
||||||
return fmt.Sprintf("%s(%s tags: %v leveldb size:%d %s %p)", strings.Repeat(" ", indent), it.Type(), it.Tags(), size, it.dir, it)
|
return fmt.Sprintf("%s(%s tags: %v leveldb size:%d %s %p)", strings.Repeat(" ", indent), it.Type(), it.tags.Tags(), size, it.dir, it)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (it *AllIterator) Type() graph.Type { return graph.All }
|
func (it *AllIterator) Type() graph.Type { return graph.All }
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@ import (
|
||||||
|
|
||||||
type Iterator struct {
|
type Iterator struct {
|
||||||
iterator.Base
|
iterator.Base
|
||||||
|
tags graph.Tagger
|
||||||
nextPrefix []byte
|
nextPrefix []byte
|
||||||
checkId []byte
|
checkId []byte
|
||||||
dir graph.Direction
|
dir graph.Direction
|
||||||
|
|
@ -72,9 +73,23 @@ func (it *Iterator) Reset() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (it *Iterator) Tagger() *graph.Tagger {
|
||||||
|
return &it.tags
|
||||||
|
}
|
||||||
|
|
||||||
|
func (it *Iterator) TagResults(dst map[string]graph.Value) {
|
||||||
|
for _, tag := range it.tags.Tags() {
|
||||||
|
dst[tag] = it.Result()
|
||||||
|
}
|
||||||
|
|
||||||
|
for tag, value := range it.tags.Fixed() {
|
||||||
|
dst[tag] = value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (it *Iterator) Clone() graph.Iterator {
|
func (it *Iterator) Clone() graph.Iterator {
|
||||||
out := NewIterator(it.originalPrefix, it.dir, it.checkId, it.ts)
|
out := NewIterator(it.originalPrefix, it.dir, it.checkId, it.ts)
|
||||||
out.CopyTagsFrom(it)
|
out.tags.CopyFrom(it)
|
||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -192,7 +207,7 @@ func (it *Iterator) Size() (int64, bool) {
|
||||||
|
|
||||||
func (it *Iterator) DebugString(indent int) string {
|
func (it *Iterator) DebugString(indent int) string {
|
||||||
size, _ := it.Size()
|
size, _ := it.Size()
|
||||||
return fmt.Sprintf("%s(%s %d tags: %v dir: %s size:%d %s)", strings.Repeat(" ", indent), it.Type(), it.UID(), it.Tags(), it.dir, size, it.ts.NameOf(it.checkId))
|
return fmt.Sprintf("%s(%s %d tags: %v dir: %s size:%d %s)", strings.Repeat(" ", indent), it.Type(), it.UID(), it.tags.Tags(), it.dir, size, it.ts.NameOf(it.checkId))
|
||||||
}
|
}
|
||||||
|
|
||||||
var levelDBType graph.Type
|
var levelDBType graph.Type
|
||||||
|
|
|
||||||
|
|
@ -415,7 +415,7 @@ func TestOptimize(t *testing.T) {
|
||||||
// With an linksto-fixed pair
|
// With an linksto-fixed pair
|
||||||
fixed := ts.FixedIterator()
|
fixed := ts.FixedIterator()
|
||||||
fixed.Add(ts.ValueOf("F"))
|
fixed.Add(ts.ValueOf("F"))
|
||||||
fixed.AddTag("internal")
|
fixed.Tagger().Add("internal")
|
||||||
lto := iterator.NewLinksTo(ts, fixed, graph.Object)
|
lto := iterator.NewLinksTo(ts, fixed, graph.Object)
|
||||||
|
|
||||||
oldIt := lto.Clone()
|
oldIt := lto.Clone()
|
||||||
|
|
|
||||||
|
|
@ -42,9 +42,10 @@ func (ts *TripleStore) optimizeLinksTo(it *iterator.LinksTo) (graph.Iterator, bo
|
||||||
panic("Sizes lie")
|
panic("Sizes lie")
|
||||||
}
|
}
|
||||||
newIt := ts.TripleIterator(it.Direction(), val)
|
newIt := ts.TripleIterator(it.Direction(), val)
|
||||||
newIt.CopyTagsFrom(it)
|
nt := newIt.Tagger()
|
||||||
for _, tag := range primary.Tags() {
|
nt.CopyFrom(it)
|
||||||
newIt.AddFixedTag(tag, val)
|
for _, tag := range primary.Tagger().Tags() {
|
||||||
|
nt.AddFixed(tag, val)
|
||||||
}
|
}
|
||||||
it.Close()
|
it.Close()
|
||||||
return newIt, true
|
return newIt, true
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@ import (
|
||||||
|
|
||||||
type Iterator struct {
|
type Iterator struct {
|
||||||
iterator.Base
|
iterator.Base
|
||||||
|
tags graph.Tagger
|
||||||
tree *llrb.LLRB
|
tree *llrb.LLRB
|
||||||
data string
|
data string
|
||||||
isRunning bool
|
isRunning bool
|
||||||
|
|
@ -65,10 +66,24 @@ func (it *Iterator) Reset() {
|
||||||
it.iterLast = Int64(-1)
|
it.iterLast = Int64(-1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (it *Iterator) Tagger() *graph.Tagger {
|
||||||
|
return &it.tags
|
||||||
|
}
|
||||||
|
|
||||||
|
func (it *Iterator) TagResults(dst map[string]graph.Value) {
|
||||||
|
for _, tag := range it.tags.Tags() {
|
||||||
|
dst[tag] = it.Result()
|
||||||
|
}
|
||||||
|
|
||||||
|
for tag, value := range it.tags.Fixed() {
|
||||||
|
dst[tag] = value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (it *Iterator) Clone() graph.Iterator {
|
func (it *Iterator) Clone() graph.Iterator {
|
||||||
var new_it = NewLlrbIterator(it.tree, it.data)
|
m := NewLlrbIterator(it.tree, it.data)
|
||||||
new_it.CopyTagsFrom(it)
|
m.tags.CopyFrom(it)
|
||||||
return new_it
|
return m
|
||||||
}
|
}
|
||||||
|
|
||||||
func (it *Iterator) Close() {}
|
func (it *Iterator) Close() {}
|
||||||
|
|
@ -98,7 +113,7 @@ func (it *Iterator) Check(v graph.Value) bool {
|
||||||
|
|
||||||
func (it *Iterator) DebugString(indent int) string {
|
func (it *Iterator) DebugString(indent int) string {
|
||||||
size, _ := it.Size()
|
size, _ := it.Size()
|
||||||
return fmt.Sprintf("%s(%s tags:%s size:%d %s)", strings.Repeat(" ", indent), it.Type(), it.Tags(), size, it.data)
|
return fmt.Sprintf("%s(%s tags:%s size:%d %s)", strings.Repeat(" ", indent), it.Type(), it.tags.Tags(), size, it.data)
|
||||||
}
|
}
|
||||||
|
|
||||||
var memType graph.Type
|
var memType graph.Type
|
||||||
|
|
|
||||||
|
|
@ -42,9 +42,10 @@ func (ts *TripleStore) optimizeLinksTo(it *iterator.LinksTo) (graph.Iterator, bo
|
||||||
panic("Sizes lie")
|
panic("Sizes lie")
|
||||||
}
|
}
|
||||||
newIt := ts.TripleIterator(it.Direction(), val)
|
newIt := ts.TripleIterator(it.Direction(), val)
|
||||||
newIt.CopyTagsFrom(it)
|
nt := newIt.Tagger()
|
||||||
for _, tag := range primary.Tags() {
|
nt.CopyFrom(it)
|
||||||
newIt.AddFixedTag(tag, val)
|
for _, tag := range primary.Tagger().Tags() {
|
||||||
|
nt.AddFixed(tag, val)
|
||||||
}
|
}
|
||||||
return newIt, true
|
return newIt, true
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -150,7 +150,7 @@ func TestLinksToOptimization(t *testing.T) {
|
||||||
fixed.Add(ts.ValueOf("cool"))
|
fixed.Add(ts.ValueOf("cool"))
|
||||||
|
|
||||||
lto := iterator.NewLinksTo(ts, fixed, graph.Object)
|
lto := iterator.NewLinksTo(ts, fixed, graph.Object)
|
||||||
lto.AddTag("foo")
|
lto.Tagger().Add("foo")
|
||||||
|
|
||||||
newIt, changed := lto.Optimize()
|
newIt, changed := lto.Optimize()
|
||||||
if !changed {
|
if !changed {
|
||||||
|
|
@ -165,7 +165,8 @@ func TestLinksToOptimization(t *testing.T) {
|
||||||
if v_clone.DebugString(0) != v.DebugString(0) {
|
if v_clone.DebugString(0) != v.DebugString(0) {
|
||||||
t.Fatal("Wrong iterator. Got ", v_clone.DebugString(0))
|
t.Fatal("Wrong iterator. Got ", v_clone.DebugString(0))
|
||||||
}
|
}
|
||||||
if len(v_clone.Tags()) < 1 || v_clone.Tags()[0] != "foo" {
|
vt := v_clone.Tagger()
|
||||||
|
if len(vt.Tags()) < 1 || vt.Tags()[0] != "foo" {
|
||||||
t.Fatal("Tag on LinksTo did not persist")
|
t.Fatal("Tag on LinksTo did not persist")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@ import (
|
||||||
|
|
||||||
type Iterator struct {
|
type Iterator struct {
|
||||||
iterator.Base
|
iterator.Base
|
||||||
|
tags graph.Tagger
|
||||||
ts *TripleStore
|
ts *TripleStore
|
||||||
dir graph.Direction
|
dir graph.Direction
|
||||||
iter *mgo.Iter
|
iter *mgo.Iter
|
||||||
|
|
@ -98,15 +99,29 @@ func (it *Iterator) Close() {
|
||||||
it.iter.Close()
|
it.iter.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (it *Iterator) Clone() graph.Iterator {
|
func (it *Iterator) Tagger() *graph.Tagger {
|
||||||
var newM graph.Iterator
|
return &it.tags
|
||||||
if it.isAll {
|
}
|
||||||
newM = NewAllIterator(it.ts, it.collection)
|
|
||||||
} else {
|
func (it *Iterator) TagResults(dst map[string]graph.Value) {
|
||||||
newM = NewIterator(it.ts, it.collection, it.dir, it.hash)
|
for _, tag := range it.tags.Tags() {
|
||||||
|
dst[tag] = it.Result()
|
||||||
}
|
}
|
||||||
newM.CopyTagsFrom(it)
|
|
||||||
return newM
|
for tag, value := range it.tags.Fixed() {
|
||||||
|
dst[tag] = value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (it *Iterator) Clone() graph.Iterator {
|
||||||
|
var m *Iterator
|
||||||
|
if it.isAll {
|
||||||
|
m = NewAllIterator(it.ts, it.collection)
|
||||||
|
} else {
|
||||||
|
m = NewIterator(it.ts, it.collection, it.dir, it.hash)
|
||||||
|
}
|
||||||
|
m.tags.CopyFrom(it)
|
||||||
|
return m
|
||||||
}
|
}
|
||||||
|
|
||||||
func (it *Iterator) Next() (graph.Value, bool) {
|
func (it *Iterator) Next() (graph.Value, bool) {
|
||||||
|
|
|
||||||
|
|
@ -42,9 +42,10 @@ func (ts *TripleStore) optimizeLinksTo(it *iterator.LinksTo) (graph.Iterator, bo
|
||||||
panic("Sizes lie")
|
panic("Sizes lie")
|
||||||
}
|
}
|
||||||
newIt := ts.TripleIterator(it.Direction(), val)
|
newIt := ts.TripleIterator(it.Direction(), val)
|
||||||
newIt.CopyTagsFrom(it)
|
nt := newIt.Tagger()
|
||||||
for _, tag := range primary.Tags() {
|
nt.CopyFrom(it)
|
||||||
newIt.AddFixedTag(tag, val)
|
for _, tag := range primary.Tagger().Tags() {
|
||||||
|
nt.AddFixed(tag, val)
|
||||||
}
|
}
|
||||||
it.Close()
|
it.Close()
|
||||||
return newIt, true
|
return newIt, true
|
||||||
|
|
|
||||||
|
|
@ -189,7 +189,7 @@ func buildIteratorTree(tree *peg.ExpressionTree, ts graph.TripleStore) graph.Ite
|
||||||
nodeID := getIdentString(tree)
|
nodeID := getIdentString(tree)
|
||||||
if tree.Children[0].Name == "Variable" {
|
if tree.Children[0].Name == "Variable" {
|
||||||
allIt := ts.NodesAllIterator()
|
allIt := ts.NodesAllIterator()
|
||||||
allIt.AddTag(nodeID)
|
allIt.Tagger().Add(nodeID)
|
||||||
out = allIt
|
out = allIt
|
||||||
} else {
|
} else {
|
||||||
n := nodeID
|
n := nodeID
|
||||||
|
|
|
||||||
|
|
@ -135,7 +135,7 @@ func buildInOutIterator(obj *otto.Object, ts graph.TripleStore, base graph.Itera
|
||||||
tags = makeListOfStringsFromArrayValue(one.Object())
|
tags = makeListOfStringsFromArrayValue(one.Object())
|
||||||
}
|
}
|
||||||
for _, tag := range tags {
|
for _, tag := range tags {
|
||||||
predicateNodeIterator.AddTag(tag)
|
predicateNodeIterator.Tagger().Add(tag)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -179,7 +179,7 @@ func buildIteratorTreeHelper(obj *otto.Object, ts graph.TripleStore, base graph.
|
||||||
case "tag":
|
case "tag":
|
||||||
it = subIt
|
it = subIt
|
||||||
for _, tag := range stringArgs {
|
for _, tag := range stringArgs {
|
||||||
it.AddTag(tag)
|
it.Tagger().Add(tag)
|
||||||
}
|
}
|
||||||
case "save":
|
case "save":
|
||||||
all := ts.NodesAllIterator()
|
all := ts.NodesAllIterator()
|
||||||
|
|
@ -187,9 +187,9 @@ func buildIteratorTreeHelper(obj *otto.Object, ts graph.TripleStore, base graph.
|
||||||
return iterator.NewNull()
|
return iterator.NewNull()
|
||||||
}
|
}
|
||||||
if len(stringArgs) == 2 {
|
if len(stringArgs) == 2 {
|
||||||
all.AddTag(stringArgs[1])
|
all.Tagger().Add(stringArgs[1])
|
||||||
} else {
|
} else {
|
||||||
all.AddTag(stringArgs[0])
|
all.Tagger().Add(stringArgs[0])
|
||||||
}
|
}
|
||||||
predFixed := ts.FixedIterator()
|
predFixed := ts.FixedIterator()
|
||||||
predFixed.Add(ts.ValueOf(stringArgs[0]))
|
predFixed.Add(ts.ValueOf(stringArgs[0]))
|
||||||
|
|
@ -207,9 +207,9 @@ func buildIteratorTreeHelper(obj *otto.Object, ts graph.TripleStore, base graph.
|
||||||
return iterator.NewNull()
|
return iterator.NewNull()
|
||||||
}
|
}
|
||||||
if len(stringArgs) == 2 {
|
if len(stringArgs) == 2 {
|
||||||
all.AddTag(stringArgs[1])
|
all.Tagger().Add(stringArgs[1])
|
||||||
} else {
|
} else {
|
||||||
all.AddTag(stringArgs[0])
|
all.Tagger().Add(stringArgs[0])
|
||||||
}
|
}
|
||||||
predFixed := ts.FixedIterator()
|
predFixed := ts.FixedIterator()
|
||||||
predFixed.Add(ts.ValueOf(stringArgs[0]))
|
predFixed.Add(ts.ValueOf(stringArgs[0]))
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@ func embedFinals(env *otto.Otto, ses *Session, obj *otto.Object) {
|
||||||
func allFunc(env *otto.Otto, ses *Session, obj *otto.Object) func(otto.FunctionCall) otto.Value {
|
func allFunc(env *otto.Otto, ses *Session, obj *otto.Object) func(otto.FunctionCall) otto.Value {
|
||||||
return func(call otto.FunctionCall) otto.Value {
|
return func(call otto.FunctionCall) otto.Value {
|
||||||
it := buildIteratorTree(obj, ses.ts)
|
it := buildIteratorTree(obj, ses.ts)
|
||||||
it.AddTag(TopResultTag)
|
it.Tagger().Add(TopResultTag)
|
||||||
ses.limit = -1
|
ses.limit = -1
|
||||||
ses.count = 0
|
ses.count = 0
|
||||||
runIteratorOnSession(it, ses)
|
runIteratorOnSession(it, ses)
|
||||||
|
|
@ -51,7 +51,7 @@ func limitFunc(env *otto.Otto, ses *Session, obj *otto.Object) func(otto.Functio
|
||||||
if len(call.ArgumentList) > 0 {
|
if len(call.ArgumentList) > 0 {
|
||||||
limitVal, _ := call.Argument(0).ToInteger()
|
limitVal, _ := call.Argument(0).ToInteger()
|
||||||
it := buildIteratorTree(obj, ses.ts)
|
it := buildIteratorTree(obj, ses.ts)
|
||||||
it.AddTag(TopResultTag)
|
it.Tagger().Add(TopResultTag)
|
||||||
ses.limit = int(limitVal)
|
ses.limit = int(limitVal)
|
||||||
ses.count = 0
|
ses.count = 0
|
||||||
runIteratorOnSession(it, ses)
|
runIteratorOnSession(it, ses)
|
||||||
|
|
@ -63,7 +63,7 @@ func limitFunc(env *otto.Otto, ses *Session, obj *otto.Object) func(otto.Functio
|
||||||
func toArrayFunc(env *otto.Otto, ses *Session, obj *otto.Object, withTags bool) func(otto.FunctionCall) otto.Value {
|
func toArrayFunc(env *otto.Otto, ses *Session, obj *otto.Object, withTags bool) func(otto.FunctionCall) otto.Value {
|
||||||
return func(call otto.FunctionCall) otto.Value {
|
return func(call otto.FunctionCall) otto.Value {
|
||||||
it := buildIteratorTree(obj, ses.ts)
|
it := buildIteratorTree(obj, ses.ts)
|
||||||
it.AddTag(TopResultTag)
|
it.Tagger().Add(TopResultTag)
|
||||||
limit := -1
|
limit := -1
|
||||||
if len(call.ArgumentList) > 0 {
|
if len(call.ArgumentList) > 0 {
|
||||||
limitParsed, _ := call.Argument(0).ToInteger()
|
limitParsed, _ := call.Argument(0).ToInteger()
|
||||||
|
|
@ -90,7 +90,7 @@ func toArrayFunc(env *otto.Otto, ses *Session, obj *otto.Object, withTags bool)
|
||||||
func toValueFunc(env *otto.Otto, ses *Session, obj *otto.Object, withTags bool) func(otto.FunctionCall) otto.Value {
|
func toValueFunc(env *otto.Otto, ses *Session, obj *otto.Object, withTags bool) func(otto.FunctionCall) otto.Value {
|
||||||
return func(call otto.FunctionCall) otto.Value {
|
return func(call otto.FunctionCall) otto.Value {
|
||||||
it := buildIteratorTree(obj, ses.ts)
|
it := buildIteratorTree(obj, ses.ts)
|
||||||
it.AddTag(TopResultTag)
|
it.Tagger().Add(TopResultTag)
|
||||||
limit := 1
|
limit := 1
|
||||||
var val otto.Value
|
var val otto.Value
|
||||||
var err error
|
var err error
|
||||||
|
|
@ -120,7 +120,7 @@ func toValueFunc(env *otto.Otto, ses *Session, obj *otto.Object, withTags bool)
|
||||||
func mapFunc(env *otto.Otto, ses *Session, obj *otto.Object) func(otto.FunctionCall) otto.Value {
|
func mapFunc(env *otto.Otto, ses *Session, obj *otto.Object) func(otto.FunctionCall) otto.Value {
|
||||||
return func(call otto.FunctionCall) otto.Value {
|
return func(call otto.FunctionCall) otto.Value {
|
||||||
it := buildIteratorTree(obj, ses.ts)
|
it := buildIteratorTree(obj, ses.ts)
|
||||||
it.AddTag(TopResultTag)
|
it.Tagger().Add(TopResultTag)
|
||||||
limit := -1
|
limit := -1
|
||||||
if len(call.ArgumentList) == 0 {
|
if len(call.ArgumentList) == 0 {
|
||||||
return otto.NullValue()
|
return otto.NullValue()
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ func (q *Query) buildFixed(s string) graph.Iterator {
|
||||||
|
|
||||||
func (q *Query) buildResultIterator(path Path) graph.Iterator {
|
func (q *Query) buildResultIterator(path Path) graph.Iterator {
|
||||||
all := q.ses.ts.NodesAllIterator()
|
all := q.ses.ts.NodesAllIterator()
|
||||||
all.AddTag(string(path))
|
all.Tagger().Add(string(path))
|
||||||
return all
|
return all
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -97,7 +97,7 @@ func (q *Query) buildIteratorTreeInternal(query interface{}, path Path) (it grap
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, false, err
|
return nil, false, err
|
||||||
}
|
}
|
||||||
it.AddTag(string(path))
|
it.Tagger().Add(string(path))
|
||||||
return it, optional, nil
|
return it, optional, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue