func influxTag(args []parse.Node) (parse.Tags, error) { st, err := influxql.ParseStatement(args[1].(*parse.StringNode).Text) if err != nil { return nil, err } s, ok := st.(*influxql.SelectStatement) if !ok { return nil, fmt.Errorf("influx: expected select statement") } t := make(parse.Tags, len(s.Dimensions)) for _, d := range s.Dimensions { if _, ok := d.Expr.(*influxql.Call); ok { continue } t[d.String()] = struct{}{} } return t, nil }
// influxQueryDuration adds time WHERE clauses to query for the given start and end durations. func influxQueryDuration(now time.Time, query, start, end string) (string, error) { sd, err := opentsdb.ParseDuration(start) if err != nil { return "", err } ed, err := opentsdb.ParseDuration(end) if end == "" { ed = 0 } else if err != nil { return "", err } st, err := influxql.ParseStatement(query) if err != nil { return "", err } s, ok := st.(*influxql.SelectStatement) if !ok { return "", fmt.Errorf("influx: expected select statement") } isTime := func(n influxql.Node) bool { v, ok := n.(*influxql.VarRef) if !ok { return false } s := strings.ToLower(v.Val) return s == "time" } influxql.WalkFunc(s.Condition, func(n influxql.Node) { b, ok := n.(*influxql.BinaryExpr) if !ok { return } if isTime(b.LHS) || isTime(b.RHS) { err = fmt.Errorf("influx query must not contain time in WHERE") } }) if err != nil { return "", err } //Add New BinaryExpr for time clause startExpr := &influxql.BinaryExpr{ Op: influxql.GTE, LHS: &influxql.VarRef{Val: "time"}, RHS: &influxql.TimeLiteral{Val: now.Add(time.Duration(-sd))}, } stopExpr := &influxql.BinaryExpr{ Op: influxql.LTE, LHS: &influxql.VarRef{Val: "time"}, RHS: &influxql.TimeLiteral{Val: now.Add(time.Duration(-ed))}, } if s.Condition != nil { s.Condition = &influxql.BinaryExpr{ Op: influxql.AND, LHS: s.Condition, RHS: &influxql.BinaryExpr{ Op: influxql.AND, LHS: startExpr, RHS: stopExpr, }, } } else { s.Condition = &influxql.BinaryExpr{ Op: influxql.AND, LHS: startExpr, RHS: stopExpr, } } return s.String(), nil }
// influxQueryDuration adds time WHERE clauses to query for the given start and end durations. func influxQueryDuration(now time.Time, query, start, end, groupByInterval string) (string, error) { sd, err := opentsdb.ParseDuration(start) if err != nil { return "", err } ed, err := opentsdb.ParseDuration(end) if end == "" { ed = 0 } else if err != nil { return "", err } st, err := influxql.ParseStatement(query) if err != nil { return "", err } s, ok := st.(*influxql.SelectStatement) if !ok { return "", fmt.Errorf("influx: expected select statement") } isTime := func(n influxql.Node) bool { v, ok := n.(*influxql.VarRef) if !ok { return false } s := strings.ToLower(v.Val) return s == "time" } influxql.WalkFunc(s.Condition, func(n influxql.Node) { b, ok := n.(*influxql.BinaryExpr) if !ok { return } if isTime(b.LHS) || isTime(b.RHS) { err = fmt.Errorf("influx query must not contain time in WHERE") } }) if err != nil { return "", err } //Add New BinaryExpr for time clause startExpr := &influxql.BinaryExpr{ Op: influxql.GTE, LHS: &influxql.VarRef{Val: "time"}, RHS: &influxql.TimeLiteral{Val: now.Add(time.Duration(-sd))}, } stopExpr := &influxql.BinaryExpr{ Op: influxql.LTE, LHS: &influxql.VarRef{Val: "time"}, RHS: &influxql.TimeLiteral{Val: now.Add(time.Duration(-ed))}, } if s.Condition != nil { s.Condition = &influxql.BinaryExpr{ Op: influxql.AND, LHS: s.Condition, RHS: &influxql.BinaryExpr{ Op: influxql.AND, LHS: startExpr, RHS: stopExpr, }, } } else { s.Condition = &influxql.BinaryExpr{ Op: influxql.AND, LHS: startExpr, RHS: stopExpr, } } // parse last argument if len(groupByInterval) > 0 { gbi, err := time.ParseDuration(groupByInterval) if err != nil { return "", err } s.Dimensions = append(s.Dimensions, &influxql.Dimension{Expr: &influxql.Call{ Name: "time", Args: []influxql.Expr{&influxql.DurationLiteral{Val: gbi}}, }, }) } // emtpy aggregate windows should be purged from the result // this default resembles the opentsdb results. if s.Fill == influxql.NullFill { s.Fill = influxql.NoFill s.FillValue = nil } return s.String(), nil }