diff --git a/src/datastore/leveldb_datastore.go b/src/datastore/leveldb_datastore.go index 6ef66c0ee1..e93ea98ae4 100644 --- a/src/datastore/leveldb_datastore.go +++ b/src/datastore/leveldb_datastore.go @@ -666,40 +666,38 @@ func isPointInRange(fieldId, startTime, endTime, point []byte) bool { func (self *LevelDbDatastore) fetchSinglePoint(database, series string, fields []*Field, query *parser.SelectQuery) (*protocol.Series, error) { fieldCount := len(fields) - fieldNames := make([]string, fieldCount) - point := &protocol.Point{Values: make([]*protocol.FieldValue, fieldCount, fieldCount)} + fieldNames := make([]string, 0, fieldCount) + point := &protocol.Point{Values: make([]*protocol.FieldValue, 0, fieldCount)} + timestampBuffer := bytes.NewBuffer(make([]byte, 0, 8)) + sequenceNumberBuffer := bytes.NewBuffer(make([]byte, 0, 8)) + timestamp := common.TimeToMicroseconds(query.GetStartTime()) + sequenceNumber, err := query.GetSinglePointQuerySequenceNumber() + if err != nil { + return nil, err + } - for i, field := range fields { + binary.Write(timestampBuffer, binary.BigEndian, self.convertTimestampToUint(×tamp)) + binary.Write(sequenceNumberBuffer, binary.BigEndian, sequenceNumber) + sequenceNumber_uint64 := uint64(sequenceNumber) + point.SequenceNumber = &sequenceNumber_uint64 + point.SetTimestampInMicroseconds(timestamp) - fieldNames[i] = field.Name - timestampBuffer := bytes.NewBuffer(make([]byte, 0, 8)) - sequenceNumberBuffer := bytes.NewBuffer(make([]byte, 0, 8)) - - timestamp := common.TimeToMicroseconds(query.GetStartTime()) - sequence_number, err := query.GetSinglePointQuerySequenceNumber() - if err != nil { - return nil, err - } - - binary.Write(timestampBuffer, binary.BigEndian, self.convertTimestampToUint(×tamp)) - binary.Write(sequenceNumberBuffer, binary.BigEndian, sequence_number) + for _, field := range fields { pointKey := append(append(field.Id, timestampBuffer.Bytes()...), sequenceNumberBuffer.Bytes()...) if data, err := self.db.Get(self.readOptions, pointKey); err != nil { return nil, err } else { - fv := &protocol.FieldValue{} - err := proto.Unmarshal(data, fv) + fieldValue := &protocol.FieldValue{} + err := proto.Unmarshal(data, fieldValue) if err != nil { return nil, err } - point.Values[i] = fv + if data != nil { + fieldNames = append(fieldNames, field.Name) + point.Values = append(point.Values, fieldValue) + } } - - seq := uint64(sequence_number) - point.SetTimestampInMicroseconds(timestamp) - point.SequenceNumber = &seq - } result := &protocol.Series{Name: &series, Fields: fieldNames, Points: []*protocol.Point{point}} diff --git a/src/integration/benchmark_test.go b/src/integration/benchmark_test.go index e16323f833..0f83e35660 100644 --- a/src/integration/benchmark_test.go +++ b/src/integration/benchmark_test.go @@ -917,11 +917,44 @@ func (self *IntegrationSuite) TestSinglePointSelect(c *C) { c.Assert(err, IsNil) c.Assert(data, HasLen, 1) c.Assert(data[0].Points, HasLen, 1) + c.Assert(data[0].Points[0], HasLen, 4) c.Assert(data[0].Points[0][2], Equals, point[2]) c.Assert(data[0].Points[0][3], Equals, point[3]) } } +func (self *IntegrationSuite) TestSinglePointSelectWithNullValues(c *C) { + err := self.server.WriteData(` +[ + { + "name": "test_single_points", + "columns": ["name", "age"], + "points": [["john", null]] + } +]`) + c.Assert(err, IsNil) + + query := "select * from test_single_points_with_nulls;" + bs, err := self.server.RunQuery(query, "u") + c.Assert(err, IsNil) + + data := []*h.SerializedSeries{} + err = json.Unmarshal(bs, &data) + c.Assert(err, IsNil) + + for _, point := range data[0].Points { + query := fmt.Sprintf("select name, age from test_single_points where time = %.0f and sequence_number = %0.f;", point[0].(float64), point[1]) + bs, err := self.server.RunQuery(query, "u") + data := []*h.SerializedSeries{} + err = json.Unmarshal(bs, &data) + c.Assert(err, IsNil) + c.Assert(data, HasLen, 1) + c.Assert(data[0].Points, HasLen, 1) + c.Assert(data[0].Points[0], HasLen, 3) + c.Assert(data[0].Points[0][2], Equals, point[2]) + } +} + func (self *IntegrationSuite) TestColumnsWithOnlySomeValuesWorkWithWhereQuery(c *C) { err := self.server.WriteData(` [