func (qs *QuadStore) optimizeLinksTo(it *iterator.LinksTo) (graph.Iterator, bool) {
	subs := it.SubIterators()
	if len(subs) != 1 {
		return it, false
	}
	primary := subs[0]
	if primary.Type() == graph.Fixed {
		size, _ := primary.Size()
		if size == 1 {
			if !primary.Next() {
				panic("unexpected size during optimize")
			}
			val := primary.Result()
			newIt := qs.QuadIterator(it.Direction(), val)
			nt := newIt.Tagger()
			nt.CopyFrom(it)
			for _, tag := range primary.Tagger().Tags() {
				nt.AddFixed(tag, val)
			}
			it.Close()
			return newIt, true
		}
	}
	return it, false
}
示例#2
0
func (qs *QuadStore) optimizeLinksTo(it *iterator.LinksTo) (graph.Iterator, bool) {
	subs := it.SubIterators()
	if len(subs) != 1 {
		return it, false
	}
	primary := subs[0]
	switch primary.Type() {
	case graph.Fixed:
		size, _ := primary.Size()
		if size == 0 {
			return iterator.NewNull(), true
		}
		if size == 1 {
			if !primary.Next() {
				panic("sql: unexpected size during optimize")
			}
			val := primary.Result()
			newIt := qs.QuadIterator(it.Direction(), val)
			nt := newIt.Tagger()
			nt.CopyFrom(it)
			for _, tag := range primary.Tagger().Tags() {
				nt.AddFixed(tag, val)
			}
			it.Close()
			return newIt, true
		} else if size > 1 {
			var vals []NodeHash
			for primary.Next() {
				vals = append(vals, primary.Result().(NodeHash))
			}
			lsql := &SQLLinkIterator{
				constraints: []constraint{
					constraint{
						dir:    it.Direction(),
						hashes: vals,
					},
				},
				tableName: newTableName(),
				size:      0,
			}
			l := &SQLIterator{
				uid: iterator.NextUID(),
				qs:  qs,
				sql: lsql,
			}
			nt := l.Tagger()
			nt.CopyFrom(it)
			for _, t := range primary.Tagger().Tags() {
				lsql.tagdirs = append(lsql.tagdirs, tagDir{
					dir: it.Direction(),
					tag: t,
				})
			}
			it.Close()
			return l, true
		}
	case sqlType:
		p := primary.(*SQLIterator)
		newit, err := linksto(p.sql, it.Direction(), qs)
		if err != nil {
			clog.Errorf("%v", err)
			return it, false
		}
		newit.Tagger().CopyFrom(it)
		return newit, true
	case graph.All:
		linkit := &SQLLinkIterator{
			tableName: newTableName(),
			size:      qs.Size(),
		}
		for _, t := range primary.Tagger().Tags() {
			linkit.tagdirs = append(linkit.tagdirs, tagDir{
				dir: it.Direction(),
				tag: t,
			})
		}
		for k, v := range primary.Tagger().Fixed() {
			linkit.tagger.AddFixed(k, v)
		}
		linkit.tagger.CopyFrom(it)
		newit := NewSQLIterator(qs, linkit)
		return newit, true
	}
	return it, false
}