diff --git a/src/api/http/api_test.go b/src/api/http/api_test.go index 0a98a4ed01..e66e69e36d 100644 --- a/src/api/http/api_test.go +++ b/src/api/http/api_test.go @@ -315,29 +315,6 @@ func (self *ApiSuite) TestQueryWithSecondsPrecision(c *C) { c.Assert(int(series[0].Points[0][0].(float64)), Equals, 1381346631) } -func (self *ApiSuite) TestWritingToSeriesWithUnderscore(c *C) { - for _, name := range []string{"1foo", "_foo"} { - - data := fmt.Sprintf(` -[ - { - "points": [ - [1382131686, "1"] - ], - "name": "%s", - "columns": ["time", "column_one"] - } -] -`, name) - - addr := self.formatUrl("/db/db1/series?time_precision=s&u=dbuser&p=password") - resp, err := libhttp.Post(addr, "application/json", bytes.NewBufferString(data)) - c.Assert(err, IsNil) - c.Assert(resp.StatusCode, Equals, libhttp.StatusBadRequest) - c.Assert(self.coordinator.series, HasLen, 0) - } -} - func (self *ApiSuite) TestQueryWithInvalidPrecision(c *C) { query := "select * from foo where column_one == 'some_value';" query = url.QueryEscape(query) diff --git a/src/common/serialize_series.go b/src/common/serialize_series.go index da3859de41..2ea3c3471e 100644 --- a/src/common/serialize_series.go +++ b/src/common/serialize_series.go @@ -3,7 +3,6 @@ package common import ( "fmt" "protocol" - "regexp" ) var ( @@ -19,14 +18,7 @@ const ( SecondPrecision ) -var VALID_TABLE_NAMES *regexp.Regexp - func init() { - var err error - VALID_TABLE_NAMES, err = regexp.Compile("^[a-zA-Z][a-zA-Z0-9._-]*$") - if err != nil { - panic(err) - } } func removeField(fields []string, name string) []string { @@ -57,10 +49,6 @@ type ApiSeries interface { } func ConvertToDataStoreSeries(s ApiSeries, precision TimePrecision) (*protocol.Series, error) { - if !VALID_TABLE_NAMES.MatchString(s.GetName()) { - return nil, fmt.Errorf("%s is not a valid series name", s.GetName()) - } - points := []*protocol.Point{} for _, point := range s.GetPoints() { values := []*protocol.FieldValue{} diff --git a/src/coordinator/coordinator.go b/src/coordinator/coordinator.go index d2f1013066..49547ae65f 100644 --- a/src/coordinator/coordinator.go +++ b/src/coordinator/coordinator.go @@ -517,19 +517,6 @@ func (self *CoordinatorImpl) InterpolateValuesAndCommit(query string, db string, } sequenceMap := make(map[sequenceKey]int) r, _ := regexp.Compile(`\[.*?\]`) - replaceInvalidCharacters := func(r rune) rune { - switch { - case (r >= 'A' && r <= 'Z') || (r >= 'a' && r <= 'z') || (r >= '0' && r <= '9'): - return r - case r == '_' || r == '-' || r == '.': - return r - case r == ' ': - return '_' - case r == '/': - return '.' - } - return -1 - } if r.MatchString(targetName) { for _, point := range series.Points { @@ -539,16 +526,14 @@ func (self *CoordinatorImpl) InterpolateValuesAndCommit(query string, db string, return point.GetFieldValueAsString(fieldIndex) }) - sanitizedTargetName := strings.Map(replaceInvalidCharacters, targetNameWithValues) - if assignSequenceNumbers { - key := sequenceKey{sanitizedTargetName, *point.Timestamp} + key := sequenceKey{targetNameWithValues, *point.Timestamp} sequenceMap[key] += 1 sequenceNumber := uint64(sequenceMap[key]) point.SequenceNumber = &sequenceNumber } - newSeries := &protocol.Series{Name: &sanitizedTargetName, Fields: series.Fields, Points: []*protocol.Point{point}} + newSeries := &protocol.Series{Name: &targetNameWithValues, Fields: series.Fields, Points: []*protocol.Point{point}} if e := self.CommitSeriesData(db, []*protocol.Series{newSeries}); e != nil { log.Error("Couldn't write data for continuous query: ", e) } diff --git a/src/integration/data_test.go b/src/integration/data_test.go index ebf627f73e..c828b53f19 100644 --- a/src/integration/data_test.go +++ b/src/integration/data_test.go @@ -1416,3 +1416,22 @@ func (self *DataTestSuite) ListSeries(c *C) (Fun, Fun) { c.Assert(names["another_query"], Equals, true) } } + +// For issue #267 - allow all characters in series name - https://github.com/influxdb/influxdb/issues/267 +func (self *SingleServerSuite) SeriesNameWithWeirdCharacters(c *C) (Fun, Fun) { + return func(client Client) { + data := `[ + { + "name": "/blah ( ) ; : ! @ # $ \n \t,foo\"=bar/baz", + "columns": ["value"], + "points": [[1]] + } + ]` + client.WriteJsonData(data, c, "s") + }, func(client Client) { + data := client.RunQuery("select value from \"/blah ( ) ; : ! @ # $ \n \t,foo\\\"=bar/baz\"", c) + c.Assert(data, HasLen, 1) + c.Assert(data[0].Points, HasLen, 1) + c.Assert(data[0].Name, Equals, "/blah ( ) ; : ! @ # $ \n \t,foo\"=bar/baz") + } +} diff --git a/src/parser/parser_test.go b/src/parser/parser_test.go index 90e9ddc42c..d5caa9a563 100644 --- a/src/parser/parser_test.go +++ b/src/parser/parser_test.go @@ -2,9 +2,9 @@ package parser import ( "fmt" + . "launchpad.net/gocheck" "testing" "time" - . "launchpad.net/gocheck" ) // Hook up gocheck into the gotest runner. @@ -265,6 +265,14 @@ func (self *QueryParserSuite) TestParseListSeries(c *C) { c.Assert(queries[0].IsListQuery(), Equals, true) } +// issue #267 +func (self *QueryParserSuite) TestParseSelectWithWeirdCharacters(c *C) { + q, err := ParseSelectQuery("select a from \"/blah ( ) ; : ! @ # $ \n \t,foo\\\"=bar/baz\"") + c.Assert(err, IsNil) + c.Assert(q.GetFromClause().Names[0].Name.Name, Equals, "/blah ( ) ; : ! @ # $ \n \t,foo\"=bar/baz") + c.Assert(q.GetColumnNames(), HasLen, 1) +} + // issue #150 func (self *QueryParserSuite) TestParseSelectWithDivisionThatLooksLikeRegex(c *C) { q, err := ParseSelectQuery("select a/2, b/2 from x") diff --git a/src/parser/query.lex b/src/parser/query.lex index 9c9d6dfad8..389699cb4c 100644 --- a/src/parser/query.lex +++ b/src/parser/query.lex @@ -22,6 +22,7 @@ static int yycolumn = 1; %option noyywrap %s FROM_CLAUSE REGEX_CONDITION %x IN_REGEX +%x IN_TABLE_NAME %% ; { return *yytext; } @@ -100,6 +101,20 @@ true|false { yylval->string = strdup(yy [a-zA-Z0-9_][a-zA-Z0-9._-]* { yylval->string = strdup(yytext); return TABLE_NAME; } +\" { BEGIN(IN_TABLE_NAME); yylval->string=calloc(1, sizeof(char)); } +\\\" { + yylval->string = realloc(yylval->string, strlen(yylval->string) + 1); + strcat(yylval->string, "\""); +} +\" { + BEGIN(INITIAL); + return TABLE_NAME; +} +[^\\"]* { + yylval->string=realloc(yylval->string, strlen(yylval->string) + strlen(yytext) + 1); + strcat(yylval->string, yytext); +} + [:\[a-zA-Z0-9_][:\[\]a-zA-Z0-9._-]* { yylval->string = strdup(yytext); return INTO_NAME; } \'[^\']*\' {