diff --git a/CHANGELOG.md b/CHANGELOG.md index 9ade8b1a7bc..11939cb11dd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ - [#2190](https://github.com/influxdb/influxdb/pull/2190): Implement failover to other data nodes for distributed queries - [#2324](https://github.com/influxdb/influxdb/issues/2324): Race in Broker.Close()/Broker.RunContinousQueryProcessing() - [#2325](https://github.com/influxdb/influxdb/pull/2325): Cluster open fixes +- [#2326](https://github.com/influxdb/influxdb/pull/2326): Fix parse error in CREATE CONTINUOUS QUERY ## v0.9.0-rc25 [2015-04-15] diff --git a/cmd/influxd/server_integration_test.go b/cmd/influxd/server_integration_test.go index 3ef19ccc355..1446aafabf8 100644 --- a/cmd/influxd/server_integration_test.go +++ b/cmd/influxd/server_integration_test.go @@ -1282,13 +1282,13 @@ func runTestsData(t *testing.T, testName string, nodes Cluster, database, retent // Continuous query control. { name: "create continuous query", - query: `CREATE CONTINUOUS QUERY myquery ON %DB% BEGIN SELECT count(value) INTO measure1 FROM myseries GROUP BY time(10m) END`, + query: `CREATE CONTINUOUS QUERY "my.query" ON %DB% BEGIN SELECT count(value) INTO measure1 FROM myseries GROUP BY time(10m) END`, queryOne: true, expected: `{"results":[{}]}`, }, { query: `SHOW CONTINUOUS QUERIES`, - expected: `{"results":[{"series":[{"name":"%DB%","columns":["name","query"],"values":[["myquery","CREATE CONTINUOUS QUERY myquery ON %DB% BEGIN SELECT count(value) INTO \"%DB%\".\"%RP%\".measure1 FROM \"%DB%\".\"%RP%\".myseries GROUP BY time(10m) END"]]}]}]}`, + expected: `{"results":[{"series":[{"name":"%DB%","columns":["name","query"],"values":[["my.query","CREATE CONTINUOUS QUERY \"my.query\" ON %DB% BEGIN SELECT count(value) INTO \"%DB%\".\"%RP%\".measure1 FROM \"%DB%\".\"%RP%\".myseries GROUP BY time(10m) END"]]}]}]}`, }, } diff --git a/influxql/ast.go b/influxql/ast.go index b5c2e11fb94..ed26e8f5a19 100644 --- a/influxql/ast.go +++ b/influxql/ast.go @@ -1281,7 +1281,7 @@ type CreateContinuousQueryStatement struct { // String returns a string representation of the statement. func (s *CreateContinuousQueryStatement) String() string { - return fmt.Sprintf("CREATE CONTINUOUS QUERY %s ON %s BEGIN %s END", s.Name, s.Database, s.Source.String()) + return fmt.Sprintf("CREATE CONTINUOUS QUERY %s ON %s BEGIN %s END", QuoteIdent(s.Name), QuoteIdent(s.Database), s.Source.String()) } // DefaultDatabase returns the default database from the statement. diff --git a/influxql/parser_test.go b/influxql/parser_test.go index 21349d1ba9a..1e6c7a7401e 100644 --- a/influxql/parser_test.go +++ b/influxql/parser_test.go @@ -614,6 +614,20 @@ func TestParser_ParseStatement(t *testing.T) { }, }, + { + s: `create continuous query "this.is-a.test" on segments begin select * into measure1 from cpu_load_short end`, + stmt: &influxql.CreateContinuousQueryStatement{ + Name: "this.is-a.test", + Database: "segments", + Source: &influxql.SelectStatement{ + IsRawQuery: true, + Fields: []*influxql.Field{{Expr: &influxql.Wildcard{}}}, + Target: &influxql.Target{Measurement: &influxql.Measurement{Name: "measure1"}}, + Sources: []influxql.Source{&influxql.Measurement{Name: "cpu_load_short"}}, + }, + }, + }, + // CREATE CONTINUOUS QUERY ... INTO . { s: `CREATE CONTINUOUS QUERY myquery ON testdb BEGIN SELECT count() INTO "1h.policy1"."cpu.load" FROM myseries GROUP BY time(5m) END`, @@ -647,7 +661,8 @@ func TestParser_ParseStatement(t *testing.T) { Name: "myquery", Database: "testdb", Source: &influxql.SelectStatement{ - Fields: []*influxql.Field{{Expr: &influxql.Call{Name: "value"}}}, + IsRawQuery: true, + Fields: []*influxql.Field{{Expr: &influxql.VarRef{Val: "value"}}}, Target: &influxql.Target{ Measurement: &influxql.Measurement{RetentionPolicy: "policy1", Name: "value"}, }, @@ -663,8 +678,9 @@ func TestParser_ParseStatement(t *testing.T) { Name: "myquery", Database: "testdb", Source: &influxql.SelectStatement{ - Fields: []*influxql.Field{{Expr: &influxql.Call{Name: "transmit_rx"}}, - {Expr: &influxql.Call{Name: "transmit_tx"}}}, + IsRawQuery: true, + Fields: []*influxql.Field{{Expr: &influxql.VarRef{Val: "transmit_rx"}}, + {Expr: &influxql.VarRef{Val: "transmit_tx"}}}, Target: &influxql.Target{ Measurement: &influxql.Measurement{RetentionPolicy: "policy1", Name: "network"}, }, @@ -1035,13 +1051,14 @@ func TestParser_ParseStatement(t *testing.T) { // We are memoizing a field so for testing we need to... if s, ok := tt.stmt.(*influxql.SelectStatement); ok { s.GroupByInterval() - } - if !reflect.DeepEqual(tt.err, errstring(err)) { - t.Errorf("%d. %q: error mismatch:\n exp=%s\n got=%s\n\n", i, tt.s, tt.err, err) } else if st, ok := stmt.(*influxql.CreateContinuousQueryStatement); ok { // if it's a CQ, there is a non-exported field that gets memoized during parsing that needs to be set if st != nil && st.Source != nil { tt.stmt.(*influxql.CreateContinuousQueryStatement).Source.GroupByInterval() } + } + + if !reflect.DeepEqual(tt.err, errstring(err)) { + 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.stmt, stmt) { t.Logf("exp=%s\ngot=%s\n", mustMarshalJSON(tt.stmt), mustMarshalJSON(stmt)) t.Errorf("%d. %q\n\nstmt mismatch:\n\nexp=%#v\n\ngot=%#v\n\n", i, tt.s, tt.stmt, stmt)