Remove restrictions on where derivative can be used entirely
This removes the previous restrictions that kept derivative as only capable of being used in a single field and only at the top level. This lets users determine how they want to use derivative more freely and opens up the possibility of also using math between derivatives. This may open up some problems when it comes to math between derivatives as timestamps may not match correctly. That is likely a problem related to any binary math to begin with though and can probably be ignored by the derivatives. I'm also not sure it makes sense to perform any math between a derivative and a difference or perform math between a derivative and a mean. Fixes #6118.pull/6375/head
parent
bfa225f149
commit
22a0505559
|
@ -1344,10 +1344,6 @@ func (s *SelectStatement) validate(tr targetRequirement) error {
|
|||
return err
|
||||
}
|
||||
|
||||
if err := s.validateDerivative(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -1719,47 +1715,6 @@ func (s *SelectStatement) validateCountDistinct() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (s *SelectStatement) validateDerivative() error {
|
||||
if !s.HasDerivative() {
|
||||
return nil
|
||||
}
|
||||
|
||||
// If a derivative is requested, it must be the only field in the query. We don't support
|
||||
// multiple fields in combination w/ derivaties yet.
|
||||
if len(s.Fields) != 1 {
|
||||
return fmt.Errorf("derivative cannot be used with other fields")
|
||||
}
|
||||
|
||||
aggr := s.FunctionCalls()
|
||||
if len(aggr) != 1 {
|
||||
return fmt.Errorf("derivative cannot be used with other fields")
|
||||
}
|
||||
|
||||
// Derivative requires two arguments
|
||||
derivativeCall := aggr[0]
|
||||
if len(derivativeCall.Args) == 0 {
|
||||
return fmt.Errorf("derivative requires a field argument")
|
||||
}
|
||||
|
||||
// First arg must be a field or aggr over a field e.g. (mean(field))
|
||||
_, callOk := derivativeCall.Args[0].(*Call)
|
||||
_, varOk := derivativeCall.Args[0].(*VarRef)
|
||||
|
||||
if !(callOk || varOk) {
|
||||
return fmt.Errorf("derivative requires a field argument")
|
||||
}
|
||||
|
||||
// If a duration arg is passed, make sure it's a duration
|
||||
if len(derivativeCall.Args) == 2 {
|
||||
// Second must be a duration .e.g (1h)
|
||||
if _, ok := derivativeCall.Args[1].(*DurationLiteral); !ok {
|
||||
return fmt.Errorf("derivative requires a duration argument")
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// GroupByInterval extracts the time interval, if specified.
|
||||
func (s *SelectStatement) GroupByInterval() (time.Duration, error) {
|
||||
// return if we've already pulled it out
|
||||
|
|
|
@ -197,6 +197,37 @@ func TestParser_ParseStatement(t *testing.T) {
|
|||
},
|
||||
},
|
||||
|
||||
{
|
||||
s: `SELECT derivative(field1, 1h) / derivative(field2, 1h) FROM myseries`,
|
||||
stmt: &influxql.SelectStatement{
|
||||
IsRawQuery: false,
|
||||
Fields: []*influxql.Field{
|
||||
{
|
||||
Expr: &influxql.BinaryExpr{
|
||||
LHS: &influxql.Call{
|
||||
Name: "derivative",
|
||||
Args: []influxql.Expr{
|
||||
&influxql.VarRef{Val: "field1"},
|
||||
&influxql.DurationLiteral{Val: time.Hour},
|
||||
},
|
||||
},
|
||||
RHS: &influxql.Call{
|
||||
Name: "derivative",
|
||||
Args: []influxql.Expr{
|
||||
&influxql.VarRef{Val: "field2"},
|
||||
&influxql.DurationLiteral{Val: time.Hour},
|
||||
},
|
||||
},
|
||||
Op: influxql.DIV,
|
||||
},
|
||||
},
|
||||
},
|
||||
Sources: []influxql.Source{
|
||||
&influxql.Measurement{Name: "myseries"},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
// difference
|
||||
{
|
||||
s: `SELECT difference(field1) FROM myseries;`,
|
||||
|
|
Loading…
Reference in New Issue