refactor(query/influxql): move transpiler spec tests to its own package
The package contains all of the transpiler specs and allows them to be put into different files instead of keeping all of the tests in the same file. They are all Go code so they are type checked rather than being loaded as JSON from disk. Additionally, to make it easier for a developer, the tests will report the exact file and line where the test was created. So rather than hunting for which file a test is located in, you will get something nice like the following: --- FAIL: TestTranspiler/SELECT_count(value)_FROM_db0..cpu_WHERE_host_=_'server01' (0.00s) testing.go:51: aggregates_with_condition.go:16: unexpected error: unimplemented function: "count" As can be seen, the test that failed can be found in the `aggregates_with_condition.go` file at line 16 which is where the test was created by the `AggregateTest` function and the relevant spec can be found in that same file.pull/10616/head
parent
55f0c59eca
commit
f694fa9637
|
@ -0,0 +1,160 @@
|
|||
package spectests
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"time"
|
||||
|
||||
"github.com/influxdata/influxql"
|
||||
"github.com/influxdata/platform/query"
|
||||
"github.com/influxdata/platform/query/ast"
|
||||
"github.com/influxdata/platform/query/execute"
|
||||
"github.com/influxdata/platform/query/functions"
|
||||
"github.com/influxdata/platform/query/semantic"
|
||||
)
|
||||
|
||||
var aggregateCreateFuncs = []func(config execute.AggregateConfig) query.OperationSpec{
|
||||
func(config execute.AggregateConfig) query.OperationSpec {
|
||||
return &functions.MeanOpSpec{AggregateConfig: config}
|
||||
},
|
||||
}
|
||||
|
||||
func AggregateTest(fn func(aggregate query.Operation) (string, *query.Spec)) Fixture {
|
||||
_, file, line, _ := runtime.Caller(1)
|
||||
fixture := &collection{
|
||||
file: filepath.Base(file),
|
||||
line: line,
|
||||
}
|
||||
|
||||
for _, aggregateSpecFn := range aggregateCreateFuncs {
|
||||
spec := aggregateSpecFn(execute.AggregateConfig{
|
||||
TimeSrc: execute.DefaultStartColLabel,
|
||||
TimeDst: execute.DefaultTimeColLabel,
|
||||
Columns: []string{execute.DefaultValueColLabel},
|
||||
})
|
||||
op := query.Operation{
|
||||
ID: query.OperationID(fmt.Sprintf("%s0", spec.Kind())),
|
||||
Spec: spec,
|
||||
}
|
||||
|
||||
fixture.Add(fn(op))
|
||||
}
|
||||
return fixture
|
||||
}
|
||||
|
||||
func init() {
|
||||
RegisterFixture(
|
||||
AggregateTest(func(aggregate query.Operation) (stmt string, spec *query.Spec) {
|
||||
return fmt.Sprintf(`SELECT %s(value) FROM db0..cpu`, aggregate.Spec.Kind()),
|
||||
&query.Spec{
|
||||
Operations: []*query.Operation{
|
||||
{
|
||||
ID: "from0",
|
||||
Spec: &functions.FromOpSpec{
|
||||
Bucket: "db0/autogen",
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "range0",
|
||||
Spec: &functions.RangeOpSpec{
|
||||
Start: query.Time{Absolute: time.Unix(0, influxql.MinTime)},
|
||||
Stop: query.Time{Absolute: time.Unix(0, influxql.MaxTime)},
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "filter0",
|
||||
Spec: &functions.FilterOpSpec{
|
||||
Fn: &semantic.FunctionExpression{
|
||||
Params: []*semantic.FunctionParam{
|
||||
{Key: &semantic.Identifier{Name: "r"}},
|
||||
},
|
||||
Body: &semantic.LogicalExpression{
|
||||
Operator: ast.AndOperator,
|
||||
Left: &semantic.BinaryExpression{
|
||||
Operator: ast.EqualOperator,
|
||||
Left: &semantic.MemberExpression{
|
||||
Object: &semantic.IdentifierExpression{
|
||||
Name: "r",
|
||||
},
|
||||
Property: "_measurement",
|
||||
},
|
||||
Right: &semantic.StringLiteral{
|
||||
Value: "cpu",
|
||||
},
|
||||
},
|
||||
Right: &semantic.BinaryExpression{
|
||||
Operator: ast.EqualOperator,
|
||||
Left: &semantic.MemberExpression{
|
||||
Object: &semantic.IdentifierExpression{
|
||||
Name: "r",
|
||||
},
|
||||
Property: "_field",
|
||||
},
|
||||
Right: &semantic.StringLiteral{
|
||||
Value: "value",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "group0",
|
||||
Spec: &functions.GroupOpSpec{
|
||||
By: []string{"_measurement"},
|
||||
},
|
||||
},
|
||||
&aggregate,
|
||||
{
|
||||
ID: "map0",
|
||||
Spec: &functions.MapOpSpec{
|
||||
Fn: &semantic.FunctionExpression{
|
||||
Params: []*semantic.FunctionParam{{
|
||||
Key: &semantic.Identifier{Name: "r"},
|
||||
}},
|
||||
Body: &semantic.ObjectExpression{
|
||||
Properties: []*semantic.Property{
|
||||
{
|
||||
Key: &semantic.Identifier{Name: "_time"},
|
||||
Value: &semantic.MemberExpression{
|
||||
Object: &semantic.IdentifierExpression{
|
||||
Name: "r",
|
||||
},
|
||||
Property: "_time",
|
||||
},
|
||||
},
|
||||
{
|
||||
Key: &semantic.Identifier{Name: string(aggregate.Spec.Kind())},
|
||||
Value: &semantic.MemberExpression{
|
||||
Object: &semantic.IdentifierExpression{
|
||||
Name: "r",
|
||||
},
|
||||
Property: "_value",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
MergeKey: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "yield0",
|
||||
Spec: &functions.YieldOpSpec{
|
||||
Name: "0",
|
||||
},
|
||||
},
|
||||
},
|
||||
Edges: []query.Edge{
|
||||
{Parent: "from0", Child: "range0"},
|
||||
{Parent: "range0", Child: "filter0"},
|
||||
{Parent: "filter0", Child: "group0"},
|
||||
{Parent: "group0", Child: aggregate.ID},
|
||||
{Parent: aggregate.ID, Child: "map0"},
|
||||
{Parent: "map0", Child: "yield0"},
|
||||
},
|
||||
}
|
||||
}),
|
||||
)
|
||||
}
|
|
@ -0,0 +1,151 @@
|
|||
package spectests
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/influxdata/influxql"
|
||||
"github.com/influxdata/platform/query"
|
||||
"github.com/influxdata/platform/query/ast"
|
||||
"github.com/influxdata/platform/query/functions"
|
||||
"github.com/influxdata/platform/query/semantic"
|
||||
)
|
||||
|
||||
func init() {
|
||||
RegisterFixture(
|
||||
AggregateTest(func(aggregate query.Operation) (stmt string, spec *query.Spec) {
|
||||
return fmt.Sprintf(`SELECT %s(value) FROM db0..cpu WHERE host = 'server01'`, aggregate.Spec.Kind()),
|
||||
&query.Spec{
|
||||
Operations: []*query.Operation{
|
||||
{
|
||||
ID: "from0",
|
||||
Spec: &functions.FromOpSpec{
|
||||
Bucket: "db0/autogen",
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "range0",
|
||||
Spec: &functions.RangeOpSpec{
|
||||
Start: query.Time{Absolute: time.Unix(0, influxql.MinTime)},
|
||||
Stop: query.Time{Absolute: time.Unix(0, influxql.MaxTime)},
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "filter0",
|
||||
Spec: &functions.FilterOpSpec{
|
||||
Fn: &semantic.FunctionExpression{
|
||||
Params: []*semantic.FunctionParam{
|
||||
{Key: &semantic.Identifier{Name: "r"}},
|
||||
},
|
||||
Body: &semantic.LogicalExpression{
|
||||
Operator: ast.AndOperator,
|
||||
Left: &semantic.BinaryExpression{
|
||||
Operator: ast.EqualOperator,
|
||||
Left: &semantic.MemberExpression{
|
||||
Object: &semantic.IdentifierExpression{
|
||||
Name: "r",
|
||||
},
|
||||
Property: "_measurement",
|
||||
},
|
||||
Right: &semantic.StringLiteral{
|
||||
Value: "cpu",
|
||||
},
|
||||
},
|
||||
Right: &semantic.BinaryExpression{
|
||||
Operator: ast.EqualOperator,
|
||||
Left: &semantic.MemberExpression{
|
||||
Object: &semantic.IdentifierExpression{
|
||||
Name: "r",
|
||||
},
|
||||
Property: "_field",
|
||||
},
|
||||
Right: &semantic.StringLiteral{
|
||||
Value: "value",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "filter1",
|
||||
Spec: &functions.FilterOpSpec{
|
||||
Fn: &semantic.FunctionExpression{
|
||||
Params: []*semantic.FunctionParam{
|
||||
{Key: &semantic.Identifier{Name: "r"}},
|
||||
},
|
||||
Body: &semantic.BinaryExpression{
|
||||
Operator: ast.EqualOperator,
|
||||
Left: &semantic.MemberExpression{
|
||||
Object: &semantic.IdentifierExpression{
|
||||
Name: "r",
|
||||
},
|
||||
Property: "host",
|
||||
},
|
||||
Right: &semantic.StringLiteral{
|
||||
Value: "server01",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "group0",
|
||||
Spec: &functions.GroupOpSpec{
|
||||
By: []string{"_measurement"},
|
||||
},
|
||||
},
|
||||
&aggregate,
|
||||
{
|
||||
ID: "map0",
|
||||
Spec: &functions.MapOpSpec{
|
||||
Fn: &semantic.FunctionExpression{
|
||||
Params: []*semantic.FunctionParam{{
|
||||
Key: &semantic.Identifier{Name: "r"},
|
||||
}},
|
||||
Body: &semantic.ObjectExpression{
|
||||
Properties: []*semantic.Property{
|
||||
{
|
||||
Key: &semantic.Identifier{Name: "_time"},
|
||||
Value: &semantic.MemberExpression{
|
||||
Object: &semantic.IdentifierExpression{
|
||||
Name: "r",
|
||||
},
|
||||
Property: "_time",
|
||||
},
|
||||
},
|
||||
{
|
||||
Key: &semantic.Identifier{Name: string(aggregate.Spec.Kind())},
|
||||
Value: &semantic.MemberExpression{
|
||||
Object: &semantic.IdentifierExpression{
|
||||
Name: "r",
|
||||
},
|
||||
Property: "_value",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
MergeKey: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "yield0",
|
||||
Spec: &functions.YieldOpSpec{
|
||||
Name: "0",
|
||||
},
|
||||
},
|
||||
},
|
||||
Edges: []query.Edge{
|
||||
{Parent: "from0", Child: "range0"},
|
||||
{Parent: "range0", Child: "filter0"},
|
||||
{Parent: "filter0", Child: "filter1"},
|
||||
{Parent: "filter1", Child: "group0"},
|
||||
{Parent: "group0", Child: aggregate.ID},
|
||||
{Parent: aggregate.ID, Child: "map0"},
|
||||
{Parent: "map0", Child: "yield0"},
|
||||
},
|
||||
}
|
||||
}),
|
||||
)
|
||||
}
|
|
@ -0,0 +1,128 @@
|
|||
package spectests
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/influxdata/influxql"
|
||||
"github.com/influxdata/platform/query"
|
||||
"github.com/influxdata/platform/query/ast"
|
||||
"github.com/influxdata/platform/query/functions"
|
||||
"github.com/influxdata/platform/query/semantic"
|
||||
)
|
||||
|
||||
func init() {
|
||||
RegisterFixture(
|
||||
AggregateTest(func(aggregate query.Operation) (stmt string, spec *query.Spec) {
|
||||
return fmt.Sprintf(`SELECT %s(value) FROM db0..cpu GROUP BY host`, aggregate.Spec.Kind()),
|
||||
&query.Spec{
|
||||
Operations: []*query.Operation{
|
||||
{
|
||||
ID: "from0",
|
||||
Spec: &functions.FromOpSpec{
|
||||
Bucket: "db0/autogen",
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "range0",
|
||||
Spec: &functions.RangeOpSpec{
|
||||
Start: query.Time{Absolute: time.Unix(0, influxql.MinTime)},
|
||||
Stop: query.Time{Absolute: time.Unix(0, influxql.MaxTime)},
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "filter0",
|
||||
Spec: &functions.FilterOpSpec{
|
||||
Fn: &semantic.FunctionExpression{
|
||||
Params: []*semantic.FunctionParam{
|
||||
{Key: &semantic.Identifier{Name: "r"}},
|
||||
},
|
||||
Body: &semantic.LogicalExpression{
|
||||
Operator: ast.AndOperator,
|
||||
Left: &semantic.BinaryExpression{
|
||||
Operator: ast.EqualOperator,
|
||||
Left: &semantic.MemberExpression{
|
||||
Object: &semantic.IdentifierExpression{
|
||||
Name: "r",
|
||||
},
|
||||
Property: "_measurement",
|
||||
},
|
||||
Right: &semantic.StringLiteral{
|
||||
Value: "cpu",
|
||||
},
|
||||
},
|
||||
Right: &semantic.BinaryExpression{
|
||||
Operator: ast.EqualOperator,
|
||||
Left: &semantic.MemberExpression{
|
||||
Object: &semantic.IdentifierExpression{
|
||||
Name: "r",
|
||||
},
|
||||
Property: "_field",
|
||||
},
|
||||
Right: &semantic.StringLiteral{
|
||||
Value: "value",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "group0",
|
||||
Spec: &functions.GroupOpSpec{
|
||||
By: []string{"_measurement", "host"},
|
||||
},
|
||||
},
|
||||
&aggregate,
|
||||
{
|
||||
ID: "map0",
|
||||
Spec: &functions.MapOpSpec{
|
||||
Fn: &semantic.FunctionExpression{
|
||||
Params: []*semantic.FunctionParam{{
|
||||
Key: &semantic.Identifier{Name: "r"},
|
||||
}},
|
||||
Body: &semantic.ObjectExpression{
|
||||
Properties: []*semantic.Property{
|
||||
{
|
||||
Key: &semantic.Identifier{Name: "_time"},
|
||||
Value: &semantic.MemberExpression{
|
||||
Object: &semantic.IdentifierExpression{
|
||||
Name: "r",
|
||||
},
|
||||
Property: "_time",
|
||||
},
|
||||
},
|
||||
{
|
||||
Key: &semantic.Identifier{Name: string(aggregate.Spec.Kind())},
|
||||
Value: &semantic.MemberExpression{
|
||||
Object: &semantic.IdentifierExpression{
|
||||
Name: "r",
|
||||
},
|
||||
Property: "_value",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
MergeKey: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "yield0",
|
||||
Spec: &functions.YieldOpSpec{
|
||||
Name: "0",
|
||||
},
|
||||
},
|
||||
},
|
||||
Edges: []query.Edge{
|
||||
{Parent: "from0", Child: "range0"},
|
||||
{Parent: "range0", Child: "filter0"},
|
||||
{Parent: "filter0", Child: "group0"},
|
||||
{Parent: "group0", Child: aggregate.ID},
|
||||
{Parent: aggregate.ID, Child: "map0"},
|
||||
{Parent: "map0", Child: "yield0"},
|
||||
},
|
||||
}
|
||||
}),
|
||||
)
|
||||
}
|
|
@ -0,0 +1,153 @@
|
|||
package spectests
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"time"
|
||||
|
||||
"github.com/influxdata/platform/query"
|
||||
"github.com/influxdata/platform/query/ast"
|
||||
"github.com/influxdata/platform/query/execute"
|
||||
"github.com/influxdata/platform/query/functions"
|
||||
"github.com/influxdata/platform/query/semantic"
|
||||
)
|
||||
|
||||
func init() {
|
||||
RegisterFixture(
|
||||
AggregateTest(func(aggregate query.Operation) (stmt string, spec *query.Spec) {
|
||||
return fmt.Sprintf(`SELECT %s(value) FROM db0..cpu WHERE time >= now() - 10m GROUP BY time(1m)`, aggregate.Spec.Kind()),
|
||||
&query.Spec{
|
||||
Operations: []*query.Operation{
|
||||
{
|
||||
ID: "from0",
|
||||
Spec: &functions.FromOpSpec{
|
||||
Bucket: "db0/autogen",
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "range0",
|
||||
Spec: &functions.RangeOpSpec{
|
||||
Start: query.Time{Absolute: Now().Add(-10 * time.Minute)},
|
||||
Stop: query.Time{Absolute: Now()},
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "filter0",
|
||||
Spec: &functions.FilterOpSpec{
|
||||
Fn: &semantic.FunctionExpression{
|
||||
Params: []*semantic.FunctionParam{
|
||||
{Key: &semantic.Identifier{Name: "r"}},
|
||||
},
|
||||
Body: &semantic.LogicalExpression{
|
||||
Operator: ast.AndOperator,
|
||||
Left: &semantic.BinaryExpression{
|
||||
Operator: ast.EqualOperator,
|
||||
Left: &semantic.MemberExpression{
|
||||
Object: &semantic.IdentifierExpression{
|
||||
Name: "r",
|
||||
},
|
||||
Property: "_measurement",
|
||||
},
|
||||
Right: &semantic.StringLiteral{
|
||||
Value: "cpu",
|
||||
},
|
||||
},
|
||||
Right: &semantic.BinaryExpression{
|
||||
Operator: ast.EqualOperator,
|
||||
Left: &semantic.MemberExpression{
|
||||
Object: &semantic.IdentifierExpression{
|
||||
Name: "r",
|
||||
},
|
||||
Property: "_field",
|
||||
},
|
||||
Right: &semantic.StringLiteral{
|
||||
Value: "value",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "group0",
|
||||
Spec: &functions.GroupOpSpec{
|
||||
By: []string{"_measurement"},
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "window0",
|
||||
Spec: &functions.WindowOpSpec{
|
||||
Every: query.Duration(time.Minute),
|
||||
Period: query.Duration(time.Minute),
|
||||
IgnoreGlobalBounds: true,
|
||||
TimeCol: execute.DefaultTimeColLabel,
|
||||
StartColLabel: execute.DefaultStartColLabel,
|
||||
StopColLabel: execute.DefaultStopColLabel,
|
||||
},
|
||||
},
|
||||
&aggregate,
|
||||
{
|
||||
ID: "window1",
|
||||
Spec: &functions.WindowOpSpec{
|
||||
Every: query.Duration(math.MaxInt64),
|
||||
Period: query.Duration(math.MaxInt64),
|
||||
IgnoreGlobalBounds: true,
|
||||
TimeCol: execute.DefaultTimeColLabel,
|
||||
StartColLabel: execute.DefaultStartColLabel,
|
||||
StopColLabel: execute.DefaultStopColLabel,
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "map0",
|
||||
Spec: &functions.MapOpSpec{
|
||||
Fn: &semantic.FunctionExpression{
|
||||
Params: []*semantic.FunctionParam{{
|
||||
Key: &semantic.Identifier{Name: "r"},
|
||||
}},
|
||||
Body: &semantic.ObjectExpression{
|
||||
Properties: []*semantic.Property{
|
||||
{
|
||||
Key: &semantic.Identifier{Name: "_time"},
|
||||
Value: &semantic.MemberExpression{
|
||||
Object: &semantic.IdentifierExpression{
|
||||
Name: "r",
|
||||
},
|
||||
Property: "_time",
|
||||
},
|
||||
},
|
||||
{
|
||||
Key: &semantic.Identifier{Name: string(aggregate.Spec.Kind())},
|
||||
Value: &semantic.MemberExpression{
|
||||
Object: &semantic.IdentifierExpression{
|
||||
Name: "r",
|
||||
},
|
||||
Property: "_value",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
MergeKey: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "yield0",
|
||||
Spec: &functions.YieldOpSpec{
|
||||
Name: "0",
|
||||
},
|
||||
},
|
||||
},
|
||||
Edges: []query.Edge{
|
||||
{Parent: "from0", Child: "range0"},
|
||||
{Parent: "range0", Child: "filter0"},
|
||||
{Parent: "filter0", Child: "group0"},
|
||||
{Parent: "group0", Child: "window0"},
|
||||
{Parent: "window0", Child: aggregate.ID},
|
||||
{Parent: aggregate.ID, Child: "window1"},
|
||||
{Parent: "window1", Child: "map0"},
|
||||
{Parent: "map0", Child: "yield0"},
|
||||
},
|
||||
}
|
||||
}),
|
||||
)
|
||||
}
|
|
@ -0,0 +1,225 @@
|
|||
package spectests
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/influxdata/influxql"
|
||||
"github.com/influxdata/platform/query"
|
||||
"github.com/influxdata/platform/query/ast"
|
||||
"github.com/influxdata/platform/query/functions"
|
||||
"github.com/influxdata/platform/query/semantic"
|
||||
)
|
||||
|
||||
func init() {
|
||||
RegisterFixture(
|
||||
NewFixture(
|
||||
`SELECT a + b FROM db0..cpu`,
|
||||
&query.Spec{
|
||||
Operations: []*query.Operation{
|
||||
{
|
||||
ID: "from0",
|
||||
Spec: &functions.FromOpSpec{
|
||||
Bucket: "db0/autogen",
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "range0",
|
||||
Spec: &functions.RangeOpSpec{
|
||||
Start: query.Time{Absolute: time.Unix(0, influxql.MinTime)},
|
||||
Stop: query.Time{Absolute: time.Unix(0, influxql.MaxTime)},
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "filter0",
|
||||
Spec: &functions.FilterOpSpec{
|
||||
Fn: &semantic.FunctionExpression{
|
||||
Params: []*semantic.FunctionParam{
|
||||
{Key: &semantic.Identifier{Name: "r"}},
|
||||
},
|
||||
Body: &semantic.LogicalExpression{
|
||||
Operator: ast.AndOperator,
|
||||
Left: &semantic.BinaryExpression{
|
||||
Operator: ast.EqualOperator,
|
||||
Left: &semantic.MemberExpression{
|
||||
Object: &semantic.IdentifierExpression{
|
||||
Name: "r",
|
||||
},
|
||||
Property: "_measurement",
|
||||
},
|
||||
Right: &semantic.StringLiteral{
|
||||
Value: "cpu",
|
||||
},
|
||||
},
|
||||
Right: &semantic.BinaryExpression{
|
||||
Operator: ast.EqualOperator,
|
||||
Left: &semantic.MemberExpression{
|
||||
Object: &semantic.IdentifierExpression{
|
||||
Name: "r",
|
||||
},
|
||||
Property: "_field",
|
||||
},
|
||||
Right: &semantic.StringLiteral{
|
||||
Value: "a",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "from1",
|
||||
Spec: &functions.FromOpSpec{
|
||||
Bucket: "db0/autogen",
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "range1",
|
||||
Spec: &functions.RangeOpSpec{
|
||||
Start: query.Time{Absolute: time.Unix(0, influxql.MinTime)},
|
||||
Stop: query.Time{Absolute: time.Unix(0, influxql.MaxTime)},
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "filter1",
|
||||
Spec: &functions.FilterOpSpec{
|
||||
Fn: &semantic.FunctionExpression{
|
||||
Params: []*semantic.FunctionParam{
|
||||
{Key: &semantic.Identifier{Name: "r"}},
|
||||
},
|
||||
Body: &semantic.LogicalExpression{
|
||||
Operator: ast.AndOperator,
|
||||
Left: &semantic.BinaryExpression{
|
||||
Operator: ast.EqualOperator,
|
||||
Left: &semantic.MemberExpression{
|
||||
Object: &semantic.IdentifierExpression{
|
||||
Name: "r",
|
||||
},
|
||||
Property: "_measurement",
|
||||
},
|
||||
Right: &semantic.StringLiteral{
|
||||
Value: "cpu",
|
||||
},
|
||||
},
|
||||
Right: &semantic.BinaryExpression{
|
||||
Operator: ast.EqualOperator,
|
||||
Left: &semantic.MemberExpression{
|
||||
Object: &semantic.IdentifierExpression{
|
||||
Name: "r",
|
||||
},
|
||||
Property: "_field",
|
||||
},
|
||||
Right: &semantic.StringLiteral{
|
||||
Value: "b",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "join0",
|
||||
Spec: &functions.JoinOpSpec{
|
||||
On: []string{"_measurement"},
|
||||
Fn: &semantic.FunctionExpression{
|
||||
Params: []*semantic.FunctionParam{{
|
||||
Key: &semantic.Identifier{Name: "tables"},
|
||||
}},
|
||||
Body: &semantic.ObjectExpression{
|
||||
Properties: []*semantic.Property{
|
||||
{
|
||||
Key: &semantic.Identifier{Name: "val0"},
|
||||
Value: &semantic.MemberExpression{
|
||||
Object: &semantic.IdentifierExpression{
|
||||
Name: "tables",
|
||||
},
|
||||
Property: "t0",
|
||||
},
|
||||
},
|
||||
{
|
||||
Key: &semantic.Identifier{Name: "val1"},
|
||||
Value: &semantic.MemberExpression{
|
||||
Object: &semantic.IdentifierExpression{
|
||||
Name: "tables",
|
||||
},
|
||||
Property: "t1",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
TableNames: map[query.OperationID]string{
|
||||
"filter0": "t0",
|
||||
"filter1": "t1",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "group0",
|
||||
Spec: &functions.GroupOpSpec{
|
||||
By: []string{"_measurement"},
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "map0",
|
||||
Spec: &functions.MapOpSpec{
|
||||
Fn: &semantic.FunctionExpression{
|
||||
Params: []*semantic.FunctionParam{{
|
||||
Key: &semantic.Identifier{Name: "r"},
|
||||
}},
|
||||
Body: &semantic.ObjectExpression{
|
||||
Properties: []*semantic.Property{
|
||||
{
|
||||
Key: &semantic.Identifier{Name: "_time"},
|
||||
Value: &semantic.MemberExpression{
|
||||
Object: &semantic.IdentifierExpression{
|
||||
Name: "r",
|
||||
},
|
||||
Property: "_time",
|
||||
},
|
||||
},
|
||||
{
|
||||
Key: &semantic.Identifier{Name: "a_b"},
|
||||
Value: &semantic.BinaryExpression{
|
||||
Operator: ast.AdditionOperator,
|
||||
Left: &semantic.MemberExpression{
|
||||
Object: &semantic.IdentifierExpression{
|
||||
Name: "r",
|
||||
},
|
||||
Property: "val0",
|
||||
},
|
||||
Right: &semantic.MemberExpression{
|
||||
Object: &semantic.IdentifierExpression{
|
||||
Name: "r",
|
||||
},
|
||||
Property: "val1",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
MergeKey: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "yield0",
|
||||
Spec: &functions.YieldOpSpec{
|
||||
Name: "0",
|
||||
},
|
||||
},
|
||||
},
|
||||
Edges: []query.Edge{
|
||||
{Parent: "from0", Child: "range0"},
|
||||
{Parent: "range0", Child: "filter0"},
|
||||
{Parent: "from1", Child: "range1"},
|
||||
{Parent: "range1", Child: "filter1"},
|
||||
{Parent: "filter0", Child: "join0"},
|
||||
{Parent: "filter1", Child: "join0"},
|
||||
{Parent: "join0", Child: "group0"},
|
||||
{Parent: "group0", Child: "map0"},
|
||||
{Parent: "map0", Child: "yield0"},
|
||||
},
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
|
@ -0,0 +1,253 @@
|
|||
package spectests
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/influxdata/influxql"
|
||||
"github.com/influxdata/platform/query"
|
||||
"github.com/influxdata/platform/query/ast"
|
||||
"github.com/influxdata/platform/query/execute"
|
||||
"github.com/influxdata/platform/query/functions"
|
||||
"github.com/influxdata/platform/query/semantic"
|
||||
)
|
||||
|
||||
func init() {
|
||||
RegisterFixture(
|
||||
NewFixture(
|
||||
`SELECT mean(value), max(value) FROM db0..cpu`,
|
||||
&query.Spec{
|
||||
Operations: []*query.Operation{
|
||||
{
|
||||
ID: "from0",
|
||||
Spec: &functions.FromOpSpec{
|
||||
Bucket: "db0/autogen",
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "range0",
|
||||
Spec: &functions.RangeOpSpec{
|
||||
Start: query.Time{Absolute: time.Unix(0, influxql.MinTime)},
|
||||
Stop: query.Time{Absolute: time.Unix(0, influxql.MaxTime)},
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "filter0",
|
||||
Spec: &functions.FilterOpSpec{
|
||||
Fn: &semantic.FunctionExpression{
|
||||
Params: []*semantic.FunctionParam{
|
||||
{Key: &semantic.Identifier{Name: "r"}},
|
||||
},
|
||||
Body: &semantic.LogicalExpression{
|
||||
Operator: ast.AndOperator,
|
||||
Left: &semantic.BinaryExpression{
|
||||
Operator: ast.EqualOperator,
|
||||
Left: &semantic.MemberExpression{
|
||||
Object: &semantic.IdentifierExpression{
|
||||
Name: "r",
|
||||
},
|
||||
Property: "_measurement",
|
||||
},
|
||||
Right: &semantic.StringLiteral{
|
||||
Value: "cpu",
|
||||
},
|
||||
},
|
||||
Right: &semantic.BinaryExpression{
|
||||
Operator: ast.EqualOperator,
|
||||
Left: &semantic.MemberExpression{
|
||||
Object: &semantic.IdentifierExpression{
|
||||
Name: "r",
|
||||
},
|
||||
Property: "_field",
|
||||
},
|
||||
Right: &semantic.StringLiteral{
|
||||
Value: "value",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "group0",
|
||||
Spec: &functions.GroupOpSpec{
|
||||
By: []string{"_measurement"},
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "mean0",
|
||||
Spec: &functions.MeanOpSpec{
|
||||
AggregateConfig: execute.AggregateConfig{
|
||||
TimeSrc: execute.DefaultStartColLabel,
|
||||
TimeDst: execute.DefaultTimeColLabel,
|
||||
Columns: []string{execute.DefaultValueColLabel},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "from1",
|
||||
Spec: &functions.FromOpSpec{
|
||||
Bucket: "db0/autogen",
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "range1",
|
||||
Spec: &functions.RangeOpSpec{
|
||||
Start: query.Time{Absolute: time.Unix(0, influxql.MinTime)},
|
||||
Stop: query.Time{Absolute: time.Unix(0, influxql.MaxTime)},
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "filter1",
|
||||
Spec: &functions.FilterOpSpec{
|
||||
Fn: &semantic.FunctionExpression{
|
||||
Params: []*semantic.FunctionParam{
|
||||
{Key: &semantic.Identifier{Name: "r"}},
|
||||
},
|
||||
Body: &semantic.LogicalExpression{
|
||||
Operator: ast.AndOperator,
|
||||
Left: &semantic.BinaryExpression{
|
||||
Operator: ast.EqualOperator,
|
||||
Left: &semantic.MemberExpression{
|
||||
Object: &semantic.IdentifierExpression{
|
||||
Name: "r",
|
||||
},
|
||||
Property: "_measurement",
|
||||
},
|
||||
Right: &semantic.StringLiteral{
|
||||
Value: "cpu",
|
||||
},
|
||||
},
|
||||
Right: &semantic.BinaryExpression{
|
||||
Operator: ast.EqualOperator,
|
||||
Left: &semantic.MemberExpression{
|
||||
Object: &semantic.IdentifierExpression{
|
||||
Name: "r",
|
||||
},
|
||||
Property: "_field",
|
||||
},
|
||||
Right: &semantic.StringLiteral{
|
||||
Value: "value",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "group1",
|
||||
Spec: &functions.GroupOpSpec{
|
||||
By: []string{"_measurement"},
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "max0",
|
||||
Spec: &functions.MaxOpSpec{
|
||||
SelectorConfig: execute.SelectorConfig{
|
||||
Column: execute.DefaultValueColLabel,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "join0",
|
||||
Spec: &functions.JoinOpSpec{
|
||||
On: []string{"_measurement"},
|
||||
Fn: &semantic.FunctionExpression{
|
||||
Params: []*semantic.FunctionParam{{
|
||||
Key: &semantic.Identifier{Name: "tables"},
|
||||
}},
|
||||
Body: &semantic.ObjectExpression{
|
||||
Properties: []*semantic.Property{
|
||||
{
|
||||
Key: &semantic.Identifier{Name: "val0"},
|
||||
Value: &semantic.MemberExpression{
|
||||
Object: &semantic.IdentifierExpression{
|
||||
Name: "tables",
|
||||
},
|
||||
Property: "t0",
|
||||
},
|
||||
},
|
||||
{
|
||||
Key: &semantic.Identifier{Name: "val1"},
|
||||
Value: &semantic.MemberExpression{
|
||||
Object: &semantic.IdentifierExpression{
|
||||
Name: "tables",
|
||||
},
|
||||
Property: "t1",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
TableNames: map[query.OperationID]string{
|
||||
"mean0": "t0",
|
||||
"max0": "t1",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "map0",
|
||||
Spec: &functions.MapOpSpec{
|
||||
Fn: &semantic.FunctionExpression{
|
||||
Params: []*semantic.FunctionParam{{
|
||||
Key: &semantic.Identifier{Name: "r"},
|
||||
}},
|
||||
Body: &semantic.ObjectExpression{
|
||||
Properties: []*semantic.Property{
|
||||
{
|
||||
Key: &semantic.Identifier{Name: "_time"},
|
||||
Value: &semantic.MemberExpression{
|
||||
Object: &semantic.IdentifierExpression{
|
||||
Name: "r",
|
||||
},
|
||||
Property: "_time",
|
||||
},
|
||||
},
|
||||
{
|
||||
Key: &semantic.Identifier{Name: "mean"},
|
||||
Value: &semantic.MemberExpression{
|
||||
Object: &semantic.IdentifierExpression{
|
||||
Name: "r",
|
||||
},
|
||||
Property: "val0",
|
||||
},
|
||||
},
|
||||
{
|
||||
Key: &semantic.Identifier{Name: "max"},
|
||||
Value: &semantic.MemberExpression{
|
||||
Object: &semantic.IdentifierExpression{
|
||||
Name: "r",
|
||||
},
|
||||
Property: "val1",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
MergeKey: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "yield0",
|
||||
Spec: &functions.YieldOpSpec{
|
||||
Name: "0",
|
||||
},
|
||||
},
|
||||
},
|
||||
Edges: []query.Edge{
|
||||
{Parent: "from0", Child: "range0"},
|
||||
{Parent: "range0", Child: "filter0"},
|
||||
{Parent: "filter0", Child: "group0"},
|
||||
{Parent: "group0", Child: "mean0"},
|
||||
{Parent: "from1", Child: "range1"},
|
||||
{Parent: "range1", Child: "filter1"},
|
||||
{Parent: "filter1", Child: "group1"},
|
||||
{Parent: "group1", Child: "max0"},
|
||||
{Parent: "mean0", Child: "join0"},
|
||||
{Parent: "max0", Child: "join0"},
|
||||
{Parent: "join0", Child: "map0"},
|
||||
{Parent: "map0", Child: "yield0"},
|
||||
},
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
|
@ -0,0 +1,246 @@
|
|||
package spectests
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/influxdata/influxql"
|
||||
"github.com/influxdata/platform/query"
|
||||
"github.com/influxdata/platform/query/ast"
|
||||
"github.com/influxdata/platform/query/execute"
|
||||
"github.com/influxdata/platform/query/functions"
|
||||
"github.com/influxdata/platform/query/semantic"
|
||||
)
|
||||
|
||||
func init() {
|
||||
RegisterFixture(
|
||||
NewFixture(
|
||||
`SELECT mean(value) FROM db0..cpu; SELECT max(value) FROM db0..cpu`,
|
||||
&query.Spec{
|
||||
Operations: []*query.Operation{
|
||||
{
|
||||
ID: "from0",
|
||||
Spec: &functions.FromOpSpec{
|
||||
Bucket: "db0/autogen",
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "range0",
|
||||
Spec: &functions.RangeOpSpec{
|
||||
Start: query.Time{Absolute: time.Unix(0, influxql.MinTime)},
|
||||
Stop: query.Time{Absolute: time.Unix(0, influxql.MaxTime)},
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "filter0",
|
||||
Spec: &functions.FilterOpSpec{
|
||||
Fn: &semantic.FunctionExpression{
|
||||
Params: []*semantic.FunctionParam{
|
||||
{Key: &semantic.Identifier{Name: "r"}},
|
||||
},
|
||||
Body: &semantic.LogicalExpression{
|
||||
Operator: ast.AndOperator,
|
||||
Left: &semantic.BinaryExpression{
|
||||
Operator: ast.EqualOperator,
|
||||
Left: &semantic.MemberExpression{
|
||||
Object: &semantic.IdentifierExpression{
|
||||
Name: "r",
|
||||
},
|
||||
Property: "_measurement",
|
||||
},
|
||||
Right: &semantic.StringLiteral{
|
||||
Value: "cpu",
|
||||
},
|
||||
},
|
||||
Right: &semantic.BinaryExpression{
|
||||
Operator: ast.EqualOperator,
|
||||
Left: &semantic.MemberExpression{
|
||||
Object: &semantic.IdentifierExpression{
|
||||
Name: "r",
|
||||
},
|
||||
Property: "_field",
|
||||
},
|
||||
Right: &semantic.StringLiteral{
|
||||
Value: "value",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "group0",
|
||||
Spec: &functions.GroupOpSpec{
|
||||
By: []string{"_measurement"},
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "mean0",
|
||||
Spec: &functions.MeanOpSpec{
|
||||
AggregateConfig: execute.AggregateConfig{
|
||||
TimeSrc: execute.DefaultStartColLabel,
|
||||
TimeDst: execute.DefaultTimeColLabel,
|
||||
Columns: []string{execute.DefaultValueColLabel},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "map0",
|
||||
Spec: &functions.MapOpSpec{
|
||||
Fn: &semantic.FunctionExpression{
|
||||
Params: []*semantic.FunctionParam{{
|
||||
Key: &semantic.Identifier{Name: "r"},
|
||||
}},
|
||||
Body: &semantic.ObjectExpression{
|
||||
Properties: []*semantic.Property{
|
||||
{
|
||||
Key: &semantic.Identifier{Name: "_time"},
|
||||
Value: &semantic.MemberExpression{
|
||||
Object: &semantic.IdentifierExpression{
|
||||
Name: "r",
|
||||
},
|
||||
Property: "_time",
|
||||
},
|
||||
},
|
||||
{
|
||||
Key: &semantic.Identifier{Name: "mean"},
|
||||
Value: &semantic.MemberExpression{
|
||||
Object: &semantic.IdentifierExpression{
|
||||
Name: "r",
|
||||
},
|
||||
Property: "_value",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
MergeKey: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "yield0",
|
||||
Spec: &functions.YieldOpSpec{
|
||||
Name: "0",
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "from1",
|
||||
Spec: &functions.FromOpSpec{
|
||||
Bucket: "db0/autogen",
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "range1",
|
||||
Spec: &functions.RangeOpSpec{
|
||||
Start: query.Time{Absolute: time.Unix(0, influxql.MinTime)},
|
||||
Stop: query.Time{Absolute: time.Unix(0, influxql.MaxTime)},
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "filter1",
|
||||
Spec: &functions.FilterOpSpec{
|
||||
Fn: &semantic.FunctionExpression{
|
||||
Params: []*semantic.FunctionParam{
|
||||
{Key: &semantic.Identifier{Name: "r"}},
|
||||
},
|
||||
Body: &semantic.LogicalExpression{
|
||||
Operator: ast.AndOperator,
|
||||
Left: &semantic.BinaryExpression{
|
||||
Operator: ast.EqualOperator,
|
||||
Left: &semantic.MemberExpression{
|
||||
Object: &semantic.IdentifierExpression{
|
||||
Name: "r",
|
||||
},
|
||||
Property: "_measurement",
|
||||
},
|
||||
Right: &semantic.StringLiteral{
|
||||
Value: "cpu",
|
||||
},
|
||||
},
|
||||
Right: &semantic.BinaryExpression{
|
||||
Operator: ast.EqualOperator,
|
||||
Left: &semantic.MemberExpression{
|
||||
Object: &semantic.IdentifierExpression{
|
||||
Name: "r",
|
||||
},
|
||||
Property: "_field",
|
||||
},
|
||||
Right: &semantic.StringLiteral{
|
||||
Value: "value",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "group1",
|
||||
Spec: &functions.GroupOpSpec{
|
||||
By: []string{"_measurement"},
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "max0",
|
||||
Spec: &functions.MaxOpSpec{
|
||||
SelectorConfig: execute.SelectorConfig{
|
||||
Column: execute.DefaultValueColLabel,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "map1",
|
||||
Spec: &functions.MapOpSpec{
|
||||
Fn: &semantic.FunctionExpression{
|
||||
Params: []*semantic.FunctionParam{{
|
||||
Key: &semantic.Identifier{Name: "r"},
|
||||
}},
|
||||
Body: &semantic.ObjectExpression{
|
||||
Properties: []*semantic.Property{
|
||||
{
|
||||
Key: &semantic.Identifier{Name: "_time"},
|
||||
Value: &semantic.MemberExpression{
|
||||
Object: &semantic.IdentifierExpression{
|
||||
Name: "r",
|
||||
},
|
||||
Property: "_time",
|
||||
},
|
||||
},
|
||||
{
|
||||
Key: &semantic.Identifier{Name: "max"},
|
||||
Value: &semantic.MemberExpression{
|
||||
Object: &semantic.IdentifierExpression{
|
||||
Name: "r",
|
||||
},
|
||||
Property: "_value",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
MergeKey: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "yield1",
|
||||
Spec: &functions.YieldOpSpec{
|
||||
Name: "1",
|
||||
},
|
||||
},
|
||||
},
|
||||
Edges: []query.Edge{
|
||||
{Parent: "from0", Child: "range0"},
|
||||
{Parent: "range0", Child: "filter0"},
|
||||
{Parent: "filter0", Child: "group0"},
|
||||
{Parent: "group0", Child: "mean0"},
|
||||
{Parent: "mean0", Child: "map0"},
|
||||
{Parent: "map0", Child: "yield0"},
|
||||
{Parent: "from1", Child: "range1"},
|
||||
{Parent: "range1", Child: "filter1"},
|
||||
{Parent: "filter1", Child: "group1"},
|
||||
{Parent: "group1", Child: "max0"},
|
||||
{Parent: "max0", Child: "map1"},
|
||||
{Parent: "map1", Child: "yield1"},
|
||||
},
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
|
@ -0,0 +1,125 @@
|
|||
package spectests
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/influxdata/influxql"
|
||||
"github.com/influxdata/platform/query"
|
||||
"github.com/influxdata/platform/query/ast"
|
||||
"github.com/influxdata/platform/query/functions"
|
||||
"github.com/influxdata/platform/query/semantic"
|
||||
)
|
||||
|
||||
func init() {
|
||||
RegisterFixture(
|
||||
NewFixture(
|
||||
`SELECT value FROM db0..cpu`,
|
||||
&query.Spec{
|
||||
Operations: []*query.Operation{
|
||||
{
|
||||
ID: "from0",
|
||||
Spec: &functions.FromOpSpec{
|
||||
Bucket: "db0/autogen",
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "range0",
|
||||
Spec: &functions.RangeOpSpec{
|
||||
Start: query.Time{Absolute: time.Unix(0, influxql.MinTime)},
|
||||
Stop: query.Time{Absolute: time.Unix(0, influxql.MaxTime)},
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "filter0",
|
||||
Spec: &functions.FilterOpSpec{
|
||||
Fn: &semantic.FunctionExpression{
|
||||
Params: []*semantic.FunctionParam{
|
||||
{Key: &semantic.Identifier{Name: "r"}},
|
||||
},
|
||||
Body: &semantic.LogicalExpression{
|
||||
Operator: ast.AndOperator,
|
||||
Left: &semantic.BinaryExpression{
|
||||
Operator: ast.EqualOperator,
|
||||
Left: &semantic.MemberExpression{
|
||||
Object: &semantic.IdentifierExpression{
|
||||
Name: "r",
|
||||
},
|
||||
Property: "_measurement",
|
||||
},
|
||||
Right: &semantic.StringLiteral{
|
||||
Value: "cpu",
|
||||
},
|
||||
},
|
||||
Right: &semantic.BinaryExpression{
|
||||
Operator: ast.EqualOperator,
|
||||
Left: &semantic.MemberExpression{
|
||||
Object: &semantic.IdentifierExpression{
|
||||
Name: "r",
|
||||
},
|
||||
Property: "_field",
|
||||
},
|
||||
Right: &semantic.StringLiteral{
|
||||
Value: "value",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "group0",
|
||||
Spec: &functions.GroupOpSpec{
|
||||
By: []string{"_measurement"},
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "map0",
|
||||
Spec: &functions.MapOpSpec{
|
||||
Fn: &semantic.FunctionExpression{
|
||||
Params: []*semantic.FunctionParam{{
|
||||
Key: &semantic.Identifier{Name: "r"},
|
||||
}},
|
||||
Body: &semantic.ObjectExpression{
|
||||
Properties: []*semantic.Property{
|
||||
{
|
||||
Key: &semantic.Identifier{Name: "_time"},
|
||||
Value: &semantic.MemberExpression{
|
||||
Object: &semantic.IdentifierExpression{
|
||||
Name: "r",
|
||||
},
|
||||
Property: "_time",
|
||||
},
|
||||
},
|
||||
{
|
||||
Key: &semantic.Identifier{Name: "value"},
|
||||
Value: &semantic.MemberExpression{
|
||||
Object: &semantic.IdentifierExpression{
|
||||
Name: "r",
|
||||
},
|
||||
Property: "_value",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
MergeKey: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "yield0",
|
||||
Spec: &functions.YieldOpSpec{
|
||||
Name: "0",
|
||||
},
|
||||
},
|
||||
},
|
||||
Edges: []query.Edge{
|
||||
{Parent: "from0", Child: "range0"},
|
||||
{Parent: "range0", Child: "filter0"},
|
||||
{Parent: "filter0", Child: "group0"},
|
||||
{Parent: "group0", Child: "map0"},
|
||||
{Parent: "map0", Child: "yield0"},
|
||||
},
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
|
@ -0,0 +1,125 @@
|
|||
package spectests
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/influxdata/influxql"
|
||||
"github.com/influxdata/platform/query"
|
||||
"github.com/influxdata/platform/query/ast"
|
||||
"github.com/influxdata/platform/query/functions"
|
||||
"github.com/influxdata/platform/query/semantic"
|
||||
)
|
||||
|
||||
func init() {
|
||||
RegisterFixture(
|
||||
NewFixture(
|
||||
`SELECT value FROM db0.alternate.cpu`,
|
||||
&query.Spec{
|
||||
Operations: []*query.Operation{
|
||||
{
|
||||
ID: "from0",
|
||||
Spec: &functions.FromOpSpec{
|
||||
Bucket: "db0/alternate",
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "range0",
|
||||
Spec: &functions.RangeOpSpec{
|
||||
Start: query.Time{Absolute: time.Unix(0, influxql.MinTime)},
|
||||
Stop: query.Time{Absolute: time.Unix(0, influxql.MaxTime)},
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "filter0",
|
||||
Spec: &functions.FilterOpSpec{
|
||||
Fn: &semantic.FunctionExpression{
|
||||
Params: []*semantic.FunctionParam{
|
||||
{Key: &semantic.Identifier{Name: "r"}},
|
||||
},
|
||||
Body: &semantic.LogicalExpression{
|
||||
Operator: ast.AndOperator,
|
||||
Left: &semantic.BinaryExpression{
|
||||
Operator: ast.EqualOperator,
|
||||
Left: &semantic.MemberExpression{
|
||||
Object: &semantic.IdentifierExpression{
|
||||
Name: "r",
|
||||
},
|
||||
Property: "_measurement",
|
||||
},
|
||||
Right: &semantic.StringLiteral{
|
||||
Value: "cpu",
|
||||
},
|
||||
},
|
||||
Right: &semantic.BinaryExpression{
|
||||
Operator: ast.EqualOperator,
|
||||
Left: &semantic.MemberExpression{
|
||||
Object: &semantic.IdentifierExpression{
|
||||
Name: "r",
|
||||
},
|
||||
Property: "_field",
|
||||
},
|
||||
Right: &semantic.StringLiteral{
|
||||
Value: "value",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "group0",
|
||||
Spec: &functions.GroupOpSpec{
|
||||
By: []string{"_measurement"},
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "map0",
|
||||
Spec: &functions.MapOpSpec{
|
||||
Fn: &semantic.FunctionExpression{
|
||||
Params: []*semantic.FunctionParam{{
|
||||
Key: &semantic.Identifier{Name: "r"},
|
||||
}},
|
||||
Body: &semantic.ObjectExpression{
|
||||
Properties: []*semantic.Property{
|
||||
{
|
||||
Key: &semantic.Identifier{Name: "_time"},
|
||||
Value: &semantic.MemberExpression{
|
||||
Object: &semantic.IdentifierExpression{
|
||||
Name: "r",
|
||||
},
|
||||
Property: "_time",
|
||||
},
|
||||
},
|
||||
{
|
||||
Key: &semantic.Identifier{Name: "value"},
|
||||
Value: &semantic.MemberExpression{
|
||||
Object: &semantic.IdentifierExpression{
|
||||
Name: "r",
|
||||
},
|
||||
Property: "_value",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
MergeKey: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "yield0",
|
||||
Spec: &functions.YieldOpSpec{
|
||||
Name: "0",
|
||||
},
|
||||
},
|
||||
},
|
||||
Edges: []query.Edge{
|
||||
{Parent: "from0", Child: "range0"},
|
||||
{Parent: "range0", Child: "filter0"},
|
||||
{Parent: "filter0", Child: "group0"},
|
||||
{Parent: "group0", Child: "map0"},
|
||||
{Parent: "map0", Child: "yield0"},
|
||||
},
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
|
@ -0,0 +1,115 @@
|
|||
package spectests
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/influxdata/platform/query"
|
||||
"github.com/influxdata/platform/query/influxql"
|
||||
)
|
||||
|
||||
// Fixture is a structure that will run tests.
|
||||
type Fixture interface {
|
||||
Run(t *testing.T)
|
||||
}
|
||||
|
||||
type fixture struct {
|
||||
stmt string
|
||||
spec *query.Spec
|
||||
|
||||
file string
|
||||
line int
|
||||
}
|
||||
|
||||
func NewFixture(stmt string, spec *query.Spec) Fixture {
|
||||
_, file, line, _ := runtime.Caller(1)
|
||||
return &fixture{
|
||||
stmt: stmt,
|
||||
spec: spec,
|
||||
file: filepath.Base(file),
|
||||
line: line,
|
||||
}
|
||||
}
|
||||
|
||||
func (f *fixture) Run(t *testing.T) {
|
||||
t.Run(f.stmt, func(t *testing.T) {
|
||||
if err := f.spec.Validate(); err != nil {
|
||||
t.Fatalf("%s:%d: expected spec is not valid: %s", f.file, f.line, err)
|
||||
}
|
||||
|
||||
transpiler := influxql.NewTranspilerWithConfig(influxql.Config{
|
||||
NowFn: Now,
|
||||
})
|
||||
spec, err := transpiler.Transpile(context.Background(), f.stmt)
|
||||
if err != nil {
|
||||
t.Fatalf("%s:%d: unexpected error: %s", f.file, f.line, err)
|
||||
} else if err := spec.Validate(); err != nil {
|
||||
t.Fatalf("%s:%d: spec is not valid: %s", f.file, f.line, err)
|
||||
}
|
||||
|
||||
// Encode both of these to JSON and compare the results.
|
||||
exp, _ := json.Marshal(f.spec)
|
||||
got, _ := json.Marshal(spec)
|
||||
if !bytes.Equal(exp, got) {
|
||||
// Unmarshal into objects so we can compare the key/value pairs.
|
||||
var expObj, gotObj interface{}
|
||||
json.Unmarshal(exp, &expObj)
|
||||
json.Unmarshal(got, &gotObj)
|
||||
|
||||
// If there is no diff, then they were trivial byte differences and
|
||||
// there is no error.
|
||||
if diff := cmp.Diff(expObj, gotObj); diff != "" {
|
||||
t.Fatalf("unexpected spec in test at %s:%d\n%s", f.file, f.line, diff)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
type collection struct {
|
||||
stmts []string
|
||||
specs []*query.Spec
|
||||
|
||||
file string
|
||||
line int
|
||||
}
|
||||
|
||||
func (c *collection) Add(stmt string, spec *query.Spec) {
|
||||
c.stmts = append(c.stmts, stmt)
|
||||
c.specs = append(c.specs, spec)
|
||||
}
|
||||
|
||||
func (c *collection) Run(t *testing.T) {
|
||||
for i, stmt := range c.stmts {
|
||||
f := fixture{
|
||||
stmt: stmt,
|
||||
spec: c.specs[i],
|
||||
file: c.file,
|
||||
line: c.line,
|
||||
}
|
||||
f.Run(t)
|
||||
}
|
||||
}
|
||||
|
||||
var allFixtures []Fixture
|
||||
|
||||
func RegisterFixture(fixtures ...Fixture) {
|
||||
allFixtures = append(allFixtures, fixtures...)
|
||||
}
|
||||
|
||||
func All() []Fixture {
|
||||
return allFixtures
|
||||
}
|
||||
|
||||
func Now() time.Time {
|
||||
t, err := time.Parse(time.RFC3339, "2010-09-15T09:00:00Z")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return t
|
||||
}
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue