Пример #1
0
func (qs *QuadStore) optimizeAndIterator(it *iterator.And) (graph.Iterator, bool) {
	// Fail fast if nothing can happen
	glog.V(4).Infoln("Entering optimizeAndIterator", it.UID())
	found := false
	for _, it := range it.SubIterators() {
		glog.V(4).Infoln(it.Type())
		if it.Type() == mongoType {
			found = true
		}
	}
	if !found {
		glog.V(4).Infoln("Aborting optimizeAndIterator")
		return it, false
	}

	newAnd := iterator.NewAnd(qs)
	var mongoIt *Iterator
	for _, it := range it.SubIterators() {
		switch it.Type() {
		case mongoType:
			if mongoIt == nil {
				mongoIt = it.(*Iterator)
			} else {
				newAnd.AddSubIterator(it)
			}
		case graph.LinksTo:
			continue
		default:
			newAnd.AddSubIterator(it)
		}
	}
	stats := mongoIt.Stats()

	lset := []graph.Linkage{
		{
			Dir:   mongoIt.dir,
			Value: qs.ValueOf(mongoIt.name),
		},
	}

	n := 0
	for _, it := range it.SubIterators() {
		if it.Type() == graph.LinksTo {
			lto := it.(*iterator.LinksTo)
			// Is it more effective to do the replacement, or let the mongo check the linksto?
			ltostats := lto.Stats()
			if (ltostats.ContainsCost+stats.NextCost)*stats.Size > (ltostats.NextCost+stats.ContainsCost)*ltostats.Size {
				continue
			}
			newLto := NewLinksTo(qs, lto.SubIterators()[0], "quads", lto.Direction(), lset)
			newAnd.AddSubIterator(newLto)
			n++
		}
	}
	if n == 0 {
		return it, false
	}

	return newAnd.Optimize()
}
Пример #2
0
func (it *AllIterator) makeCursor() {
	var cursor *sql.Rows
	var err error
	if it.cursor != nil {
		it.cursor.Close()
	}
	if it.table == "quads" {
		cursor, err = it.qs.db.Query(`SELECT subject, predicate, object, label FROM quads;`)
		if err != nil {
			glog.Errorln("Couldn't get cursor from SQL database: %v", err)
			cursor = nil
		}
	} else {
		glog.V(4).Infoln("sql: getting node query")
		cursor, err = it.qs.db.Query(`SELECT node FROM
			(
				SELECT subject FROM quads
				UNION
				SELECT predicate FROM quads
				UNION
				SELECT object FROM quads
				UNION
				SELECT label FROM quads
			) AS DistinctNodes (node) WHERE node IS NOT NULL;`)
		if err != nil {
			glog.Errorln("Couldn't get cursor from SQL database: %v", err)
			cursor = nil
		}
		glog.V(4).Infoln("sql: got node query")
	}
	it.cursor = cursor
}
Пример #3
0
func (m *MqlSession) ExecInput(input string, c chan interface{}, limit int) {
	defer close(c)
	var mqlQuery interface{}
	err := json.Unmarshal([]byte(input), &mqlQuery)
	if err != nil {
		return
	}
	m.currentQuery = NewMqlQuery(m)
	m.currentQuery.BuildIteratorTree(mqlQuery)
	if m.currentQuery.isError {
		return
	}
	it, _ := m.currentQuery.it.Optimize()
	if glog.V(2) {
		glog.V(2).Infoln(it.DebugString(0))
	}
	for {
		_, ok := it.Next()
		if !ok {
			break
		}
		tags := make(map[string]graph.TSVal)
		it.TagResults(&tags)
		c <- &tags
		for it.NextResult() == true {
			tags := make(map[string]graph.TSVal)
			it.TagResults(&tags)
			c <- &tags
		}
	}
}
Пример #4
0
func (s *Session) ExecInput(input string, c chan interface{}, _ int) {
	defer close(c)
	var mqlQuery interface{}
	err := json.Unmarshal([]byte(input), &mqlQuery)
	if err != nil {
		return
	}
	s.currentQuery = NewQuery(s)
	s.currentQuery.BuildIteratorTree(mqlQuery)
	if s.currentQuery.isError() {
		return
	}
	it, _ := s.currentQuery.it.Optimize()
	if glog.V(2) {
		glog.V(2).Infoln(it.DebugString(0))
	}
	for graph.Next(it) {
		tags := make(map[string]graph.Value)
		it.TagResults(tags)
		c <- tags
		for it.NextPath() == true {
			tags := make(map[string]graph.Value)
			it.TagResults(tags)
			c <- tags
		}
	}
}
Пример #5
0
func Load(qw graph.QuadWriter, cfg *config.Config, dec quad.Unmarshaler) error {
	block := make([]quad.Quad, 0, cfg.LoadSize)
	count := 0
	for {
		t, err := dec.Unmarshal()
		if err != nil {
			if err == io.EOF {
				break
			}
			return err
		}
		block = append(block, t)
		if len(block) == cap(block) {
			count += len(block)
			err := qw.AddQuadSet(block)
			if err != nil {
				return fmt.Errorf("db: failed to load data: %v", err)
			}
			block = block[:0]
			if glog.V(2) {
				glog.V(2).Infof("Wrote %d quads.", count)
			}
		}
	}
	count += len(block)
	err := qw.AddQuadSet(block)
	if err != nil {
		return fmt.Errorf("db: failed to load data: %v", err)
	}
	if glog.V(2) {
		glog.V(2).Infof("Wrote %d quads.", count)
	}

	return nil
}
Пример #6
0
// Size is the number of values stored, if we've got them all.
// Otherwise, guess based on the size of the subiterator.
func (it *Materialize) Size() (int64, bool) {
	if it.hasRun && !it.aborted {
		glog.V(2).Infoln("returning size", it.actualSize)
		return it.actualSize, true
	}
	glog.V(2).Infoln("bailing size", it.actualSize)
	return it.subIt.Size()
}
Пример #7
0
func (l *SQLLinkIterator) buildSQL(next bool, val graph.Value) (string, []string) {
	query := "SELECT "
	t := []string{
		fmt.Sprintf("%s.subject", l.tableName),
		fmt.Sprintf("%s.predicate", l.tableName),
		fmt.Sprintf("%s.object", l.tableName),
		fmt.Sprintf("%s.label", l.tableName),
	}
	for _, v := range l.getTags() {
		t = append(t, v.String())
	}
	query += strings.Join(t, ", ")
	query += " FROM "
	t = []string{}
	var values []string
	for _, k := range l.getTables() {
		values = append(values, k.values...)
		t = append(t, fmt.Sprintf("%s as %s", k.table, k.name))
	}
	query += strings.Join(t, ", ")
	constraint, wherevalues := l.buildWhere()
	if constraint != "" {
		query += " WHERE "
	}

	values = append(values, wherevalues...)
	if !next {
		v := val.(quad.Quad)
		if constraint != "" {
			constraint += " AND "
		} else {
			constraint += " WHERE "
		}
		t = []string{
			fmt.Sprintf("%s.subject_hash = ?", l.tableName),
			fmt.Sprintf("%s.predicate_hash = ?", l.tableName),
			fmt.Sprintf("%s.object_hash = ?", l.tableName),
			fmt.Sprintf("%s.label_hash = ?", l.tableName),
		}
		constraint += strings.Join(t, " AND ")
		values = append(values, hashOf(v.Subject))
		values = append(values, hashOf(v.Predicate))
		values = append(values, hashOf(v.Object))
		values = append(values, hashOf(v.Label))
	}
	query += constraint
	query += ";"

	if glog.V(4) {
		dstr := query
		for i := 1; i <= len(values); i++ {
			dstr = strings.Replace(dstr, "?", fmt.Sprintf("'%s'", values[i-1]), 1)
		}
		glog.V(4).Infoln(dstr)
	}
	return query, values
}
Пример #8
0
func ContainsLogOut(it Iterator, val Value, good bool) bool {
	if glog.V(4) {
		if good {
			glog.V(4).Infof("%s %d CHECK CONTAINS %d GOOD", strings.ToUpper(it.Type().String()), it.UID(), val)
		} else {
			glog.V(4).Infof("%s %d CHECK CONTAINS %d BAD", strings.ToUpper(it.Type().String()), it.UID(), val)
		}
	}
	return good
}
Пример #9
0
func NextLogOut(it Iterator, val TSVal, ok bool) (TSVal, bool) {
	if glog.V(4) {
		if ok {
			glog.V(4).Infof("%s %d NEXT IS %d", strings.ToUpper(it.Type()), it.GetUid(), val)
		} else {
			glog.V(4).Infof("%s %d NEXT DONE", strings.ToUpper(it.Type()), it.GetUid())
		}
	}
	return val, ok
}
Пример #10
0
func NextLogOut(it Iterator, val Value, ok bool) (Value, bool) {
	if glog.V(4) {
		if ok {
			glog.V(4).Infof("%s %d NEXT IS %d", strings.ToUpper(it.Type().String()), it.UID(), val)
		} else {
			glog.V(4).Infof("%s %d NEXT DONE", strings.ToUpper(it.Type().String()), it.UID())
		}
	}
	return val, ok
}
Пример #11
0
func CheckLogOut(it Iterator, val TSVal, good bool) bool {
	if glog.V(4) {
		if good {
			glog.V(4).Infof("%s %d CHECK %d GOOD", strings.ToUpper(it.Type()), it.GetUid(), val)
		} else {
			glog.V(4).Infof("%s %d CHECK %d BAD", strings.ToUpper(it.Type()), it.GetUid(), val)
		}
	}
	return good
}
Пример #12
0
// Check a value against our internal iterator. In order to do this, we must first open a new
// iterator of "triples that have `val` in our direction", given to us by the triple store,
// and then Next() values out of that iterator and Check() them against our subiterator.
func (it *HasA) Check(val graph.TSVal) bool {
	graph.CheckLogIn(it, val)
	if glog.V(4) {
		glog.V(4).Infoln("Id is", it.ts.GetNameFor(val))
	}
	// TODO(barakmich): Optimize this
	if it.resultIt != nil {
		it.resultIt.Close()
	}
	it.resultIt = it.ts.GetTripleIterator(it.dir, val)
	return graph.CheckLogOut(it, val, it.GetCheckResult())
}
Пример #13
0
// Check a value against our internal iterator. In order to do this, we must first open a new
// iterator of "triples that have `val` in our direction", given to us by the triple store,
// and then Next() values out of that iterator and Contains() them against our subiterator.
func (it *HasA) Contains(val graph.Value) bool {
	graph.ContainsLogIn(it, val)
	if glog.V(4) {
		glog.V(4).Infoln("Id is", it.ts.NameOf(val))
	}
	// TODO(barakmich): Optimize this
	if it.resultIt != nil {
		it.resultIt.Close()
	}
	it.resultIt = it.ts.TripleIterator(it.dir, val)
	return graph.ContainsLogOut(it, val, it.NextContains())
}
Пример #14
0
// Check a value against our internal iterator. In order to do this, we must first open a new
// iterator of "triples that have `val` in our direction", given to us by the triple store,
// and then Next() values out of that iterator and Check() them against our subiterator.
func (h *HasaIterator) Check(val TSVal) bool {
	CheckLogIn(h, val)
	if glog.V(4) {
		glog.V(4).Infoln("Id is", h.ts.GetNameFor(val))
	}
	// TODO(barakmich): Optimize this
	if h.resultIt != nil {
		h.resultIt.Close()
	}
	h.resultIt = h.ts.GetTripleIterator(h.direction, val)
	return CheckLogOut(h, val, h.GetCheckResult())
}
Пример #15
0
// NextContains() is shared code between Contains() and GetNextResult() -- calls next on the
// result iterator (a triple iterator based on the last checked value) and returns true if
// another match is made.
func (it *HasA) NextContains() bool {
	for graph.Next(it.resultIt) {
		link := it.resultIt.Result()
		if glog.V(4) {
			glog.V(4).Infoln("Quad is", it.ts.Quad(link))
		}
		if it.primaryIt.Contains(link) {
			it.result = it.ts.TripleDirection(link, it.dir)
			return true
		}
	}
	return false
}
Пример #16
0
// NextContains() is shared code between Contains() and GetNextResult() -- calls next on the
// result iterator (a quad iterator based on the last checked value) and returns true if
// another match is made.
func (it *HasA) NextContains() bool {
	for graph.Next(it.resultIt) {
		it.runstats.ContainsNext += 1
		link := it.resultIt.Result()
		if glog.V(4) {
			glog.V(4).Infoln("Quad is", it.qs.Quad(link))
		}
		if it.primaryIt.Contains(link) {
			it.result = it.qs.QuadDirection(link, it.dir)
			return true
		}
	}
	it.err = it.resultIt.Err()
	return false
}
Пример #17
0
// Get the next result that matches this branch.
func (it *HasA) NextPath() bool {
	// Order here is important. If the subiterator has a NextPath, then we
	// need do nothing -- there is a next result, and we shouldn't move forward.
	// However, we then need to get the next result from our last Contains().
	//
	// The upshot is, the end of NextPath() bubbles up from the bottom of the
	// iterator tree up, and we need to respect that.
	glog.V(4).Infoln("HASA", it.UID(), "NextPath")
	if it.primaryIt.NextPath() {
		return true
	}
	result := it.NextContains()
	glog.V(4).Infoln("HASA", it.UID(), "NextPath Returns", result, "")
	return result
}
Пример #18
0
// Called by subclases.
func BaseInit(it *Base) {
	// Your basic iterator is nextable
	it.canNext = true
	if glog.V(2) {
		it.uid = nextID()
	}
}
Пример #19
0
func (ts *TripleStore) NameOf(k graph.Value) string {
	if k == nil {
		glog.V(2).Infoln("k was nil")
		return ""
	}
	return ts.valueData(k.([]byte)).Name
}
Пример #20
0
func (qs *TripleStore) NameOf(k graph.Value) string {
	if k == nil {
		glog.V(2).Info("k was nil")
		return ""
	}
	return qs.valueData(k.(Token)).Name
}
Пример #21
0
func (qs *QuadStore) sizeForIterator(isAll bool, dir quad.Direction, val string) int64 {
	var err error
	if isAll {
		return qs.Size()
	}
	if qs.noSizes {
		if dir == quad.Predicate {
			return (qs.Size() / 100) + 1
		}
		return (qs.Size() / 1000) + 1
	}
	if val, ok := qs.lru.Get(val + string(dir.Prefix())); ok {
		return val
	}
	var size int64
	glog.V(4).Infoln("sql: getting size for select %s, %s", dir.String(), val)
	err = qs.db.QueryRow(
		fmt.Sprintf("SELECT count(*) FROM quads WHERE %s_hash = $1;", dir.String()), hashOf(val)).Scan(&size)
	if err != nil {
		glog.Errorln("Error getting size from SQL database: %v", err)
		return 0
	}
	qs.lru.Put(val+string(dir.Prefix()), size)
	return size
}
Пример #22
0
func (ts *TripleStore) GetNameFor(k graph.TSVal) string {
	if k == nil {
		glog.V(2).Infoln("k was nil")
		return ""
	}
	return ts.getValueData(k.([]byte)).Name
}
Пример #23
0
// GetCheckResult() is shared code between Check() and GetNextResult() -- calls next on the
// result iterator (a triple iterator based on the last checked value) and returns true if
// another match is made.
func (h *HasaIterator) GetCheckResult() bool {
	for {
		linkVal, ok := h.resultIt.Next()
		if !ok {
			break
		}
		if glog.V(4) {
			glog.V(4).Infoln("Triple is", h.ts.GetTriple(linkVal).ToString())
		}
		if h.primaryIt.Check(linkVal) {
			h.Last = h.ts.GetTripleDirection(linkVal, h.direction)
			return true
		}
	}
	return false
}
Пример #24
0
// NextContains() is shared code between Contains() and GetNextResult() -- calls next on the
// result iterator (a triple iterator based on the last checked value) and returns true if
// another match is made.
func (it *HasA) NextContains() bool {
	for {
		linkVal, ok := graph.Next(it.resultIt)
		if !ok {
			break
		}
		if glog.V(4) {
			glog.V(4).Infoln("Quad is", it.ts.Quad(linkVal))
		}
		if it.primaryIt.Contains(linkVal) {
			it.result = it.ts.TripleDirection(linkVal, it.dir)
			return true
		}
	}
	return false
}
Пример #25
0
func (s *Session) ExecInput(input string, c chan interface{}, _ int) {
	defer close(c)
	var mqlQuery interface{}
	err := json.Unmarshal([]byte(input), &mqlQuery)
	if err != nil {
		return
	}
	s.currentQuery = NewQuery(s)
	s.currentQuery.BuildIteratorTree(mqlQuery)
	if s.currentQuery.isError() {
		return
	}
	it, _ := s.currentQuery.it.Optimize()
	if glog.V(2) {
		b, err := json.MarshalIndent(it.Describe(), "", "  ")
		if err != nil {
			glog.Infof("failed to format description: %v", err)
		} else {
			glog.Infof("%s", b)
		}
	}
	for graph.Next(it) {
		tags := make(map[string]graph.Value)
		it.TagResults(tags)
		c <- tags
		for it.NextPath() == true {
			tags := make(map[string]graph.Value)
			it.TagResults(tags)
			c <- tags
		}
	}
}
Пример #26
0
// GetCheckResult() is shared code between Check() and GetNextResult() -- calls next on the
// result iterator (a triple iterator based on the last checked value) and returns true if
// another match is made.
func (it *HasA) GetCheckResult() bool {
	for {
		linkVal, ok := it.resultIt.Next()
		if !ok {
			break
		}
		if glog.V(4) {
			glog.V(4).Infoln("Triple is", it.ts.GetTriple(linkVal))
		}
		if it.primaryIt.Check(linkVal) {
			it.Last = it.ts.GetTripleDirection(linkVal, it.dir)
			return true
		}
	}
	return false
}
Пример #27
0
func (qs *QuadStore) NameOf(v graph.Value) string {
	if v == nil {
		glog.V(2).Info("NameOf was nil")
		return ""
	}
	return v.(string)
}
Пример #28
0
// NameOf ??
func (qs *QuadStore) NameOf(k graph.Value) string {
	if k == nil {
		glog.V(2).Info("k was nil")
		return ""
	}
	return qs.valueDataLMDB(k.(*Token)).Name
}
Пример #29
0
func (wk *worker) runIterator(it graph.Iterator) {
	if wk.wantShape() {
		iterator.OutputQueryShapeForIterator(it, wk.qs, wk.shape)
		return
	}
	it, _ = it.Optimize()
	if glog.V(2) {
		b, err := json.MarshalIndent(it.Describe(), "", "  ")
		if err != nil {
			glog.Infof("failed to format description: %v", err)
		} else {
			glog.Infof("%s", b)
		}
	}
	for {
		select {
		case <-wk.kill:
			return
		default:
		}
		if !graph.Next(it) {
			break
		}
		tags := make(map[string]graph.Value)
		it.TagResults(tags)
		if !wk.send(&Result{actualResults: tags}) {
			break
		}
		for it.NextPath() {
			select {
			case <-wk.kill:
				return
			default:
			}
			tags := make(map[string]graph.Value)
			it.TagResults(tags)
			if !wk.send(&Result{actualResults: tags}) {
				break
			}
		}
	}
	if glog.V(2) {
		bytes, _ := json.MarshalIndent(graph.DumpStats(it), "", "  ")
		glog.V(2).Infoln(string(bytes))
	}
	it.Close()
}
Пример #30
0
// Check a value against our internal iterator. In order to do this, we must first open a new
// iterator of "quads that have `val` in our direction", given to us by the quad store,
// and then Next() values out of that iterator and Contains() them against our subiterator.
func (it *HasA) Contains(val graph.Value) bool {
	graph.ContainsLogIn(it, val)
	it.runstats.Contains += 1
	if glog.V(4) {
		glog.V(4).Infoln("Id is", it.qs.NameOf(val))
	}
	// TODO(barakmich): Optimize this
	if it.resultIt != nil {
		it.resultIt.Close()
	}
	it.resultIt = it.qs.QuadIterator(it.dir, val)
	ok := it.NextContains()
	if it.err != nil {
		return false
	}
	return graph.ContainsLogOut(it, val, ok)
}