// 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 }
// Ensure an Expr can be rewritten handling nils. func TestRewriteExpr(t *testing.T) { expr := MustParseExpr(`(time > 1 AND time < 10) OR foo = 2`) // Remove all time expressions. act := influxql.RewriteExpr(expr, func(e influxql.Expr) influxql.Expr { switch e := e.(type) { case *influxql.BinaryExpr: if lhs, ok := e.LHS.(*influxql.VarRef); ok && lhs.Val == "time" { return nil } } return e }) // Verify that everything is flipped. if act := act.String(); act != `foo = 2` { t.Fatalf("unexpected result: %s", act) } }