Exemple #1
0
// CreateIterator returns an iterator for the data in the shard.
func (s *Shard) CreateIterator(opt influxql.IteratorOptions) (influxql.Iterator, error) {
	if s.closed() {
		return nil, ErrEngineClosed
	}

	if influxql.Sources(opt.Sources).HasSystemSource() {
		return s.createSystemIterator(opt)
	}
	return s.engine.CreateIterator(opt)
}
Exemple #2
0
// createVarRefIterator creates an iterator for a variable reference.
func (e *Engine) createVarRefIterator(opt influxql.IteratorOptions) ([]influxql.Iterator, error) {
	ref, _ := opt.Expr.(*influxql.VarRef)

	var itrs []influxql.Iterator
	if err := func() error {
		mms := tsdb.Measurements(e.index.MeasurementsByName(influxql.Sources(opt.Sources).Names()))

		// Retrieve the maximum number of fields (without time).
		conditionFields := make([]string, len(influxql.ExprNames(opt.Condition)))

		for _, mm := range mms {
			// Determine tagsets for this measurement based on dimensions and filters.
			tagSets, err := mm.TagSets(opt.Dimensions, opt.Condition)
			if err != nil {
				return err
			}

			// Calculate tag sets and apply SLIMIT/SOFFSET.
			tagSets = influxql.LimitTagSets(tagSets, opt.SLimit, opt.SOffset)

			for _, t := range tagSets {
				for i, seriesKey := range t.SeriesKeys {
					fields := 0
					if t.Filters[i] != nil {
						// Retrieve non-time fields from this series filter and filter out tags.
						for _, f := range influxql.ExprNames(t.Filters[i]) {
							if mm.HasField(f) {
								conditionFields[fields] = f
								fields++
							}
						}
					}

					itr, err := e.createVarRefSeriesIterator(ref, mm, seriesKey, t, t.Filters[i], conditionFields[:fields], opt)
					if err != nil {
						return err
					} else if itr == nil {
						continue
					}
					itrs = append(itrs, itr)
				}
			}
		}
		return nil
	}(); err != nil {
		influxql.Iterators(itrs).Close()
		return nil, err
	}

	return itrs, nil
}
Exemple #3
0
func TestSources_HasSystemSource(t *testing.T) {
	sources := influxql.Sources([]influxql.Source{
		&influxql.Measurement{
			Name: "_measurements",
		},
	})

	ok := sources.HasSystemSource()
	if !ok {
		t.Errorf("expected to find a system source, found none")
	}

	sources = influxql.Sources([]influxql.Source{
		&influxql.Measurement{
			Name: "cpu",
		},
	})

	ok = sources.HasSystemSource()
	if ok {
		t.Errorf("expected to find no system source, found one")
	}
}
Exemple #4
0
func TestSources_Names(t *testing.T) {
	sources := influxql.Sources([]influxql.Source{
		&influxql.Measurement{
			Name: "cpu",
		},
		&influxql.Measurement{
			Name: "mem",
		},
	})

	names := sources.Names()
	if names[0] != "cpu" {
		t.Errorf("expected cpu, got %s", names[0])
	}
	if names[1] != "mem" {
		t.Errorf("expected mem, got %s", names[1])
	}
}
Exemple #5
0
// SeriesKeys returns a list of series in the shard.
func (s *Shard) SeriesKeys(opt influxql.IteratorOptions) (influxql.SeriesList, error) {
	if s.closed() {
		return nil, ErrEngineClosed
	}

	if influxql.Sources(opt.Sources).HasSystemSource() {
		// Only support a single system source.
		if len(opt.Sources) > 1 {
			return nil, errors.New("cannot select from multiple system sources")
		}

		// Meta queries don't need to know the series name and
		// always have a single series of strings.
		auxFields := make([]influxql.DataType, len(opt.Aux))
		for i := range auxFields {
			auxFields[i] = influxql.String
		}
		return []influxql.Series{{Aux: auxFields}}, nil
	}

	return s.engine.SeriesKeys(opt)
}
Exemple #6
0
func (e *Engine) SeriesKeys(opt influxql.IteratorOptions) (influxql.SeriesList, error) {
	seriesList := influxql.SeriesList{}
	mms := tsdb.Measurements(e.index.MeasurementsByName(influxql.Sources(opt.Sources).Names()))
	for _, mm := range mms {
		// Determine tagsets for this measurement based on dimensions and filters.
		tagSets, err := mm.TagSets(opt.Dimensions, opt.Condition)
		if err != nil {
			return nil, err
		}

		// Calculate tag sets and apply SLIMIT/SOFFSET.
		tagSets = influxql.LimitTagSets(tagSets, opt.SLimit, opt.SOffset)
		for _, t := range tagSets {
			tagMap := make(map[string]string)
			for k, v := range t.Tags {
				if v == "" {
					continue
				}
				tagMap[k] = v
			}
			tags := influxql.NewTags(tagMap)

			series := influxql.Series{
				Name: mm.Name,
				Tags: tags,
				Aux:  make([]influxql.DataType, len(opt.Aux)),
			}

			// Determine the aux field types.
			for _, seriesKey := range t.SeriesKeys {
				tags := influxql.NewTags(e.index.TagsForSeries(seriesKey))
				for i, field := range opt.Aux {
					typ := func() influxql.DataType {
						mf := e.measurementFields[mm.Name]
						if mf == nil {
							return influxql.Unknown
						}

						f := mf.Field(field)
						if f == nil {
							return influxql.Unknown
						}
						return f.Type
					}()

					if typ == influxql.Unknown {
						if v := tags.Value(field); v != "" {
							// All tags are strings.
							typ = influxql.String
						}
					}

					if typ != influxql.Unknown {
						if series.Aux[i] == influxql.Unknown || typ < series.Aux[i] {
							series.Aux[i] = typ
						}
					}
				}
			}
			seriesList = append(seriesList, series)
		}
	}
	return seriesList, nil
}