Ejemplo n.º 1
0
// NewTagValuesIterator returns a new instance of TagValuesIterator.
func NewTagValuesIterator(sh *Shard, opt influxql.IteratorOptions) (influxql.Iterator, error) {
	if opt.Condition == nil {
		return nil, errors.New("a condition is required")
	}

	mms, ok, err := sh.index.measurementsByExpr(opt.Condition)
	if err != nil {
		return nil, err
	} else if !ok {
		mms = sh.index.Measurements()
		sort.Sort(mms)
	}

	filterExpr := influxql.CloneExpr(opt.Condition)
	filterExpr = influxql.RewriteExpr(filterExpr, func(e influxql.Expr) influxql.Expr {
		switch e := e.(type) {
		case *influxql.BinaryExpr:
			switch e.Op {
			case influxql.EQ, influxql.NEQ, influxql.EQREGEX, influxql.NEQREGEX:
				tag, ok := e.LHS.(*influxql.VarRef)
				if !ok || tag.Val == "name" || strings.HasPrefix(tag.Val, "_") {
					return nil
				}
			}
		}
		return e
	})

	var series []*Series
	keys := newStringSet()
	for _, mm := range mms {
		ss, ok, err := mm.tagKeysByExpr(opt.Condition)
		if err != nil {
			return nil, err
		} else if !ok {
			keys.add(mm.TagKeys()...)
		} else {
			keys = keys.union(ss)
		}

		ids, err := mm.seriesIDsAllOrByExpr(filterExpr)
		if err != nil {
			return nil, err
		}

		for _, id := range ids {
			series = append(series, mm.SeriesByID(id))
		}
	}

	return &tagValuesIterator{
		series: series,
		keys:   keys.list(),
		fields: opt.Aux,
	}, nil
}
Ejemplo n.º 2
0
func (s *Store) TagValues(database string, cond influxql.Expr) ([]TagValues, error) {
	if cond == nil {
		return nil, errors.New("a condition is required")
	}

	dbi := s.DatabaseIndex(database)
	if dbi == nil {
		return nil, nil
	}

	measurementExpr := influxql.CloneExpr(cond)
	measurementExpr = influxql.Reduce(influxql.RewriteExpr(measurementExpr, func(e influxql.Expr) influxql.Expr {
		switch e := e.(type) {
		case *influxql.BinaryExpr:
			switch e.Op {
			case influxql.EQ, influxql.NEQ, influxql.EQREGEX, influxql.NEQREGEX:
				tag, ok := e.LHS.(*influxql.VarRef)
				if !ok || tag.Val != "_name" {
					return nil
				}
			}
		}
		return e
	}), nil)

	mms, ok, err := dbi.MeasurementsByExpr(measurementExpr)
	if err != nil {
		return nil, err
	} else if !ok {
		mms = dbi.Measurements()
		sort.Sort(mms)
	}

	// If there are no measurements, return immediately.
	if len(mms) == 0 {
		return nil, nil
	}

	filterExpr := influxql.CloneExpr(cond)
	filterExpr = influxql.Reduce(influxql.RewriteExpr(filterExpr, func(e influxql.Expr) influxql.Expr {
		switch e := e.(type) {
		case *influxql.BinaryExpr:
			switch e.Op {
			case influxql.EQ, influxql.NEQ, influxql.EQREGEX, influxql.NEQREGEX:
				tag, ok := e.LHS.(*influxql.VarRef)
				if !ok || strings.HasPrefix(tag.Val, "_") {
					return nil
				}
			}
		}
		return e
	}), nil)

	tagValues := make([]TagValues, len(mms))
	for i, mm := range mms {
		tagValues[i].Measurement = mm.Name

		ids, err := mm.SeriesIDsAllOrByExpr(filterExpr)
		if err != nil {
			return nil, err
		}
		ss := mm.SeriesByIDSlice(ids)

		// Determine a list of keys from condition.
		keySet, ok, err := mm.TagKeysByExpr(cond)
		if err != nil {
			return nil, err
		}

		// Loop over all keys for each series.
		m := make(map[KeyValue]struct{}, len(ss))
		for _, series := range ss {
			for key, value := range series.Tags {
				if !ok {
					// nop
				} else if _, exists := keySet[key]; !exists {
					continue
				}
				m[KeyValue{key, value}] = struct{}{}
			}
		}

		// Return an empty slice if there are no key/value matches.
		if len(m) == 0 {
			continue
		}

		// Sort key/value set.
		a := make([]KeyValue, 0, len(m))
		for kv := range m {
			a = append(a, kv)
		}
		sort.Sort(KeyValues(a))
		tagValues[i].Values = a
	}

	return tagValues, nil
}
Ejemplo n.º 3
0
func (e *StatementExecutor) executeShowTagValues(stmt *influxql.SelectStatement, ctx *influxql.ExecutionContext, store LocalTSDBStore) error {
	if stmt.Condition == nil {
		return errors.New("a condition is required")
	}

	source := stmt.Sources[0].(*influxql.Measurement)
	index := store.DatabaseIndex(source.Database)
	if index == nil {
		ctx.Results <- &influxql.Result{StatementID: ctx.StatementID, Series: make([]*models.Row, 0)}
		return nil
	}

	measurementExpr := influxql.CloneExpr(stmt.Condition)
	measurementExpr = influxql.Reduce(influxql.RewriteExpr(measurementExpr, func(e influxql.Expr) influxql.Expr {
		switch e := e.(type) {
		case *influxql.BinaryExpr:
			switch e.Op {
			case influxql.EQ, influxql.NEQ, influxql.EQREGEX, influxql.NEQREGEX:
				tag, ok := e.LHS.(*influxql.VarRef)
				if !ok || tag.Val != "_name" {
					return nil
				}
			}
		}
		return e
	}), nil)

	mms, ok, err := index.MeasurementsByExpr(measurementExpr)
	if err != nil {
		return err
	} else if !ok {
		mms = index.Measurements()
		sort.Sort(mms)
	}

	// If there are no measurements, return immediately.
	if len(mms) == 0 {
		ctx.Results <- &influxql.Result{StatementID: ctx.StatementID, Series: make([]*models.Row, 0)}
		return nil
	}

	filterExpr := influxql.CloneExpr(stmt.Condition)
	filterExpr = influxql.Reduce(influxql.RewriteExpr(filterExpr, func(e influxql.Expr) influxql.Expr {
		switch e := e.(type) {
		case *influxql.BinaryExpr:
			switch e.Op {
			case influxql.EQ, influxql.NEQ, influxql.EQREGEX, influxql.NEQREGEX:
				tag, ok := e.LHS.(*influxql.VarRef)
				if !ok || strings.HasPrefix(tag.Val, "_") {
					return nil
				}
			}
		}
		return e
	}), nil)

	var emitted bool
	columns := stmt.ColumnNames()
	for _, mm := range mms {
		ids, err := mm.SeriesIDsAllOrByExpr(filterExpr)
		if err != nil {
			return err
		}
		ss := mm.SeriesByIDSlice(ids)

		// Determine a list of keys from condition.
		keySet, ok, err := mm.TagKeysByExpr(stmt.Condition)
		if err != nil {
			return err
		}

		// Loop over all keys for each series.
		m := make(map[keyValue]struct{}, len(ss))
		for _, series := range ss {
			for key, value := range series.Tags {
				if !ok {
					// nop
				} else if _, exists := keySet[key]; !exists {
					continue
				}
				m[keyValue{key, value}] = struct{}{}
			}
		}

		// Move to next series if no key/values match.
		if len(m) == 0 {
			continue
		}

		// Sort key/value set.
		a := make([]keyValue, 0, len(m))
		for kv := range m {
			a = append(a, kv)
		}
		sort.Sort(keyValues(a))

		// Convert to result values.
		slab := make([]interface{}, len(a)*2)
		values := make([][]interface{}, len(a))
		for i, elem := range a {
			slab[i*2], slab[i*2+1] = elem.key, elem.value
			values[i] = slab[i*2 : i*2+2]
		}

		// Send result to client.
		ctx.Results <- &influxql.Result{
			StatementID: ctx.StatementID,
			Series: []*models.Row{&models.Row{
				Name:    mm.Name,
				Columns: columns,
				Values:  values,
			}},
		}
		emitted = true
	}

	// Always emit at least one row.
	if !emitted {
		ctx.Results <- &influxql.Result{StatementID: ctx.StatementID, Series: make([]*models.Row, 0)}
	}

	return nil
}