Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support int64 data types #2261

Merged
merged 1 commit into from
Apr 13, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

### Bugfixes
- [#2255](https://github.com/influxdb/influxdb/pull/2255): Fix panic when changing default retention policy.
- [#2261](https://github.com/influxdb/influxdb/pull/2261): Support int64 value types.

## v0.9.0-rc23 [2015-04-11]

Expand Down
26 changes: 15 additions & 11 deletions database.go
Original file line number Diff line number Diff line change
Expand Up @@ -780,17 +780,14 @@ func (f *FieldCodec) EncodeFields(values map[string]interface{}) ([]byte, error)
var buf []byte

switch field.Type {
case influxql.Number:
var value float64
// Convert integers to floats.
if intval, ok := v.(int); ok {
value = float64(intval)
} else {
value = v.(float64)
}

case influxql.Float:
value := v.(float64)
buf = make([]byte, 9)
binary.BigEndian.PutUint64(buf[1:9], math.Float64bits(value))
case influxql.Integer:
value := v.(int64)
buf = make([]byte, 9)
binary.BigEndian.PutUint64(buf[1:9], uint64(value))
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems easiest to just cast it to an unsigned value, and just encode it as that.

case influxql.Boolean:
value := v.(bool)

Expand Down Expand Up @@ -850,10 +847,13 @@ func (f *FieldCodec) DecodeByID(targetID uint8, b []byte) (interface{}, error) {

var value interface{}
switch field.Type {
case influxql.Number:
case influxql.Float:
// Move bytes forward.
value = math.Float64frombits(binary.BigEndian.Uint64(b[1:9]))
b = b[9:]
case influxql.Integer:
value = int64(binary.BigEndian.Uint64(b[1:9]))
b = b[9:]
case influxql.Boolean:
if b[1] == 1 {
value = true
Expand Down Expand Up @@ -904,10 +904,14 @@ func (f *FieldCodec) DecodeFields(b []byte) (map[uint8]interface{}, error) {

var value interface{}
switch field.Type {
case influxql.Number:
case influxql.Float:
value = math.Float64frombits(binary.BigEndian.Uint64(b[1:9]))
// Move bytes forward.
b = b[9:]
case influxql.Integer:
value = int64(binary.BigEndian.Uint64(b[1:9]))
// Move bytes forward.
b = b[9:]
case influxql.Boolean:
if b[1] == 1 {
value = true
Expand Down
2 changes: 1 addition & 1 deletion httpd/handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1564,7 +1564,7 @@ func TestHandler_serveWriteSeriesFieldTypeConflict(t *testing.T) {
if len(r.Results) != 0 {
t.Fatalf("unexpected results count")
}
if r.Err.Error() != "field \"value\" is type string, mapped as type number" {
if r.Err.Error() != "field \"value\" is type string, mapped as type float" {
t.Fatalf("unexpected error returned, actual: %s", r.Err.Error())
}
}
Expand Down
12 changes: 7 additions & 5 deletions influxql/ast.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,10 @@ type DataType string
const (
// Unknown primitive data type.
Unknown = DataType("")
// Number means the data type is an int or float.
Number = DataType("number")
// Float means the data type is a float
Float = DataType("float")
// Integer means the data type is a integer
Integer = DataType("integer")
// Boolean means the data type is a boolean.
Boolean = DataType("boolean")
// String means the data type is a string of text.
Expand All @@ -33,9 +35,9 @@ const (
func InspectDataType(v interface{}) DataType {
switch v.(type) {
case float64:
return Number
case int:
return Number
return Float
case int64, int32, int:
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if this is really necessary.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I might just need int64.

return Integer
case bool:
return Boolean
case string:
Expand Down
2 changes: 1 addition & 1 deletion influxql/ast_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ func TestInspectDataType(t *testing.T) {
v interface{}
typ influxql.DataType
}{
{float64(100), influxql.Number},
{float64(100), influxql.Float},
} {
if typ := influxql.InspectDataType(tt.v); tt.typ != typ {
t.Errorf("%d. %v (%s): unexpected type: %s", i, tt.v, tt.typ, typ)
Expand Down
12 changes: 6 additions & 6 deletions internal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import (
func TestMeasurement_uniqueTagValues(t *testing.T) {
// Create a measurement to run against.
m := NewMeasurement("cpu")
m.createFieldIfNotExists("value", influxql.Number)
m.createFieldIfNotExists("value", influxql.Float)

for i, tt := range []struct {
expr string
Expand All @@ -37,7 +37,7 @@ func TestMeasurement_uniqueTagValues(t *testing.T) {
// Ensure a measurement can expand an expression for all possible tag values used.
func TestMeasurement_expandExpr(t *testing.T) {
m := NewMeasurement("cpu")
m.createFieldIfNotExists("value", influxql.Number)
m.createFieldIfNotExists("value", influxql.Float)

type tagSetExprString struct {
tagExpr []tagExpr
Expand Down Expand Up @@ -129,13 +129,13 @@ func TestCreateMeasurementsCommand(t *testing.T) {
}

// Add a field.
err = c.addFieldIfNotExists("bar", "value", influxql.Number)
err = c.addFieldIfNotExists("bar", "value", influxql.Integer)
if err != nil {
t.Fatal("error adding field \"value\"")
}

// Add same field again.
err = c.addFieldIfNotExists("bar", "value", influxql.Number)
err = c.addFieldIfNotExists("bar", "value", influxql.Integer)
if err != nil {
t.Fatal("error re-adding field \"value\"")
}
Expand Down Expand Up @@ -167,7 +167,7 @@ func TestCreateMeasurementsCommand_Errors(t *testing.T) {
// Measurements should be created automatically.
c.addSeriesIfNotExists("bar", nil)

err = c.addFieldIfNotExists("bar", "value", influxql.Number)
err = c.addFieldIfNotExists("bar", "value", influxql.Float)
if err != nil {
t.Fatalf("unexpected error got %s", err.Error())
}
Expand All @@ -176,7 +176,7 @@ func TestCreateMeasurementsCommand_Errors(t *testing.T) {
c.addMeasurementIfNotExists("bar")

// Test type conflicts
err = c.addFieldIfNotExists("bar", "value", influxql.Number)
err = c.addFieldIfNotExists("bar", "value", influxql.Float)
if err != nil {
t.Fatal("error adding field \"value\"")
}
Expand Down
33 changes: 33 additions & 0 deletions server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -976,6 +976,39 @@ func TestServer_StartRetentionPolicyEnforcement_ErrZeroInterval(t *testing.T) {
}
}

// Ensure the server can support writes of all data types.
func TestServer_WriteAllDataTypes(t *testing.T) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Must add test to server.go since it's the only way to control the types.

c := test.NewDefaultMessagingClient()
defer c.Close()
s := OpenServer(c)
defer s.Close()
s.CreateDatabase("foo")
s.CreateRetentionPolicy("foo", &influxdb.RetentionPolicy{Name: "raw", Duration: 1 * time.Hour})
s.SetDefaultRetentionPolicy("foo", "raw")

// Write series with one point to the database.
s.MustWriteSeries("foo", "raw", []influxdb.Point{{Name: "series1", Timestamp: mustParseTime("2000-01-01T00:00:00Z"), Fields: map[string]interface{}{"value": float64(20)}}})
s.MustWriteSeries("foo", "raw", []influxdb.Point{{Name: "series2", Timestamp: mustParseTime("2000-01-01T00:00:00Z"), Fields: map[string]interface{}{"value": int64(30)}}})
s.MustWriteSeries("foo", "raw", []influxdb.Point{{Name: "series3", Timestamp: mustParseTime("2000-01-01T00:00:00Z"), Fields: map[string]interface{}{"value": "baz"}}})
s.MustWriteSeries("foo", "raw", []influxdb.Point{{Name: "series4", Timestamp: mustParseTime("2000-01-01T00:00:00Z"), Fields: map[string]interface{}{"value": true}}})

f := func(t *testing.T, database, query, expected string) {
results := s.executeQuery(MustParseQuery(query), database, nil)
if res := results.Results[0]; res.Err != nil {
t.Errorf("unexpected error: %s", res.Err)
} else if len(res.Series) != 1 {
t.Errorf("unexpected row count: %d", len(res.Series))
} else if s := mustMarshalJSON(res); s != expected {
t.Errorf("unexpected row(0): \nexp: %s\ngot: %s", expected, s)
}
}

f(t, "foo", "SELECT * from series1", `{"series":[{"name":"series1","columns":["time","value"],"values":[["2000-01-01T00:00:00Z",20]]}]}`)
f(t, "foo", "SELECT * from series2", `{"series":[{"name":"series2","columns":["time","value"],"values":[["2000-01-01T00:00:00Z",30]]}]}`)
f(t, "foo", "SELECT * from series3", `{"series":[{"name":"series3","columns":["time","value"],"values":[["2000-01-01T00:00:00Z","baz"]]}]}`)
f(t, "foo", "SELECT * from series4", `{"series":[{"name":"series4","columns":["time","value"],"values":[["2000-01-01T00:00:00Z",true]]}]}`)
}

func TestServer_EnforceRetentionPolices(t *testing.T) {
c := test.NewDefaultMessagingClient()
s := OpenServer(c)
Expand Down