diff --git a/graph/iterator/materialize_iterator.go b/graph/iterator/materialize_iterator.go index 1b448b3..8bd2a53 100644 --- a/graph/iterator/materialize_iterator.go +++ b/graph/iterator/materialize_iterator.go @@ -32,6 +32,10 @@ type result struct { tags map[string]graph.Value } +type hashable interface { + Hashable() interface{} +} + type Materialize struct { uid uint64 tags graph.Tagger @@ -228,7 +232,7 @@ func (it *Materialize) NextResult() bool { func (it *Materialize) materializeSet() { i := 0 for { - val, ok := graph.Next(it.subIt) + id, ok := graph.Next(it.subIt) if !ok { break } @@ -237,6 +241,10 @@ func (it *Materialize) materializeSet() { it.aborted = true break } + val := id + if h, ok := id.(hashable); ok { + val = h.Hashable() + } if _, ok := it.containsMap[val]; !ok { it.containsMap[val] = len(it.values) it.values = append(it.values, nil) diff --git a/graph/leveldb/all_iterator.go b/graph/leveldb/all_iterator.go index 5346f97..a810792 100644 --- a/graph/leveldb/all_iterator.go +++ b/graph/leveldb/all_iterator.go @@ -117,8 +117,8 @@ func (it *AllIterator) Next() (graph.Value, bool) { it.Close() return nil, false } - it.result = out - return out, true + it.result = Token(out) + return it.result, true } func (it *AllIterator) ResultTree() *graph.ResultTree { diff --git a/graph/leveldb/iterator.go b/graph/leveldb/iterator.go index b434dfd..720b664 100644 --- a/graph/leveldb/iterator.go +++ b/graph/leveldb/iterator.go @@ -42,7 +42,7 @@ type Iterator struct { } func NewIterator(prefix string, d quad.Direction, value graph.Value, qs *TripleStore) *Iterator { - vb := value.([]byte) + vb := value.(Token) p := make([]byte, 0, 2+qs.hasher.Size()) p = append(p, []byte(prefix)...) p = append(p, []byte(vb[1:])...) @@ -105,7 +105,7 @@ func (it *Iterator) TagResults(dst map[string]graph.Value) { } func (it *Iterator) Clone() graph.Iterator { - out := NewIterator(it.originalPrefix, it.dir, it.checkId, it.qs) + out := NewIterator(it.originalPrefix, it.dir, Token(it.checkId), it.qs) out.tags.CopyFrom(it) return out } @@ -134,12 +134,12 @@ func (it *Iterator) Next() (graph.Value, bool) { if bytes.HasPrefix(it.iter.Key(), it.nextPrefix) { out := make([]byte, len(it.iter.Key())) copy(out, it.iter.Key()) - it.result = out + it.result = Token(out) ok := it.iter.Next() if !ok { it.Close() } - return out, true + return Token(out), true } it.Close() it.result = nil @@ -216,7 +216,7 @@ func PositionOf(prefix []byte, d quad.Direction, qs *TripleStore) int { } func (it *Iterator) Contains(v graph.Value) bool { - val := v.([]byte) + val := v.(Token) if val[0] == 'z' { return false } @@ -227,7 +227,7 @@ func (it *Iterator) Contains(v graph.Value) bool { } } else { nameForDir := it.qs.Quad(v).Get(it.dir) - hashForDir := it.qs.ValueOf(nameForDir).([]byte) + hashForDir := it.qs.ValueOf(nameForDir).(Token) if bytes.Equal(hashForDir, it.checkId) { return true } @@ -236,12 +236,20 @@ func (it *Iterator) Contains(v graph.Value) bool { } func (it *Iterator) Size() (int64, bool) { - return it.qs.SizeOf(it.checkId), true + return it.qs.SizeOf(Token(it.checkId)), true } func (it *Iterator) DebugString(indent int) string { 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.Tags(), it.dir, size, it.qs.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.qs.NameOf(Token(it.checkId)), + ) } var levelDBType graph.Type diff --git a/graph/leveldb/triplestore.go b/graph/leveldb/triplestore.go index 600b360..8ba7bde 100644 --- a/graph/leveldb/triplestore.go +++ b/graph/leveldb/triplestore.go @@ -42,6 +42,12 @@ const ( DefaultWriteBufferSize = 20 ) +type Token []byte + +func (t Token) Hashable() interface{} { + return string(t) +} + type TripleStore struct { dbOpts *opt.Options db *leveldb.DB @@ -308,7 +314,7 @@ func (qs *TripleStore) Close() { func (qs *TripleStore) Quad(k graph.Value) quad.Quad { var triple quad.Quad - b, err := qs.db.Get(k.([]byte), qs.readopts) + b, err := qs.db.Get(k.(Token), qs.readopts) if err != nil && err != leveldb.ErrNotFound { glog.Error("Error: couldn't get triple from DB.") return quad.Quad{} @@ -334,7 +340,7 @@ func (qs *TripleStore) convertStringToByteHash(s string) []byte { } func (qs *TripleStore) ValueOf(s string) graph.Value { - return qs.createValueKeyFor(s) + return Token(qs.createValueKeyFor(s)) } func (qs *TripleStore) valueData(value_key []byte) ValueData { @@ -362,14 +368,14 @@ func (qs *TripleStore) NameOf(k graph.Value) string { glog.V(2).Info("k was nil") return "" } - return qs.valueData(k.([]byte)).Name + return qs.valueData(k.(Token)).Name } func (qs *TripleStore) SizeOf(k graph.Value) int64 { if k == nil { return 0 } - return int64(qs.valueData(k.([]byte)).Size) + return int64(qs.valueData(k.(Token)).Size) } func (qs *TripleStore) getSize() { @@ -432,17 +438,17 @@ func (qs *TripleStore) TriplesAllIterator() graph.Iterator { } func (qs *TripleStore) TripleDirection(val graph.Value, d quad.Direction) graph.Value { - v := val.([]uint8) + v := val.(Token) offset := PositionOf(v[0:2], d, qs) if offset != -1 { - return append([]byte("z"), v[offset:offset+qs.hasher.Size()]...) + return Token(append([]byte("z"), v[offset:offset+qs.hasher.Size()]...)) } else { - return qs.Quad(val).Get(d) + return Token(qs.Quad(val).Get(d)) } } func compareBytes(a, b graph.Value) bool { - return bytes.Equal(a.([]uint8), b.([]uint8)) + return bytes.Equal(a.(Token), b.(Token)) } func (qs *TripleStore) FixedIterator() graph.FixedIterator {