1696 lines
44 KiB
Go
1696 lines
44 KiB
Go
package parser_test
|
|
|
|
import (
|
|
"regexp"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/google/go-cmp/cmp"
|
|
"github.com/influxdata/platform/query/ast"
|
|
"github.com/influxdata/platform/query/ast/asttest"
|
|
"github.com/influxdata/platform/query/parser"
|
|
)
|
|
|
|
func TestParse(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
raw string
|
|
want *ast.Program
|
|
wantErr bool
|
|
}{
|
|
{
|
|
name: "optional query metadata",
|
|
raw: `option task = {
|
|
name: "foo",
|
|
every: 1h,
|
|
delay: 10m,
|
|
cron: "0 2 * * *",
|
|
retry: 5,
|
|
}`,
|
|
want: &ast.Program{
|
|
Body: []ast.Statement{
|
|
&ast.OptionStatement{
|
|
Declaration: &ast.VariableDeclarator{
|
|
ID: &ast.Identifier{Name: "task"},
|
|
Init: &ast.ObjectExpression{
|
|
Properties: []*ast.Property{
|
|
{
|
|
Key: &ast.Identifier{Name: "name"},
|
|
Value: &ast.StringLiteral{Value: "foo"},
|
|
},
|
|
{
|
|
Key: &ast.Identifier{Name: "every"},
|
|
Value: &ast.DurationLiteral{Value: 1 * time.Hour},
|
|
},
|
|
{
|
|
Key: &ast.Identifier{Name: "delay"},
|
|
Value: &ast.DurationLiteral{Value: 10 * time.Minute},
|
|
},
|
|
{
|
|
Key: &ast.Identifier{Name: "cron"},
|
|
Value: &ast.StringLiteral{Value: "0 2 * * *"},
|
|
},
|
|
{
|
|
Key: &ast.Identifier{Name: "retry"},
|
|
Value: &ast.IntegerLiteral{Value: 5},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "optional query metadata preceding query text",
|
|
raw: `option task = {
|
|
name: "foo", // Name of task
|
|
every: 1h, // Execution frequency of task
|
|
}
|
|
|
|
// Task will execute the following query
|
|
from() |> count()`,
|
|
want: &ast.Program{
|
|
Body: []ast.Statement{
|
|
&ast.OptionStatement{
|
|
Declaration: &ast.VariableDeclarator{
|
|
ID: &ast.Identifier{Name: "task"},
|
|
Init: &ast.ObjectExpression{
|
|
Properties: []*ast.Property{
|
|
{
|
|
Key: &ast.Identifier{Name: "name"},
|
|
Value: &ast.StringLiteral{Value: "foo"},
|
|
},
|
|
{
|
|
Key: &ast.Identifier{Name: "every"},
|
|
Value: &ast.DurationLiteral{Value: 1 * time.Hour},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
&ast.ExpressionStatement{
|
|
Expression: &ast.PipeExpression{
|
|
Argument: &ast.CallExpression{
|
|
Callee: &ast.Identifier{Name: "from"},
|
|
Arguments: nil,
|
|
},
|
|
Call: &ast.CallExpression{
|
|
Callee: &ast.Identifier{Name: "count"},
|
|
Arguments: nil,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "from",
|
|
raw: `from()`,
|
|
want: &ast.Program{
|
|
Body: []ast.Statement{
|
|
&ast.ExpressionStatement{
|
|
Expression: &ast.CallExpression{
|
|
Callee: &ast.Identifier{
|
|
Name: "from",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "comment",
|
|
raw: `// Comment
|
|
from()`,
|
|
want: &ast.Program{
|
|
Body: []ast.Statement{
|
|
&ast.ExpressionStatement{
|
|
Expression: &ast.CallExpression{
|
|
Callee: &ast.Identifier{
|
|
Name: "from",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "identifier with number",
|
|
raw: `tan2()`,
|
|
want: &ast.Program{
|
|
Body: []ast.Statement{
|
|
&ast.ExpressionStatement{
|
|
Expression: &ast.CallExpression{
|
|
Callee: &ast.Identifier{
|
|
Name: "tan2",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "regex literal",
|
|
raw: `/.*/`,
|
|
want: &ast.Program{
|
|
Body: []ast.Statement{
|
|
&ast.ExpressionStatement{
|
|
Expression: &ast.RegexpLiteral{
|
|
Value: regexp.MustCompile(".*"),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "regex literal with escape sequence",
|
|
raw: `/a\/b\\c\d/`,
|
|
want: &ast.Program{
|
|
Body: []ast.Statement{
|
|
&ast.ExpressionStatement{
|
|
Expression: &ast.RegexpLiteral{
|
|
Value: regexp.MustCompile(`a/b\\c\d`),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "regex match operators",
|
|
raw: `"a" =~ /.*/ and "b" !~ /c/`,
|
|
want: &ast.Program{
|
|
Body: []ast.Statement{
|
|
&ast.ExpressionStatement{
|
|
Expression: &ast.LogicalExpression{
|
|
Operator: ast.AndOperator,
|
|
Left: &ast.BinaryExpression{
|
|
Operator: ast.RegexpMatchOperator,
|
|
Left: &ast.StringLiteral{Value: "a"},
|
|
Right: &ast.RegexpLiteral{Value: regexp.MustCompile(".*")},
|
|
},
|
|
Right: &ast.BinaryExpression{
|
|
Operator: ast.NotRegexpMatchOperator,
|
|
Left: &ast.StringLiteral{Value: "b"},
|
|
Right: &ast.RegexpLiteral{Value: regexp.MustCompile("c")},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "declare variable as an int",
|
|
raw: `howdy = 1`,
|
|
want: &ast.Program{
|
|
Body: []ast.Statement{
|
|
&ast.VariableDeclaration{
|
|
Declarations: []*ast.VariableDeclarator{{
|
|
ID: &ast.Identifier{Name: "howdy"},
|
|
Init: &ast.IntegerLiteral{Value: 1},
|
|
}},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "declare variable as a float",
|
|
raw: `howdy = 1.1`,
|
|
want: &ast.Program{
|
|
Body: []ast.Statement{
|
|
&ast.VariableDeclaration{
|
|
Declarations: []*ast.VariableDeclarator{{
|
|
ID: &ast.Identifier{Name: "howdy"},
|
|
Init: &ast.FloatLiteral{Value: 1.1},
|
|
}},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "declare variable as an array",
|
|
raw: `howdy = [1, 2, 3, 4]`,
|
|
want: &ast.Program{
|
|
Body: []ast.Statement{
|
|
&ast.VariableDeclaration{
|
|
Declarations: []*ast.VariableDeclarator{{
|
|
ID: &ast.Identifier{Name: "howdy"},
|
|
Init: &ast.ArrayExpression{
|
|
Elements: []ast.Expression{
|
|
&ast.IntegerLiteral{Value: 1},
|
|
&ast.IntegerLiteral{Value: 2},
|
|
&ast.IntegerLiteral{Value: 3},
|
|
&ast.IntegerLiteral{Value: 4},
|
|
},
|
|
},
|
|
}},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "use variable to declare something",
|
|
raw: `howdy = 1
|
|
from()`,
|
|
want: &ast.Program{
|
|
Body: []ast.Statement{
|
|
&ast.VariableDeclaration{
|
|
Declarations: []*ast.VariableDeclarator{{
|
|
ID: &ast.Identifier{Name: "howdy"},
|
|
Init: &ast.IntegerLiteral{Value: 1},
|
|
}},
|
|
},
|
|
&ast.ExpressionStatement{
|
|
Expression: &ast.CallExpression{
|
|
Callee: &ast.Identifier{
|
|
Name: "from",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "variable is from statement",
|
|
raw: `howdy = from()
|
|
howdy.count()`,
|
|
want: &ast.Program{
|
|
Body: []ast.Statement{
|
|
&ast.VariableDeclaration{
|
|
Declarations: []*ast.VariableDeclarator{{
|
|
ID: &ast.Identifier{
|
|
Name: "howdy",
|
|
},
|
|
Init: &ast.CallExpression{
|
|
Callee: &ast.Identifier{
|
|
Name: "from",
|
|
},
|
|
},
|
|
}},
|
|
},
|
|
&ast.ExpressionStatement{
|
|
Expression: &ast.CallExpression{
|
|
Callee: &ast.MemberExpression{
|
|
Object: &ast.Identifier{
|
|
Name: "howdy",
|
|
},
|
|
Property: &ast.Identifier{
|
|
Name: "count",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "pipe expression",
|
|
raw: `from() |> count()`,
|
|
want: &ast.Program{
|
|
Body: []ast.Statement{
|
|
&ast.ExpressionStatement{
|
|
Expression: &ast.PipeExpression{
|
|
Argument: &ast.CallExpression{
|
|
Callee: &ast.Identifier{Name: "from"},
|
|
Arguments: nil,
|
|
},
|
|
Call: &ast.CallExpression{
|
|
Callee: &ast.Identifier{Name: "count"},
|
|
Arguments: nil,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "literal pipe expression",
|
|
raw: `5 |> pow2()`,
|
|
want: &ast.Program{
|
|
Body: []ast.Statement{
|
|
&ast.ExpressionStatement{
|
|
Expression: &ast.PipeExpression{
|
|
Argument: &ast.IntegerLiteral{Value: 5},
|
|
Call: &ast.CallExpression{
|
|
Callee: &ast.Identifier{Name: "pow2"},
|
|
Arguments: nil,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "member expression pipe expression",
|
|
raw: `foo.bar |> baz()`,
|
|
want: &ast.Program{
|
|
Body: []ast.Statement{
|
|
&ast.ExpressionStatement{
|
|
Expression: &ast.PipeExpression{
|
|
Argument: &ast.MemberExpression{
|
|
Object: &ast.Identifier{Name: "foo"},
|
|
Property: &ast.Identifier{Name: "bar"},
|
|
},
|
|
Call: &ast.CallExpression{
|
|
Callee: &ast.Identifier{Name: "baz"},
|
|
Arguments: nil,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "multiple pipe expressions",
|
|
raw: `from() |> range() |> filter() |> count()`,
|
|
want: &ast.Program{
|
|
Body: []ast.Statement{
|
|
&ast.ExpressionStatement{
|
|
Expression: &ast.PipeExpression{
|
|
Argument: &ast.PipeExpression{
|
|
Argument: &ast.PipeExpression{
|
|
Argument: &ast.CallExpression{
|
|
Callee: &ast.Identifier{Name: "from"},
|
|
},
|
|
Call: &ast.CallExpression{
|
|
Callee: &ast.Identifier{Name: "range"},
|
|
},
|
|
},
|
|
Call: &ast.CallExpression{
|
|
Callee: &ast.Identifier{Name: "filter"},
|
|
},
|
|
},
|
|
Call: &ast.CallExpression{
|
|
Callee: &ast.Identifier{Name: "count"},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "two variables for two froms",
|
|
raw: `howdy = from()
|
|
doody = from()
|
|
howdy|>count()
|
|
doody|>sum()`,
|
|
want: &ast.Program{
|
|
Body: []ast.Statement{
|
|
&ast.VariableDeclaration{
|
|
Declarations: []*ast.VariableDeclarator{{
|
|
ID: &ast.Identifier{
|
|
Name: "howdy",
|
|
},
|
|
Init: &ast.CallExpression{
|
|
Callee: &ast.Identifier{
|
|
Name: "from",
|
|
},
|
|
},
|
|
}},
|
|
},
|
|
&ast.VariableDeclaration{
|
|
Declarations: []*ast.VariableDeclarator{{
|
|
ID: &ast.Identifier{
|
|
Name: "doody",
|
|
},
|
|
Init: &ast.CallExpression{
|
|
Callee: &ast.Identifier{
|
|
Name: "from",
|
|
},
|
|
},
|
|
}},
|
|
},
|
|
&ast.ExpressionStatement{
|
|
Expression: &ast.PipeExpression{
|
|
Argument: &ast.Identifier{Name: "howdy"},
|
|
Call: &ast.CallExpression{
|
|
Callee: &ast.Identifier{
|
|
Name: "count",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
&ast.ExpressionStatement{
|
|
Expression: &ast.PipeExpression{
|
|
Argument: &ast.Identifier{Name: "doody"},
|
|
Call: &ast.CallExpression{
|
|
Callee: &ast.Identifier{
|
|
Name: "sum",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "from with database",
|
|
raw: `from(db:"telegraf")`,
|
|
want: &ast.Program{
|
|
Body: []ast.Statement{
|
|
&ast.ExpressionStatement{
|
|
Expression: &ast.CallExpression{
|
|
Callee: &ast.Identifier{
|
|
Name: "from",
|
|
},
|
|
Arguments: []ast.Expression{
|
|
&ast.ObjectExpression{
|
|
Properties: []*ast.Property{
|
|
{
|
|
Key: &ast.Identifier{
|
|
Name: "db",
|
|
},
|
|
Value: &ast.StringLiteral{
|
|
Value: "telegraf",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "map member expressions",
|
|
raw: `m = {key1: 1, key2:"value2"}
|
|
m.key1
|
|
m["key2"]
|
|
`,
|
|
want: &ast.Program{
|
|
Body: []ast.Statement{
|
|
&ast.VariableDeclaration{
|
|
Declarations: []*ast.VariableDeclarator{{
|
|
ID: &ast.Identifier{
|
|
Name: "m",
|
|
},
|
|
Init: &ast.ObjectExpression{
|
|
Properties: []*ast.Property{
|
|
{
|
|
Key: &ast.Identifier{Name: "key1"},
|
|
Value: &ast.IntegerLiteral{Value: 1},
|
|
},
|
|
{
|
|
Key: &ast.Identifier{Name: "key2"},
|
|
Value: &ast.StringLiteral{Value: "value2"},
|
|
},
|
|
},
|
|
},
|
|
}},
|
|
},
|
|
&ast.ExpressionStatement{
|
|
Expression: &ast.MemberExpression{
|
|
Object: &ast.Identifier{Name: "m"},
|
|
Property: &ast.Identifier{Name: "key1"},
|
|
},
|
|
},
|
|
&ast.ExpressionStatement{
|
|
Expression: &ast.MemberExpression{
|
|
Object: &ast.Identifier{Name: "m"},
|
|
Property: &ast.StringLiteral{Value: "key2"},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "var as binary expression of other vars",
|
|
raw: `a = 1
|
|
b = 2
|
|
c = a + b
|
|
d = a`,
|
|
want: &ast.Program{
|
|
Body: []ast.Statement{
|
|
&ast.VariableDeclaration{
|
|
Declarations: []*ast.VariableDeclarator{{
|
|
ID: &ast.Identifier{
|
|
Name: "a",
|
|
},
|
|
Init: &ast.IntegerLiteral{Value: 1},
|
|
}},
|
|
},
|
|
&ast.VariableDeclaration{
|
|
Declarations: []*ast.VariableDeclarator{{
|
|
ID: &ast.Identifier{
|
|
Name: "b",
|
|
},
|
|
Init: &ast.IntegerLiteral{Value: 2},
|
|
}},
|
|
},
|
|
&ast.VariableDeclaration{
|
|
Declarations: []*ast.VariableDeclarator{{
|
|
ID: &ast.Identifier{
|
|
Name: "c",
|
|
},
|
|
Init: &ast.BinaryExpression{
|
|
Operator: ast.AdditionOperator,
|
|
Left: &ast.Identifier{Name: "a"},
|
|
Right: &ast.Identifier{Name: "b"},
|
|
},
|
|
}},
|
|
},
|
|
&ast.VariableDeclaration{
|
|
Declarations: []*ast.VariableDeclarator{{
|
|
ID: &ast.Identifier{
|
|
Name: "d",
|
|
},
|
|
Init: &ast.Identifier{Name: "a"},
|
|
}},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "var as unary expression of other vars",
|
|
raw: `a = 5
|
|
c = -a`,
|
|
want: &ast.Program{
|
|
Body: []ast.Statement{
|
|
&ast.VariableDeclaration{
|
|
Declarations: []*ast.VariableDeclarator{{
|
|
ID: &ast.Identifier{
|
|
Name: "a",
|
|
},
|
|
Init: &ast.IntegerLiteral{Value: 5},
|
|
}},
|
|
},
|
|
&ast.VariableDeclaration{
|
|
Declarations: []*ast.VariableDeclarator{{
|
|
ID: &ast.Identifier{
|
|
Name: "c",
|
|
},
|
|
Init: &ast.UnaryExpression{
|
|
Operator: ast.SubtractionOperator,
|
|
Argument: &ast.Identifier{Name: "a"},
|
|
},
|
|
}},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "var as both binary and unary expressions",
|
|
raw: `a = 5
|
|
c = 10 * -a`,
|
|
want: &ast.Program{
|
|
Body: []ast.Statement{
|
|
&ast.VariableDeclaration{
|
|
Declarations: []*ast.VariableDeclarator{{
|
|
ID: &ast.Identifier{
|
|
Name: "a",
|
|
},
|
|
Init: &ast.IntegerLiteral{Value: 5},
|
|
}},
|
|
},
|
|
&ast.VariableDeclaration{
|
|
Declarations: []*ast.VariableDeclarator{{
|
|
ID: &ast.Identifier{
|
|
Name: "c",
|
|
},
|
|
Init: &ast.BinaryExpression{
|
|
Operator: ast.MultiplicationOperator,
|
|
Left: &ast.IntegerLiteral{Value: 10},
|
|
Right: &ast.UnaryExpression{
|
|
Operator: ast.SubtractionOperator,
|
|
Argument: &ast.Identifier{Name: "a"},
|
|
},
|
|
},
|
|
}},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "unary expressions within logical expression",
|
|
raw: `a = 5.0
|
|
10.0 * -a == -0.5 or a == 6.0`,
|
|
want: &ast.Program{
|
|
Body: []ast.Statement{
|
|
&ast.VariableDeclaration{
|
|
Declarations: []*ast.VariableDeclarator{{
|
|
ID: &ast.Identifier{
|
|
Name: "a",
|
|
},
|
|
Init: &ast.FloatLiteral{Value: 5},
|
|
}},
|
|
},
|
|
&ast.ExpressionStatement{
|
|
Expression: &ast.LogicalExpression{
|
|
Operator: ast.OrOperator,
|
|
Left: &ast.BinaryExpression{
|
|
Operator: ast.EqualOperator,
|
|
Left: &ast.BinaryExpression{
|
|
Operator: ast.MultiplicationOperator,
|
|
Left: &ast.FloatLiteral{Value: 10},
|
|
Right: &ast.UnaryExpression{
|
|
Operator: ast.SubtractionOperator,
|
|
Argument: &ast.Identifier{Name: "a"},
|
|
},
|
|
},
|
|
Right: &ast.UnaryExpression{
|
|
Operator: ast.SubtractionOperator,
|
|
Argument: &ast.FloatLiteral{Value: 0.5},
|
|
},
|
|
},
|
|
Right: &ast.BinaryExpression{
|
|
Operator: ast.EqualOperator,
|
|
Left: &ast.Identifier{Name: "a"},
|
|
Right: &ast.FloatLiteral{Value: 6},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "unary expressions with too many comments",
|
|
raw: `// define a
|
|
a = 5.0
|
|
// eval this
|
|
10.0 * -a == -0.5
|
|
// or this
|
|
or a == 6.0`,
|
|
want: &ast.Program{
|
|
Body: []ast.Statement{
|
|
&ast.VariableDeclaration{
|
|
Declarations: []*ast.VariableDeclarator{{
|
|
ID: &ast.Identifier{
|
|
Name: "a",
|
|
},
|
|
Init: &ast.FloatLiteral{Value: 5},
|
|
}},
|
|
},
|
|
&ast.ExpressionStatement{
|
|
Expression: &ast.LogicalExpression{
|
|
Operator: ast.OrOperator,
|
|
Left: &ast.BinaryExpression{
|
|
Operator: ast.EqualOperator,
|
|
Left: &ast.BinaryExpression{
|
|
Operator: ast.MultiplicationOperator,
|
|
Left: &ast.FloatLiteral{Value: 10},
|
|
Right: &ast.UnaryExpression{
|
|
Operator: ast.SubtractionOperator,
|
|
Argument: &ast.Identifier{Name: "a"},
|
|
},
|
|
},
|
|
Right: &ast.UnaryExpression{
|
|
Operator: ast.SubtractionOperator,
|
|
Argument: &ast.FloatLiteral{Value: 0.5},
|
|
},
|
|
},
|
|
Right: &ast.BinaryExpression{
|
|
Operator: ast.EqualOperator,
|
|
Left: &ast.Identifier{Name: "a"},
|
|
Right: &ast.FloatLiteral{Value: 6},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "expressions with function calls",
|
|
raw: `a = foo() == 10`,
|
|
want: &ast.Program{
|
|
Body: []ast.Statement{
|
|
&ast.VariableDeclaration{
|
|
Declarations: []*ast.VariableDeclarator{{
|
|
ID: &ast.Identifier{
|
|
Name: "a",
|
|
},
|
|
Init: &ast.BinaryExpression{
|
|
Operator: ast.EqualOperator,
|
|
Left: &ast.CallExpression{
|
|
Callee: &ast.Identifier{Name: "foo"},
|
|
},
|
|
Right: &ast.IntegerLiteral{Value: 10},
|
|
},
|
|
}},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "mix unary logical and binary expressions",
|
|
raw: `
|
|
not (f() == 6.0 * x) or fail()`,
|
|
want: &ast.Program{
|
|
Body: []ast.Statement{
|
|
&ast.ExpressionStatement{
|
|
Expression: &ast.LogicalExpression{
|
|
Operator: ast.OrOperator,
|
|
Left: &ast.UnaryExpression{
|
|
Operator: ast.NotOperator,
|
|
Argument: &ast.BinaryExpression{
|
|
Operator: ast.EqualOperator,
|
|
Left: &ast.CallExpression{
|
|
Callee: &ast.Identifier{Name: "f"},
|
|
},
|
|
Right: &ast.BinaryExpression{
|
|
Operator: ast.MultiplicationOperator,
|
|
Left: &ast.FloatLiteral{Value: 6},
|
|
Right: &ast.Identifier{Name: "x"},
|
|
},
|
|
},
|
|
},
|
|
Right: &ast.CallExpression{
|
|
Callee: &ast.Identifier{Name: "fail"},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "mix unary logical and binary expressions with extra parens",
|
|
raw: `
|
|
(not (f() == 6.0 * x) or fail())`,
|
|
want: &ast.Program{
|
|
Body: []ast.Statement{
|
|
&ast.ExpressionStatement{
|
|
Expression: &ast.LogicalExpression{
|
|
Operator: ast.OrOperator,
|
|
Left: &ast.UnaryExpression{
|
|
Operator: ast.NotOperator,
|
|
Argument: &ast.BinaryExpression{
|
|
Operator: ast.EqualOperator,
|
|
Left: &ast.CallExpression{
|
|
Callee: &ast.Identifier{Name: "f"},
|
|
},
|
|
Right: &ast.BinaryExpression{
|
|
Operator: ast.MultiplicationOperator,
|
|
Left: &ast.FloatLiteral{Value: 6},
|
|
Right: &ast.Identifier{Name: "x"},
|
|
},
|
|
},
|
|
},
|
|
Right: &ast.CallExpression{
|
|
Callee: &ast.Identifier{Name: "fail"},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "arrow function called",
|
|
raw: `plusOne = (r) => r + 1
|
|
plusOne(r:5)
|
|
`,
|
|
want: &ast.Program{
|
|
Body: []ast.Statement{
|
|
&ast.VariableDeclaration{
|
|
Declarations: []*ast.VariableDeclarator{{
|
|
ID: &ast.Identifier{
|
|
Name: "plusOne",
|
|
},
|
|
Init: &ast.ArrowFunctionExpression{
|
|
Params: []*ast.Property{{Key: &ast.Identifier{Name: "r"}}},
|
|
Body: &ast.BinaryExpression{
|
|
Operator: ast.AdditionOperator,
|
|
Left: &ast.Identifier{Name: "r"},
|
|
Right: &ast.IntegerLiteral{Value: 1},
|
|
},
|
|
},
|
|
}},
|
|
},
|
|
&ast.ExpressionStatement{
|
|
Expression: &ast.CallExpression{
|
|
Callee: &ast.Identifier{Name: "plusOne"},
|
|
Arguments: []ast.Expression{
|
|
&ast.ObjectExpression{
|
|
Properties: []*ast.Property{
|
|
{
|
|
Key: &ast.Identifier{
|
|
Name: "r",
|
|
},
|
|
Value: &ast.IntegerLiteral{
|
|
Value: 5,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "arrow function return map",
|
|
raw: `toMap = (r) =>({r:r})`,
|
|
want: &ast.Program{
|
|
Body: []ast.Statement{
|
|
&ast.VariableDeclaration{
|
|
Declarations: []*ast.VariableDeclarator{{
|
|
ID: &ast.Identifier{
|
|
Name: "toMap",
|
|
},
|
|
Init: &ast.ArrowFunctionExpression{
|
|
Params: []*ast.Property{{Key: &ast.Identifier{Name: "r"}}},
|
|
Body: &ast.ObjectExpression{
|
|
Properties: []*ast.Property{{
|
|
Key: &ast.Identifier{Name: "r"},
|
|
Value: &ast.Identifier{Name: "r"},
|
|
}},
|
|
},
|
|
},
|
|
}},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "arrow function with default arg",
|
|
raw: `addN = (r, n=5) => r + n`,
|
|
want: &ast.Program{
|
|
Body: []ast.Statement{
|
|
&ast.VariableDeclaration{
|
|
Declarations: []*ast.VariableDeclarator{{
|
|
ID: &ast.Identifier{
|
|
Name: "addN",
|
|
},
|
|
Init: &ast.ArrowFunctionExpression{
|
|
Params: []*ast.Property{
|
|
{Key: &ast.Identifier{Name: "r"}},
|
|
{Key: &ast.Identifier{Name: "n"}, Value: &ast.IntegerLiteral{Value: 5}},
|
|
},
|
|
Body: &ast.BinaryExpression{
|
|
Operator: ast.AdditionOperator,
|
|
Left: &ast.Identifier{Name: "r"},
|
|
Right: &ast.Identifier{Name: "n"},
|
|
},
|
|
},
|
|
}},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "arrow function called in binary expression",
|
|
raw: `
|
|
plusOne = (r) => r + 1
|
|
plusOne(r:5) == 6 or die()
|
|
`,
|
|
want: &ast.Program{
|
|
Body: []ast.Statement{
|
|
&ast.VariableDeclaration{
|
|
Declarations: []*ast.VariableDeclarator{{
|
|
ID: &ast.Identifier{
|
|
Name: "plusOne",
|
|
},
|
|
Init: &ast.ArrowFunctionExpression{
|
|
Params: []*ast.Property{{Key: &ast.Identifier{Name: "r"}}},
|
|
Body: &ast.BinaryExpression{
|
|
Operator: ast.AdditionOperator,
|
|
Left: &ast.Identifier{Name: "r"},
|
|
Right: &ast.IntegerLiteral{Value: 1},
|
|
},
|
|
},
|
|
}},
|
|
},
|
|
&ast.ExpressionStatement{
|
|
Expression: &ast.LogicalExpression{
|
|
Operator: ast.OrOperator,
|
|
Left: &ast.BinaryExpression{
|
|
Operator: ast.EqualOperator,
|
|
Left: &ast.CallExpression{
|
|
Callee: &ast.Identifier{Name: "plusOne"},
|
|
Arguments: []ast.Expression{
|
|
&ast.ObjectExpression{
|
|
Properties: []*ast.Property{
|
|
{
|
|
Key: &ast.Identifier{
|
|
Name: "r",
|
|
},
|
|
Value: &ast.IntegerLiteral{
|
|
Value: 5,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
Right: &ast.IntegerLiteral{Value: 6},
|
|
},
|
|
Right: &ast.CallExpression{
|
|
Callee: &ast.Identifier{Name: "die"},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "arrow function as single expression",
|
|
raw: `f = (r) => r["_measurement"] == "cpu"`,
|
|
want: &ast.Program{
|
|
Body: []ast.Statement{
|
|
&ast.VariableDeclaration{
|
|
Declarations: []*ast.VariableDeclarator{{
|
|
ID: &ast.Identifier{
|
|
Name: "f",
|
|
},
|
|
Init: &ast.ArrowFunctionExpression{
|
|
Params: []*ast.Property{{Key: &ast.Identifier{Name: "r"}}},
|
|
Body: &ast.BinaryExpression{
|
|
Operator: ast.EqualOperator,
|
|
Left: &ast.MemberExpression{
|
|
Object: &ast.Identifier{Name: "r"},
|
|
Property: &ast.StringLiteral{Value: "_measurement"},
|
|
},
|
|
Right: &ast.StringLiteral{Value: "cpu"},
|
|
},
|
|
},
|
|
}},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "arrow function as block",
|
|
raw: `f = (r) => {
|
|
m = r["_measurement"]
|
|
return m == "cpu"
|
|
}`,
|
|
want: &ast.Program{
|
|
Body: []ast.Statement{
|
|
&ast.VariableDeclaration{
|
|
Declarations: []*ast.VariableDeclarator{{
|
|
ID: &ast.Identifier{
|
|
Name: "f",
|
|
},
|
|
Init: &ast.ArrowFunctionExpression{
|
|
Params: []*ast.Property{{Key: &ast.Identifier{Name: "r"}}},
|
|
Body: &ast.BlockStatement{
|
|
Body: []ast.Statement{
|
|
&ast.VariableDeclaration{
|
|
Declarations: []*ast.VariableDeclarator{{
|
|
ID: &ast.Identifier{
|
|
Name: "m",
|
|
},
|
|
Init: &ast.MemberExpression{
|
|
Object: &ast.Identifier{Name: "r"},
|
|
Property: &ast.StringLiteral{Value: "_measurement"},
|
|
},
|
|
}},
|
|
},
|
|
&ast.ReturnStatement{
|
|
Argument: &ast.BinaryExpression{
|
|
Operator: ast.EqualOperator,
|
|
Left: &ast.Identifier{Name: "m"},
|
|
Right: &ast.StringLiteral{Value: "cpu"},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "from with filter with no parens",
|
|
raw: `from(db:"telegraf").filter(fn: (r) => r["other"]=="mem" and r["this"]=="that" or r["these"]!="those")`,
|
|
want: &ast.Program{
|
|
Body: []ast.Statement{
|
|
&ast.ExpressionStatement{
|
|
Expression: &ast.CallExpression{
|
|
Callee: &ast.MemberExpression{
|
|
Property: &ast.Identifier{Name: "filter"},
|
|
Object: &ast.CallExpression{
|
|
Callee: &ast.Identifier{
|
|
Name: "from",
|
|
},
|
|
Arguments: []ast.Expression{
|
|
&ast.ObjectExpression{
|
|
Properties: []*ast.Property{
|
|
{
|
|
Key: &ast.Identifier{Name: "db"},
|
|
Value: &ast.StringLiteral{Value: "telegraf"},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
Arguments: []ast.Expression{
|
|
&ast.ObjectExpression{
|
|
Properties: []*ast.Property{
|
|
{
|
|
Key: &ast.Identifier{Name: "fn"},
|
|
Value: &ast.ArrowFunctionExpression{
|
|
Params: []*ast.Property{{Key: &ast.Identifier{Name: "r"}}},
|
|
Body: &ast.LogicalExpression{
|
|
Operator: ast.OrOperator,
|
|
Left: &ast.LogicalExpression{
|
|
Operator: ast.AndOperator,
|
|
Left: &ast.BinaryExpression{
|
|
Operator: ast.EqualOperator,
|
|
Left: &ast.MemberExpression{
|
|
Object: &ast.Identifier{Name: "r"},
|
|
Property: &ast.StringLiteral{Value: "other"},
|
|
},
|
|
Right: &ast.StringLiteral{Value: "mem"},
|
|
},
|
|
Right: &ast.BinaryExpression{
|
|
Operator: ast.EqualOperator,
|
|
Left: &ast.MemberExpression{
|
|
Object: &ast.Identifier{Name: "r"},
|
|
Property: &ast.StringLiteral{Value: "this"},
|
|
},
|
|
Right: &ast.StringLiteral{Value: "that"},
|
|
},
|
|
},
|
|
Right: &ast.BinaryExpression{
|
|
Operator: ast.NotEqualOperator,
|
|
Left: &ast.MemberExpression{
|
|
Object: &ast.Identifier{Name: "r"},
|
|
Property: &ast.StringLiteral{Value: "these"},
|
|
},
|
|
Right: &ast.StringLiteral{Value: "those"},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "from with range",
|
|
raw: `from(db:"telegraf")|>range(start:-1h, end:10m)`,
|
|
want: &ast.Program{
|
|
Body: []ast.Statement{
|
|
&ast.ExpressionStatement{
|
|
Expression: &ast.PipeExpression{
|
|
Argument: &ast.CallExpression{
|
|
Callee: &ast.Identifier{Name: "from"},
|
|
Arguments: []ast.Expression{
|
|
&ast.ObjectExpression{
|
|
Properties: []*ast.Property{
|
|
{
|
|
Key: &ast.Identifier{Name: "db"},
|
|
Value: &ast.StringLiteral{Value: "telegraf"},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
Call: &ast.CallExpression{
|
|
Callee: &ast.Identifier{Name: "range"},
|
|
Arguments: []ast.Expression{
|
|
&ast.ObjectExpression{
|
|
Properties: []*ast.Property{
|
|
{
|
|
Key: &ast.Identifier{Name: "start"},
|
|
Value: &ast.UnaryExpression{
|
|
Operator: ast.SubtractionOperator,
|
|
Argument: &ast.DurationLiteral{Value: time.Hour},
|
|
},
|
|
},
|
|
{
|
|
Key: &ast.Identifier{Name: "end"},
|
|
Value: &ast.DurationLiteral{Value: 10 * time.Minute},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "from with limit",
|
|
raw: `from(db:"telegraf")|>limit(limit:100, offset:10)`,
|
|
want: &ast.Program{
|
|
Body: []ast.Statement{
|
|
&ast.ExpressionStatement{
|
|
Expression: &ast.PipeExpression{
|
|
Argument: &ast.CallExpression{
|
|
Callee: &ast.Identifier{Name: "from"},
|
|
Arguments: []ast.Expression{
|
|
&ast.ObjectExpression{
|
|
Properties: []*ast.Property{
|
|
{
|
|
Key: &ast.Identifier{Name: "db"},
|
|
Value: &ast.StringLiteral{Value: "telegraf"},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
Call: &ast.CallExpression{
|
|
Callee: &ast.Identifier{Name: "limit"},
|
|
Arguments: []ast.Expression{
|
|
&ast.ObjectExpression{
|
|
Properties: []*ast.Property{
|
|
{
|
|
Key: &ast.Identifier{Name: "limit"},
|
|
Value: &ast.IntegerLiteral{Value: 100},
|
|
},
|
|
{
|
|
Key: &ast.Identifier{Name: "offset"},
|
|
Value: &ast.IntegerLiteral{Value: 10},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "from with range and count",
|
|
raw: `from(db:"mydb")
|
|
|> range(start:-4h, stop:-2h)
|
|
|> count()`,
|
|
want: &ast.Program{
|
|
Body: []ast.Statement{
|
|
&ast.ExpressionStatement{
|
|
Expression: &ast.PipeExpression{
|
|
Argument: &ast.PipeExpression{
|
|
Argument: &ast.CallExpression{
|
|
Callee: &ast.Identifier{Name: "from"},
|
|
Arguments: []ast.Expression{
|
|
&ast.ObjectExpression{
|
|
Properties: []*ast.Property{
|
|
{
|
|
Key: &ast.Identifier{Name: "db"},
|
|
Value: &ast.StringLiteral{Value: "mydb"},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
Call: &ast.CallExpression{
|
|
Callee: &ast.Identifier{Name: "range"},
|
|
Arguments: []ast.Expression{
|
|
&ast.ObjectExpression{
|
|
Properties: []*ast.Property{
|
|
{
|
|
Key: &ast.Identifier{Name: "start"},
|
|
Value: &ast.UnaryExpression{
|
|
Operator: ast.SubtractionOperator,
|
|
Argument: &ast.DurationLiteral{Value: 4 * time.Hour},
|
|
},
|
|
},
|
|
{
|
|
Key: &ast.Identifier{Name: "stop"},
|
|
Value: &ast.UnaryExpression{
|
|
Operator: ast.SubtractionOperator,
|
|
Argument: &ast.DurationLiteral{Value: 2 * time.Hour},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
Call: &ast.CallExpression{
|
|
Callee: &ast.Identifier{Name: "count"},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "from with range, limit and count",
|
|
raw: `from(db:"mydb")
|
|
|> range(start:-4h, stop:-2h)
|
|
|> limit(n:10)
|
|
|> count()`,
|
|
want: &ast.Program{
|
|
Body: []ast.Statement{
|
|
&ast.ExpressionStatement{
|
|
Expression: &ast.PipeExpression{
|
|
Argument: &ast.PipeExpression{
|
|
Argument: &ast.PipeExpression{
|
|
Argument: &ast.CallExpression{
|
|
Callee: &ast.Identifier{Name: "from"},
|
|
Arguments: []ast.Expression{
|
|
&ast.ObjectExpression{
|
|
Properties: []*ast.Property{
|
|
{
|
|
Key: &ast.Identifier{Name: "db"},
|
|
Value: &ast.StringLiteral{Value: "mydb"},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
Call: &ast.CallExpression{
|
|
Callee: &ast.Identifier{Name: "range"},
|
|
Arguments: []ast.Expression{
|
|
&ast.ObjectExpression{
|
|
Properties: []*ast.Property{
|
|
{
|
|
Key: &ast.Identifier{Name: "start"},
|
|
Value: &ast.UnaryExpression{
|
|
Operator: ast.SubtractionOperator,
|
|
Argument: &ast.DurationLiteral{Value: 4 * time.Hour},
|
|
},
|
|
},
|
|
{
|
|
Key: &ast.Identifier{Name: "stop"},
|
|
Value: &ast.UnaryExpression{
|
|
Operator: ast.SubtractionOperator,
|
|
Argument: &ast.DurationLiteral{Value: 2 * time.Hour},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
Call: &ast.CallExpression{
|
|
Callee: &ast.Identifier{Name: "limit"},
|
|
Arguments: []ast.Expression{
|
|
&ast.ObjectExpression{
|
|
Properties: []*ast.Property{{
|
|
Key: &ast.Identifier{Name: "n"},
|
|
Value: &ast.IntegerLiteral{Value: 10},
|
|
}},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
Call: &ast.CallExpression{
|
|
Callee: &ast.Identifier{Name: "count"},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "from with join",
|
|
raw: `
|
|
a = from(db:"dbA") |> range(start:-1h)
|
|
b = from(db:"dbB") |> range(start:-1h)
|
|
join(tables:[a,b], on:["host"], fn: (a,b) => a["_field"] + b["_field"])`,
|
|
want: &ast.Program{
|
|
Body: []ast.Statement{
|
|
&ast.VariableDeclaration{
|
|
Declarations: []*ast.VariableDeclarator{{
|
|
ID: &ast.Identifier{
|
|
Name: "a",
|
|
},
|
|
Init: &ast.PipeExpression{
|
|
Argument: &ast.CallExpression{
|
|
Callee: &ast.Identifier{Name: "from"},
|
|
Arguments: []ast.Expression{
|
|
&ast.ObjectExpression{
|
|
Properties: []*ast.Property{
|
|
{
|
|
Key: &ast.Identifier{Name: "db"},
|
|
Value: &ast.StringLiteral{Value: "dbA"},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
Call: &ast.CallExpression{
|
|
Callee: &ast.Identifier{Name: "range"},
|
|
Arguments: []ast.Expression{
|
|
&ast.ObjectExpression{
|
|
Properties: []*ast.Property{
|
|
{
|
|
Key: &ast.Identifier{Name: "start"},
|
|
Value: &ast.UnaryExpression{
|
|
Operator: ast.SubtractionOperator,
|
|
Argument: &ast.DurationLiteral{Value: 1 * time.Hour},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}},
|
|
},
|
|
&ast.VariableDeclaration{
|
|
Declarations: []*ast.VariableDeclarator{{
|
|
ID: &ast.Identifier{
|
|
Name: "b",
|
|
},
|
|
Init: &ast.PipeExpression{
|
|
Argument: &ast.CallExpression{
|
|
Callee: &ast.Identifier{Name: "from"},
|
|
Arguments: []ast.Expression{
|
|
&ast.ObjectExpression{
|
|
Properties: []*ast.Property{
|
|
{
|
|
Key: &ast.Identifier{Name: "db"},
|
|
Value: &ast.StringLiteral{Value: "dbB"},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
Call: &ast.CallExpression{
|
|
Callee: &ast.Identifier{Name: "range"},
|
|
Arguments: []ast.Expression{
|
|
&ast.ObjectExpression{
|
|
Properties: []*ast.Property{
|
|
{
|
|
Key: &ast.Identifier{Name: "start"},
|
|
Value: &ast.UnaryExpression{
|
|
Operator: ast.SubtractionOperator,
|
|
Argument: &ast.DurationLiteral{Value: 1 * time.Hour},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}},
|
|
},
|
|
&ast.ExpressionStatement{
|
|
Expression: &ast.CallExpression{
|
|
Callee: &ast.Identifier{Name: "join"},
|
|
Arguments: []ast.Expression{
|
|
&ast.ObjectExpression{
|
|
Properties: []*ast.Property{
|
|
{
|
|
Key: &ast.Identifier{Name: "tables"},
|
|
Value: &ast.ArrayExpression{
|
|
Elements: []ast.Expression{
|
|
&ast.Identifier{Name: "a"},
|
|
&ast.Identifier{Name: "b"},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
Key: &ast.Identifier{Name: "on"},
|
|
Value: &ast.ArrayExpression{
|
|
Elements: []ast.Expression{&ast.StringLiteral{Value: "host"}},
|
|
},
|
|
},
|
|
{
|
|
Key: &ast.Identifier{Name: "fn"},
|
|
Value: &ast.ArrowFunctionExpression{
|
|
Params: []*ast.Property{
|
|
{Key: &ast.Identifier{Name: "a"}},
|
|
{Key: &ast.Identifier{Name: "b"}},
|
|
},
|
|
Body: &ast.BinaryExpression{
|
|
Operator: ast.AdditionOperator,
|
|
Left: &ast.MemberExpression{
|
|
Object: &ast.Identifier{Name: "a"},
|
|
Property: &ast.StringLiteral{Value: "_field"},
|
|
},
|
|
Right: &ast.MemberExpression{
|
|
Object: &ast.Identifier{Name: "b"},
|
|
Property: &ast.StringLiteral{Value: "_field"},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "from with join with complex expression",
|
|
raw: `
|
|
a = from(db:"Flux")
|
|
|> filter(fn: (r) => r["_measurement"] == "a")
|
|
|> range(start:-1h)
|
|
|
|
b = from(db:"Flux")
|
|
|> filter(fn: (r) => r["_measurement"] == "b")
|
|
|> range(start:-1h)
|
|
|
|
join(tables:[a,b], on:["t1"], fn: (a,b) => (a["_field"] - b["_field"]) / b["_field"])
|
|
`,
|
|
want: &ast.Program{
|
|
Body: []ast.Statement{
|
|
&ast.VariableDeclaration{
|
|
Declarations: []*ast.VariableDeclarator{{
|
|
ID: &ast.Identifier{
|
|
Name: "a",
|
|
},
|
|
Init: &ast.PipeExpression{
|
|
Argument: &ast.PipeExpression{
|
|
Argument: &ast.CallExpression{
|
|
Callee: &ast.Identifier{Name: "from"},
|
|
Arguments: []ast.Expression{
|
|
&ast.ObjectExpression{
|
|
Properties: []*ast.Property{
|
|
{
|
|
Key: &ast.Identifier{Name: "db"},
|
|
Value: &ast.StringLiteral{Value: "Flux"},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
Call: &ast.CallExpression{
|
|
Callee: &ast.Identifier{Name: "filter"},
|
|
Arguments: []ast.Expression{
|
|
&ast.ObjectExpression{
|
|
Properties: []*ast.Property{
|
|
{
|
|
Key: &ast.Identifier{Name: "fn"},
|
|
Value: &ast.ArrowFunctionExpression{
|
|
Params: []*ast.Property{{Key: &ast.Identifier{Name: "r"}}},
|
|
Body: &ast.BinaryExpression{
|
|
Operator: ast.EqualOperator,
|
|
Left: &ast.MemberExpression{
|
|
Object: &ast.Identifier{Name: "r"},
|
|
Property: &ast.StringLiteral{Value: "_measurement"},
|
|
},
|
|
Right: &ast.StringLiteral{Value: "a"},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
Call: &ast.CallExpression{
|
|
Callee: &ast.Identifier{Name: "range"},
|
|
Arguments: []ast.Expression{
|
|
&ast.ObjectExpression{
|
|
Properties: []*ast.Property{
|
|
{
|
|
Key: &ast.Identifier{Name: "start"},
|
|
Value: &ast.UnaryExpression{
|
|
Operator: ast.SubtractionOperator,
|
|
Argument: &ast.DurationLiteral{Value: 1 * time.Hour},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}},
|
|
},
|
|
&ast.VariableDeclaration{
|
|
Declarations: []*ast.VariableDeclarator{{
|
|
ID: &ast.Identifier{
|
|
Name: "b",
|
|
},
|
|
Init: &ast.PipeExpression{
|
|
Argument: &ast.PipeExpression{
|
|
Argument: &ast.CallExpression{
|
|
Callee: &ast.Identifier{Name: "from"},
|
|
Arguments: []ast.Expression{
|
|
&ast.ObjectExpression{
|
|
Properties: []*ast.Property{
|
|
{
|
|
Key: &ast.Identifier{Name: "db"},
|
|
Value: &ast.StringLiteral{Value: "Flux"},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
Call: &ast.CallExpression{
|
|
Callee: &ast.Identifier{Name: "filter"},
|
|
Arguments: []ast.Expression{
|
|
&ast.ObjectExpression{
|
|
Properties: []*ast.Property{
|
|
{
|
|
Key: &ast.Identifier{Name: "fn"},
|
|
Value: &ast.ArrowFunctionExpression{
|
|
Params: []*ast.Property{{Key: &ast.Identifier{Name: "r"}}},
|
|
Body: &ast.BinaryExpression{
|
|
Operator: ast.EqualOperator,
|
|
Left: &ast.MemberExpression{
|
|
Object: &ast.Identifier{Name: "r"},
|
|
Property: &ast.StringLiteral{Value: "_measurement"},
|
|
},
|
|
Right: &ast.StringLiteral{Value: "b"},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
Call: &ast.CallExpression{
|
|
Callee: &ast.Identifier{Name: "range"},
|
|
Arguments: []ast.Expression{
|
|
&ast.ObjectExpression{
|
|
Properties: []*ast.Property{
|
|
{
|
|
Key: &ast.Identifier{Name: "start"},
|
|
Value: &ast.UnaryExpression{
|
|
Operator: ast.SubtractionOperator,
|
|
Argument: &ast.DurationLiteral{Value: 1 * time.Hour},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}},
|
|
},
|
|
&ast.ExpressionStatement{
|
|
Expression: &ast.CallExpression{
|
|
Callee: &ast.Identifier{Name: "join"},
|
|
Arguments: []ast.Expression{
|
|
&ast.ObjectExpression{
|
|
Properties: []*ast.Property{
|
|
{
|
|
Key: &ast.Identifier{Name: "tables"},
|
|
Value: &ast.ArrayExpression{
|
|
Elements: []ast.Expression{
|
|
&ast.Identifier{Name: "a"},
|
|
&ast.Identifier{Name: "b"},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
Key: &ast.Identifier{Name: "on"},
|
|
Value: &ast.ArrayExpression{
|
|
Elements: []ast.Expression{
|
|
&ast.StringLiteral{
|
|
Value: "t1",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
Key: &ast.Identifier{Name: "fn"},
|
|
Value: &ast.ArrowFunctionExpression{
|
|
Params: []*ast.Property{
|
|
{Key: &ast.Identifier{Name: "a"}},
|
|
{Key: &ast.Identifier{Name: "b"}},
|
|
},
|
|
Body: &ast.BinaryExpression{
|
|
Operator: ast.DivisionOperator,
|
|
Left: &ast.BinaryExpression{
|
|
Operator: ast.SubtractionOperator,
|
|
Left: &ast.MemberExpression{
|
|
Object: &ast.Identifier{Name: "a"},
|
|
Property: &ast.StringLiteral{Value: "_field"},
|
|
},
|
|
Right: &ast.MemberExpression{
|
|
Object: &ast.Identifier{Name: "b"},
|
|
Property: &ast.StringLiteral{Value: "_field"},
|
|
},
|
|
},
|
|
Right: &ast.MemberExpression{
|
|
Object: &ast.Identifier{Name: "b"},
|
|
Property: &ast.StringLiteral{Value: "_field"},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "parse error extra gibberish",
|
|
raw: `from(db:"Flux") &^*&H#IUJBN`,
|
|
wantErr: true,
|
|
},
|
|
{
|
|
name: "parse error extra gibberish and valid content",
|
|
raw: `from(db:"Flux") &^*&H#IUJBN from(db:"other")`,
|
|
wantErr: true,
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
tt := tt
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
t.Parallel()
|
|
// Set the env var`GO_TAGS=parser_debug` in order
|
|
// to turn on parser debugging as it is turned off by default.
|
|
got, err := parser.NewAST(tt.raw)
|
|
if (err != nil) != tt.wantErr {
|
|
t.Errorf("parser.NewAST() error = %v, wantErr %v", err, tt.wantErr)
|
|
return
|
|
}
|
|
if tt.wantErr {
|
|
return
|
|
}
|
|
if !cmp.Equal(tt.want, got, asttest.CompareOptions...) {
|
|
t.Errorf("parser.NewAST() = -want/+got %s", cmp.Diff(tt.want, got, asttest.CompareOptions...))
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
var benchmarkQuery = []byte(`
|
|
start = -10s
|
|
|
|
do = (cpu) =>
|
|
from(db:"telegraf")
|
|
.filter(fn: (r) =>
|
|
r["_measurement"] == "cpu"
|
|
and
|
|
r["cpu"] == cpu)
|
|
.range(start:start)
|
|
|
|
cpu0 = do(cpu:"cpu0")
|
|
cpu1 = do(cpu:"cpu1")
|
|
|
|
join(
|
|
tables:[cpu0, cpu1],
|
|
on:["_measurement","_field","host"],
|
|
fn: (a,b) => a["_value"] - b["_value"],
|
|
)
|
|
`)
|
|
|
|
var benchmarkProgram interface{}
|
|
|
|
func BenchmarkParse(b *testing.B) {
|
|
b.ReportAllocs()
|
|
var err error
|
|
for n := 0; n < b.N; n++ {
|
|
benchmarkProgram, err = parser.Parse("", benchmarkQuery)
|
|
if err != nil {
|
|
b.Fatal(err)
|
|
}
|
|
}
|
|
}
|