diff --git a/influxql/parser_test.go b/influxql/parser_test.go index 194dbba2d4..f3af57742e 100644 --- a/influxql/parser_test.go +++ b/influxql/parser_test.go @@ -2817,6 +2817,62 @@ func TestParser_ParseExpr(t *testing.T) { }, }, + // Binary expression with LHS precedence + { + s: `1 / 2 + 3`, + expr: &influxql.BinaryExpr{ + Op: influxql.ADD, + LHS: &influxql.BinaryExpr{ + Op: influxql.DIV, + LHS: &influxql.IntegerLiteral{Val: 1}, + RHS: &influxql.IntegerLiteral{Val: 2}, + }, + RHS: &influxql.IntegerLiteral{Val: 3}, + }, + }, + + // Binary expression with RHS precedence + { + s: `1 + 2 / 3`, + expr: &influxql.BinaryExpr{ + Op: influxql.ADD, + LHS: &influxql.IntegerLiteral{Val: 1}, + RHS: &influxql.BinaryExpr{ + Op: influxql.DIV, + LHS: &influxql.IntegerLiteral{Val: 2}, + RHS: &influxql.IntegerLiteral{Val: 3}, + }, + }, + }, + + // Binary expression with LHS precedence + { + s: `1 % 2 + 3`, + expr: &influxql.BinaryExpr{ + Op: influxql.ADD, + LHS: &influxql.BinaryExpr{ + Op: influxql.MOD, + LHS: &influxql.IntegerLiteral{Val: 1}, + RHS: &influxql.IntegerLiteral{Val: 2}, + }, + RHS: &influxql.IntegerLiteral{Val: 3}, + }, + }, + + // Binary expression with RHS precedence + { + s: `1 + 2 % 3`, + expr: &influxql.BinaryExpr{ + Op: influxql.ADD, + LHS: &influxql.IntegerLiteral{Val: 1}, + RHS: &influxql.BinaryExpr{ + Op: influxql.MOD, + LHS: &influxql.IntegerLiteral{Val: 2}, + RHS: &influxql.IntegerLiteral{Val: 3}, + }, + }, + }, + // Binary expression with LHS paren group. { s: `(1 + 2) * 3`, @@ -2950,6 +3006,16 @@ func TestParser_ParseExpr(t *testing.T) { t.Errorf("%d. %q: error mismatch:\n exp=%s\n got=%s\n\n", i, tt.s, tt.err, err) } else if tt.err == "" && !reflect.DeepEqual(tt.expr, expr) { t.Errorf("%d. %q\n\nexpr mismatch:\n\nexp=%#v\n\ngot=%#v\n\n", i, tt.s, tt.expr, expr) + } else if err == nil { + // Attempt to reparse the expr as a string and confirm it parses the same. + expr2, err := influxql.ParseExpr(expr.String()) + if err != nil { + t.Errorf("%d. %q: unable to parse expr string: %s", i, expr.String(), err) + } else if !reflect.DeepEqual(tt.expr, expr2) { + t.Logf("\n# %s\nexp=%s\ngot=%s\n", tt.s, mustMarshalJSON(tt.expr), mustMarshalJSON(expr2)) + t.Logf("\nSQL exp=%s\nSQL got=%s\n", tt.expr.String(), expr2.String()) + t.Errorf("%d. %q\n\nexpr reparse mismatch:\n\nexp=%#v\n\ngot=%#v\n\n", i, tt.s, tt.expr, expr2) + } } } } diff --git a/influxql/token.go b/influxql/token.go index 80867cb64e..a2e17b04cb 100644 --- a/influxql/token.go +++ b/influxql/token.go @@ -156,6 +156,7 @@ var tokens = [...]string{ SUB: "-", MUL: "*", DIV: "/", + MOD: "%", AND: "AND", OR: "OR", @@ -285,7 +286,7 @@ func (tok Token) Precedence() int { return 3 case ADD, SUB: return 4 - case MUL, DIV: + case MUL, DIV, MOD: return 5 } return 0