diff --git a/CHANGELOG.md b/CHANGELOG.md index 4396dadf3c..b2ab13187c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ - [#3420](https://github.com/influxdb/influxdb/pull/3420): Catch opentsdb malformed tags. Thanks @nathanielc. - [#3404](https://github.com/influxdb/influxdb/pull/3404): Added support for escaped single quotes in query string. Thanks @jhorwit2 - [#3414](https://github.com/influxdb/influxdb/issues/3414): Shard mappers perform query re-writing +- [#3525](https://github.com/influxdb/influxdb/pull/3525): check if fields are valid during parse time. ## v0.9.2 [2015-07-24] diff --git a/influxql/parser.go b/influxql/parser.go index 6a8e34913d..f995441ace 100644 --- a/influxql/parser.go +++ b/influxql/parser.go @@ -1471,11 +1471,18 @@ func (p *Parser) parseFields() (Fields, error) { func (p *Parser) parseField() (*Field, error) { f := &Field{} + _, pos, _ := p.scanIgnoreWhitespace() + p.unscan() // Parse the expression first. expr, err := p.ParseExpr() if err != nil { return nil, err } + var c validateField + Walk(&c, expr) + if c.foundInvalid { + return nil, fmt.Errorf("invalid operator %s in SELECT clause at line %d, char %d; operator is intended for WHERE clause", c.badToken, pos.Line+1, pos.Char+1) + } f.Expr = expr // Parse the alias if the current and next tokens are "WS AS". @@ -1491,6 +1498,30 @@ func (p *Parser) parseField() (*Field, error) { return f, nil } +// validateField checks if the Expr is a valid field. We disallow all binary expression +// that return a boolean +type validateField struct { + foundInvalid bool + badToken Token +} + +func (c *validateField) Visit(n Node) Visitor { + e, ok := n.(*BinaryExpr) + if !ok { + return c + } + + switch e.Op { + case EQ, NEQ, EQREGEX, + NEQREGEX, LT, LTE, GT, GTE, + AND, OR: + c.foundInvalid = true + c.badToken = e.Op + return nil + } + return c +} + // parseAlias parses the "AS (IDENT|STRING)" alias for fields and dimensions. func (p *Parser) parseAlias() (string, error) { // Check if the next token is "AS". If not, then unscan and exit. diff --git a/influxql/parser_test.go b/influxql/parser_test.go index 2e1e9ffd79..2ea53a0ed2 100644 --- a/influxql/parser_test.go +++ b/influxql/parser_test.go @@ -1244,6 +1244,9 @@ func TestParser_ParseStatement(t *testing.T) { {s: `select derivative() from myseries`, err: `invalid number of arguments for derivative, expected at least 1 but no more than 2, got 0`}, {s: `select derivative(mean(value), 1h, 3) from myseries`, err: `invalid number of arguments for derivative, expected at least 1 but no more than 2, got 3`}, {s: `SELECT field1 from myseries WHERE host =~ 'asd' LIMIT 1`, err: `found asd, expected regex at line 1, char 42`}, + {s: `SELECT value > 2 FROM cpu`, err: `invalid operator > in SELECT clause at line 1, char 8; operator is intended for WHERE clause`}, + {s: `SELECT value = 2 FROM cpu`, err: `invalid operator = in SELECT clause at line 1, char 8; operator is intended for WHERE clause`}, + {s: `SELECT s =~ /foo/ FROM cpu`, err: `invalid operator =~ in SELECT clause at line 1, char 8; operator is intended for WHERE clause`}, {s: `DELETE`, err: `found EOF, expected FROM at line 1, char 8`}, {s: `DELETE FROM`, err: `found EOF, expected identifier at line 1, char 13`}, {s: `DELETE FROM myseries WHERE`, err: `found EOF, expected identifier, string, number, bool at line 1, char 28`},