From eda74a25f11005f3ea016d8aec957915de2ed13f Mon Sep 17 00:00:00 2001 From: Cory LaNou Date: Thu, 12 Mar 2015 18:20:58 -0600 Subject: [PATCH 1/3] allow offset 0 --- influxql/parser.go | 32 ++++++++++++++++---------------- influxql/parser_test.go | 12 ++++++++++++ server_test.go | 8 ++++++++ 3 files changed, 36 insertions(+), 16 deletions(-) diff --git a/influxql/parser.go b/influxql/parser.go index c21215d8992..dfc8ace39b8 100644 --- a/influxql/parser.go +++ b/influxql/parser.go @@ -564,22 +564,22 @@ func (p *Parser) parseSelectStatement(tr targetRequirement) (*SelectStatement, e } // Parse limit: "LIMIT ". - if stmt.Limit, err = p.parseOptionalTokenAndInt(LIMIT); err != nil { + if stmt.Limit, err = p.parseOptionalTokenAndInt(LIMIT, false); err != nil { return nil, err } // Parse offset: "OFFSET ". - if stmt.Offset, err = p.parseOptionalTokenAndInt(OFFSET); err != nil { + if stmt.Offset, err = p.parseOptionalTokenAndInt(OFFSET, false); err != nil { return nil, err } // Parse series limit: "SLIMIT ". - if stmt.SLimit, err = p.parseOptionalTokenAndInt(SLIMIT); err != nil { + if stmt.SLimit, err = p.parseOptionalTokenAndInt(SLIMIT, false); err != nil { return nil, err } // Parse series offset: "SOFFSET ". - if stmt.SOffset, err = p.parseOptionalTokenAndInt(SOFFSET); err != nil { + if stmt.SOffset, err = p.parseOptionalTokenAndInt(SOFFSET, false); err != nil { return nil, err } @@ -679,12 +679,12 @@ func (p *Parser) parseShowSeriesStatement() (*ShowSeriesStatement, error) { } // Parse limit: "LIMIT ". - if stmt.Limit, err = p.parseOptionalTokenAndInt(LIMIT); err != nil { + if stmt.Limit, err = p.parseOptionalTokenAndInt(LIMIT, false); err != nil { return nil, err } // Parse offset: "OFFSET ". - if stmt.Offset, err = p.parseOptionalTokenAndInt(OFFSET); err != nil { + if stmt.Offset, err = p.parseOptionalTokenAndInt(OFFSET, true); err != nil { return nil, err } @@ -708,12 +708,12 @@ func (p *Parser) parseShowMeasurementsStatement() (*ShowMeasurementsStatement, e } // Parse limit: "LIMIT ". - if stmt.Limit, err = p.parseOptionalTokenAndInt(LIMIT); err != nil { + if stmt.Limit, err = p.parseOptionalTokenAndInt(LIMIT, false); err != nil { return nil, err } // Parse offset: "OFFSET ". - if stmt.Offset, err = p.parseOptionalTokenAndInt(OFFSET); err != nil { + if stmt.Offset, err = p.parseOptionalTokenAndInt(OFFSET, false); err != nil { return nil, err } @@ -760,12 +760,12 @@ func (p *Parser) parseShowTagKeysStatement() (*ShowTagKeysStatement, error) { } // Parse limit: "LIMIT ". - if stmt.Limit, err = p.parseOptionalTokenAndInt(LIMIT); err != nil { + if stmt.Limit, err = p.parseOptionalTokenAndInt(LIMIT, false); err != nil { return nil, err } // Parse offset: "OFFSET ". - if stmt.Offset, err = p.parseOptionalTokenAndInt(OFFSET); err != nil { + if stmt.Offset, err = p.parseOptionalTokenAndInt(OFFSET, false); err != nil { return nil, err } @@ -803,12 +803,12 @@ func (p *Parser) parseShowTagValuesStatement() (*ShowTagValuesStatement, error) } // Parse limit: "LIMIT ". - if stmt.Limit, err = p.parseOptionalTokenAndInt(LIMIT); err != nil { + if stmt.Limit, err = p.parseOptionalTokenAndInt(LIMIT, false); err != nil { return nil, err } // Parse offset: "OFFSET ". - if stmt.Offset, err = p.parseOptionalTokenAndInt(OFFSET); err != nil { + if stmt.Offset, err = p.parseOptionalTokenAndInt(OFFSET, false); err != nil { return nil, err } @@ -883,12 +883,12 @@ func (p *Parser) parseShowFieldKeysStatement() (*ShowFieldKeysStatement, error) } // Parse limit: "LIMIT ". - if stmt.Limit, err = p.parseOptionalTokenAndInt(LIMIT); err != nil { + if stmt.Limit, err = p.parseOptionalTokenAndInt(LIMIT, false); err != nil { return nil, err } // Parse offset: "OFFSET ". - if stmt.Offset, err = p.parseOptionalTokenAndInt(OFFSET); err != nil { + if stmt.Offset, err = p.parseOptionalTokenAndInt(OFFSET, false); err != nil { return nil, err } @@ -1413,7 +1413,7 @@ func (p *Parser) parseFill() (FillOption, interface{}, error) { // parseOptionalTokenAndInt parses the specified token followed // by an int, if it exists. -func (p *Parser) parseOptionalTokenAndInt(t Token) (int, error) { +func (p *Parser) parseOptionalTokenAndInt(t Token, allowZero bool) (int, error) { // Check if the token exists. if tok, _, _ := p.scanIgnoreWhitespace(); tok != t { p.unscan() @@ -1435,7 +1435,7 @@ func (p *Parser) parseOptionalTokenAndInt(t Token) (int, error) { // Parse number. n, _ := strconv.ParseInt(lit, 10, 64) - if n < 1 { + if n < 1 && !allowZero { msg := fmt.Sprintf("%s must be > 0", t.String()) return 0, &ParseError{Message: msg, Pos: pos} } diff --git a/influxql/parser_test.go b/influxql/parser_test.go index ebbd806e878..5cb6b6520bf 100644 --- a/influxql/parser_test.go +++ b/influxql/parser_test.go @@ -244,6 +244,18 @@ func TestParser_ParseStatement(t *testing.T) { stmt: &influxql.ShowSeriesStatement{}, }, + // SHOW SERIES with OFFSET 0 + { + s: `SHOW SERIES OFFSET 0`, + stmt: &influxql.ShowSeriesStatement{Offset: 0}, + }, + + // SHOW SERIES with LIMIT 2 OFFSET 0 + { + s: `SHOW SERIES LIMIT 2 OFFSET 0`, + stmt: &influxql.ShowSeriesStatement{Offset: 0, Limit: 2}, + }, + // SHOW SERIES WHERE with ORDER BY and LIMIT { s: `SHOW SERIES WHERE region = 'uswest' ORDER BY ASC, field1, field2 DESC LIMIT 10`, diff --git a/server_test.go b/server_test.go index 510747319d8..9de930c4791 100644 --- a/server_test.go +++ b/server_test.go @@ -1609,6 +1609,14 @@ func TestServer_ShowSeriesLimitOffset(t *testing.T) { t.Fatalf("unexpected row count: %d", len(res.Series)) } + // Select data from the server. + results = s.ExecuteQuery(MustParseQuery(`SHOW SERIES LIMIT 4 OFFSET 0`), "foo", nil) + if res := results.Results[0]; res.Err != nil { + t.Fatalf("unexpected error: %s", res.Err) + } else if len(res.Series) != 2 { + t.Fatalf("unexpected row count: %d", len(res.Series)) + } + // Select data from the server. results = s.ExecuteQuery(MustParseQuery(`SHOW SERIES LIMIT 20`), "foo", nil) if res := results.Results[0]; res.Err != nil { From bdfb9bfa0b001d1bd34f1427f280ad3a9200c78a Mon Sep 17 00:00:00 2001 From: Cory LaNou Date: Thu, 12 Mar 2015 18:23:51 -0600 Subject: [PATCH 2/3] update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e4e9b50956d..2468d8ae02b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ - [#1930](https://github.com/influxdb/influxdb/pull/1930): Auto create database for graphite if not specified. - [#1908](https://github.com/influxdb/influxdb/pull/1908): Cosmetic CLI output fixes. - [#1931](https://github.com/influxdb/influxdb/pull/1931): Add default column to SHOW RETENTION POLICIES. +- [#1937](https://github.com/influxdb/influxdb/pull/1937): OFFSET should be allowed to be 0. ### Features - [#1902](https://github.com/influxdb/influxdb/pull/1902): Enforce retention policies to have a minimum duration. From 08b15d937092bcd6d0a4a871284a63c796ef9162 Mon Sep 17 00:00:00 2001 From: Cory LaNou Date: Thu, 12 Mar 2015 18:59:38 -0600 Subject: [PATCH 3/3] zeros are ok after all --- influxql/parser.go | 34 +++++++++++++++++----------------- influxql/parser_test.go | 2 -- 2 files changed, 17 insertions(+), 19 deletions(-) diff --git a/influxql/parser.go b/influxql/parser.go index dfc8ace39b8..6aacaa407a6 100644 --- a/influxql/parser.go +++ b/influxql/parser.go @@ -564,22 +564,22 @@ func (p *Parser) parseSelectStatement(tr targetRequirement) (*SelectStatement, e } // Parse limit: "LIMIT ". - if stmt.Limit, err = p.parseOptionalTokenAndInt(LIMIT, false); err != nil { + if stmt.Limit, err = p.parseOptionalTokenAndInt(LIMIT); err != nil { return nil, err } // Parse offset: "OFFSET ". - if stmt.Offset, err = p.parseOptionalTokenAndInt(OFFSET, false); err != nil { + if stmt.Offset, err = p.parseOptionalTokenAndInt(OFFSET); err != nil { return nil, err } // Parse series limit: "SLIMIT ". - if stmt.SLimit, err = p.parseOptionalTokenAndInt(SLIMIT, false); err != nil { + if stmt.SLimit, err = p.parseOptionalTokenAndInt(SLIMIT); err != nil { return nil, err } // Parse series offset: "SOFFSET ". - if stmt.SOffset, err = p.parseOptionalTokenAndInt(SOFFSET, false); err != nil { + if stmt.SOffset, err = p.parseOptionalTokenAndInt(SOFFSET); err != nil { return nil, err } @@ -679,12 +679,12 @@ func (p *Parser) parseShowSeriesStatement() (*ShowSeriesStatement, error) { } // Parse limit: "LIMIT ". - if stmt.Limit, err = p.parseOptionalTokenAndInt(LIMIT, false); err != nil { + if stmt.Limit, err = p.parseOptionalTokenAndInt(LIMIT); err != nil { return nil, err } // Parse offset: "OFFSET ". - if stmt.Offset, err = p.parseOptionalTokenAndInt(OFFSET, true); err != nil { + if stmt.Offset, err = p.parseOptionalTokenAndInt(OFFSET); err != nil { return nil, err } @@ -708,12 +708,12 @@ func (p *Parser) parseShowMeasurementsStatement() (*ShowMeasurementsStatement, e } // Parse limit: "LIMIT ". - if stmt.Limit, err = p.parseOptionalTokenAndInt(LIMIT, false); err != nil { + if stmt.Limit, err = p.parseOptionalTokenAndInt(LIMIT); err != nil { return nil, err } // Parse offset: "OFFSET ". - if stmt.Offset, err = p.parseOptionalTokenAndInt(OFFSET, false); err != nil { + if stmt.Offset, err = p.parseOptionalTokenAndInt(OFFSET); err != nil { return nil, err } @@ -760,12 +760,12 @@ func (p *Parser) parseShowTagKeysStatement() (*ShowTagKeysStatement, error) { } // Parse limit: "LIMIT ". - if stmt.Limit, err = p.parseOptionalTokenAndInt(LIMIT, false); err != nil { + if stmt.Limit, err = p.parseOptionalTokenAndInt(LIMIT); err != nil { return nil, err } // Parse offset: "OFFSET ". - if stmt.Offset, err = p.parseOptionalTokenAndInt(OFFSET, false); err != nil { + if stmt.Offset, err = p.parseOptionalTokenAndInt(OFFSET); err != nil { return nil, err } @@ -803,12 +803,12 @@ func (p *Parser) parseShowTagValuesStatement() (*ShowTagValuesStatement, error) } // Parse limit: "LIMIT ". - if stmt.Limit, err = p.parseOptionalTokenAndInt(LIMIT, false); err != nil { + if stmt.Limit, err = p.parseOptionalTokenAndInt(LIMIT); err != nil { return nil, err } // Parse offset: "OFFSET ". - if stmt.Offset, err = p.parseOptionalTokenAndInt(OFFSET, false); err != nil { + if stmt.Offset, err = p.parseOptionalTokenAndInt(OFFSET); err != nil { return nil, err } @@ -883,12 +883,12 @@ func (p *Parser) parseShowFieldKeysStatement() (*ShowFieldKeysStatement, error) } // Parse limit: "LIMIT ". - if stmt.Limit, err = p.parseOptionalTokenAndInt(LIMIT, false); err != nil { + if stmt.Limit, err = p.parseOptionalTokenAndInt(LIMIT); err != nil { return nil, err } // Parse offset: "OFFSET ". - if stmt.Offset, err = p.parseOptionalTokenAndInt(OFFSET, false); err != nil { + if stmt.Offset, err = p.parseOptionalTokenAndInt(OFFSET); err != nil { return nil, err } @@ -1413,7 +1413,7 @@ func (p *Parser) parseFill() (FillOption, interface{}, error) { // parseOptionalTokenAndInt parses the specified token followed // by an int, if it exists. -func (p *Parser) parseOptionalTokenAndInt(t Token, allowZero bool) (int, error) { +func (p *Parser) parseOptionalTokenAndInt(t Token) (int, error) { // Check if the token exists. if tok, _, _ := p.scanIgnoreWhitespace(); tok != t { p.unscan() @@ -1435,8 +1435,8 @@ func (p *Parser) parseOptionalTokenAndInt(t Token, allowZero bool) (int, error) // Parse number. n, _ := strconv.ParseInt(lit, 10, 64) - if n < 1 && !allowZero { - msg := fmt.Sprintf("%s must be > 0", t.String()) + if n < 0 { + msg := fmt.Sprintf("%s must be >= 0", t.String()) return 0, &ParseError{Message: msg, Pos: pos} } diff --git a/influxql/parser_test.go b/influxql/parser_test.go index 5cb6b6520bf..00a2606069b 100644 --- a/influxql/parser_test.go +++ b/influxql/parser_test.go @@ -778,10 +778,8 @@ func TestParser_ParseStatement(t *testing.T) { {s: `SELECT field1 FROM myseries GROUP`, err: `found EOF, expected BY at line 1, char 35`}, {s: `SELECT field1 FROM myseries LIMIT`, err: `found EOF, expected number at line 1, char 35`}, {s: `SELECT field1 FROM myseries LIMIT 10.5`, err: `fractional parts not allowed in LIMIT at line 1, char 35`}, - {s: `SELECT field1 FROM myseries LIMIT 0`, err: `LIMIT must be > 0 at line 1, char 35`}, {s: `SELECT field1 FROM myseries OFFSET`, err: `found EOF, expected number at line 1, char 36`}, {s: `SELECT field1 FROM myseries OFFSET 10.5`, err: `fractional parts not allowed in OFFSET at line 1, char 36`}, - {s: `SELECT field1 FROM myseries OFFSET 0`, err: `OFFSET must be > 0 at line 1, char 36`}, {s: `SELECT field1 FROM myseries ORDER`, err: `found EOF, expected BY at line 1, char 35`}, {s: `SELECT field1 FROM myseries ORDER BY /`, err: `found /, expected identifier, ASC, or DESC at line 1, char 38`}, {s: `SELECT field1 FROM myseries ORDER BY 1`, err: `found 1, expected identifier, ASC, or DESC at line 1, char 38`},