diff --git a/CHANGELOG.md b/CHANGELOG.md index 60511ee2f1a..62b29db989a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ - [2829](https://github.com/influxdb/influxdb/pull/2829) -- Re-enable Graphite support as a new Service-style component. - [2814](https://github.com/influxdb/influxdb/issues/2814) -- Convert collectd to a service. - [2852](https://github.com/influxdb/influxdb/pull/2852) -- Don't panic when altering retention policies. Thanks for the report @huhongbo +- [2857](https://github.com/influxdb/influxdb/issues/2857) -- Fix parsing commas in string field values. ## v0.9.0-rc32 [2015-06-07] diff --git a/tsdb/points.go b/tsdb/points.go index 2a2b1f4d858..8c4406ed103 100644 --- a/tsdb/points.go +++ b/tsdb/points.go @@ -436,6 +436,33 @@ func scanTagValue(buf []byte, i int) (int, []byte) { return i, buf[start:i] } +func scanFieldValue(buf []byte, i int) (int, []byte) { + start := i + quoted := false + for { + if i >= len(buf) { + break + } + + if buf[i] == '"' { + i += 1 + quoted = !quoted + continue + } + + if buf[i] == '\\' { + i += 2 + continue + } + + if buf[i] == ',' && !quoted { + break + } + i += 1 + } + return i, buf[start:i] +} + func escape(in []byte) []byte { for b, esc := range escapeCodes { in = bytes.Replace(in, []byte{b}, esc, -1) @@ -700,7 +727,7 @@ func newFieldsFromBinary(buf []byte) Fields { continue } - i, valueBuf = scanTo(buf, i+1, ',') + i, valueBuf = scanFieldValue(buf, i+1) if len(valueBuf) == 0 { fields[string(name)] = nil continue diff --git a/tsdb/points_test.go b/tsdb/points_test.go index 8a6d66145d4..5f9b1685eae 100644 --- a/tsdb/points_test.go +++ b/tsdb/points_test.go @@ -334,6 +334,39 @@ func TestParsePointWithStringWithSpaces(t *testing.T) { ) } +func TestParsePointWithStringWithCommas(t *testing.T) { + // escaped comma + test(t, `cpu,host=serverA,region=us-east value=1.0,str="foo\,bar" 1000000000`, + NewPoint( + "cpu", + Tags{ + "host": "serverA", + "region": "us-east", + }, + Fields{ + "value": 1.0, + "str": "foo,bar", // commas in string value + }, + time.Unix(1, 0)), + ) + + // non-escaped comma + test(t, `cpu,host=serverA,region=us-east value=1.0,str="foo,bar" 1000000000`, + NewPoint( + "cpu", + Tags{ + "host": "serverA", + "region": "us-east", + }, + Fields{ + "value": 1.0, + "str": "foo,bar", // commas in string value + }, + time.Unix(1, 0)), + ) + +} + func TestParsePointWithStringWithEquals(t *testing.T) { test(t, `cpu,host=serverA,region=us-east str="foo=bar",value=1.0, 1000000000`, NewPoint(