Merge pull request #3541 from DanielMorsing/validateFields

check if fields are valid during parse.
pull/3560/head
Paul Dix 2015-08-04 11:03:33 -04:00
commit affd0b1ca2
3 changed files with 35 additions and 0 deletions

View File

@ -14,6 +14,7 @@
- [#3420](https://github.com/influxdb/influxdb/pull/3420): Catch opentsdb malformed tags. Thanks @nathanielc. - [#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 - [#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 - [#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] ## v0.9.2 [2015-07-24]

View File

@ -1471,11 +1471,18 @@ func (p *Parser) parseFields() (Fields, error) {
func (p *Parser) parseField() (*Field, error) { func (p *Parser) parseField() (*Field, error) {
f := &Field{} f := &Field{}
_, pos, _ := p.scanIgnoreWhitespace()
p.unscan()
// Parse the expression first. // Parse the expression first.
expr, err := p.ParseExpr() expr, err := p.ParseExpr()
if err != nil { if err != nil {
return nil, err 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 f.Expr = expr
// Parse the alias if the current and next tokens are "WS AS". // 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 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. // parseAlias parses the "AS (IDENT|STRING)" alias for fields and dimensions.
func (p *Parser) parseAlias() (string, error) { func (p *Parser) parseAlias() (string, error) {
// Check if the next token is "AS". If not, then unscan and exit. // Check if the next token is "AS". If not, then unscan and exit.

View File

@ -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() 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 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 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`, 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`, 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`}, {s: `DELETE FROM myseries WHERE`, err: `found EOF, expected identifier, string, number, bool at line 1, char 28`},