From e8baddf32a89977bb52119b6410417bef16c867e Mon Sep 17 00:00:00 2001 From: junya koyama Date: Tue, 26 Sep 2023 07:59:14 +0900 Subject: [PATCH 1/6] feat: type-safe conversion for line-protocol Signed-off-by: junya koyama --- influxdb3/point.go | 20 +++++ influxdb3/value.go | 194 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 214 insertions(+) create mode 100644 influxdb3/value.go diff --git a/influxdb3/point.go b/influxdb3/point.go index 4060e0c..abd497f 100644 --- a/influxdb3/point.go +++ b/influxdb3/point.go @@ -155,6 +155,26 @@ func (m *Point) AddField(k string, v interface{}) *Point { return m } +// AddFieldFromValue adds a [github.com/influxdata/line-protocol/v2/lineprotocol.Value] to the Point. +// +// Parameters: +// - k: The key of the field. +// - v: The value of the line protocol format. +// +// Returns: +// - The updated Point with the field added. +func (m *Point) AddFieldFromValue(k string, v lineprotocol.Value) *Point { + for i, field := range m.Fields { + if k == field.Key { + m.Fields[i].Value = v + return m + } + } + + m.Fields = append(m.Fields, Field{Key: k, Value: v}) + return m +} + // AddField adds a field to the Point. // // Parameters: diff --git a/influxdb3/value.go b/influxdb3/value.go new file mode 100644 index 0000000..ee0aff5 --- /dev/null +++ b/influxdb3/value.go @@ -0,0 +1,194 @@ +/* + The MIT License + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +package influxdb3 + +import ( + "fmt" + "time" + + "github.com/influxdata/line-protocol/v2/lineprotocol" +) + +// NativeType are unions of type sets that can converted to [lineprotocol.NewValue]. +// +// [lineprotocol.NewValue]: https://pkg.go.dev/github.com/influxdata/line-protocol/v2/lineprotocol#NewValue +// +// [line-protocol]: https://docs.influxdata.com/influxdb/cloud-serverless/reference/syntax/line-protocol/#field-set +type NativeType interface { + float64 | int64 | uint64 | string | []byte | bool +} + +// [Float] is IEEE-754 64-bit floating-point numbers. Default numerical type. InfluxDB supports scientific notation in float field values. +// Non-finite floating-point field values (+/- infinity and NaN from IEEE 754) are not currently supported. +// +// [Float]: https://docs.influxdata.com/influxdb/cloud-serverless/reference/syntax/line-protocol/#float +type Float interface { + ~float32 | ~float64 +} + +// [Integer] is signed 64-bit integers. +// +// [Integer]: https://docs.influxdata.com/influxdb/cloud-serverless/reference/syntax/line-protocol/#integer +type Integer interface { + ~int | ~int8 | ~int16 | ~int32 | ~int64 +} + +// [UInteger] is unsigned 64-bit integers. +// +// [UInteger]: https://docs.influxdata.com/influxdb/cloud-serverless/reference/syntax/line-protocol/#uinteger +type UInteger interface { + ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 +} + +// [String] is plain text string. Length limit 64KB. +// +// [String]: https://docs.influxdata.com/influxdb/cloud-serverless/reference/syntax/line-protocol/#string +type String interface { + ~string | ~[]byte +} + +// [Boolean] is true or false values. +// +// [Boolean]: https://docs.influxdata.com/influxdb/cloud-serverless/reference/syntax/line-protocol/#boolean +type Boolean interface { + ~bool +} + +// NewValueFromNative is a convenient function for creating a [lineprotocol.Value] from NativeType. +// +// Parameters: +// - v: The value of the field value. +// +// Returns: +// - The created [lineprotocol.Value]. +// +// [lineprotocol.Value]: https://pkg.go.dev/github.com/influxdata/line-protocol/v2/lineprotocol#Value +func NewValueFromNative[N NativeType](v N) lineprotocol.Value { + return lineprotocol.MustNewValue(v) +} + +// NewValueFromFloat is a convenient function for creating a [lineprotocol.Value] from Float. +// +// Parameters: +// - v: The value of the Float value. +// +// Returns: +// - The created [lineprotocol.Value]. +// +// [lineprotocol.Value]: https://pkg.go.dev/github.com/influxdata/line-protocol/v2/lineprotocol#Value +func NewValueFromFloat[F Float](v F) lineprotocol.Value { + data, ok := lineprotocol.FloatValue(float64(v)) + if !ok { + panic(fmt.Errorf("invalid float value for NewValueFromFloat: %T (%#v)", v, v)) + } + return data +} + +// NewValueFromInt is a convenient function for creating a [lineprotocol.Value] from Integer. +// +// Parameters: +// - v: The value of the Integer value. +// +// Returns: +// - The created [lineprotocol.Value]. +// +// [lineprotocol.Value]: https://pkg.go.dev/github.com/influxdata/line-protocol/v2/lineprotocol#Value +func NewValueFromInt[I Integer](v I) lineprotocol.Value { + return lineprotocol.IntValue(int64(v)) +} + +// NewValueFromUInt is a convenient function for creating a [lineprotocol.Value] from UInteger. +// +// Parameters: +// - v: The value of the UInteger value. +// +// Returns: +// - The created [lineprotocol.Value]. +// +// [lineprotocol.Value]: https://pkg.go.dev/github.com/influxdata/line-protocol/v2/lineprotocol#Value +func NewValueFromUInt[U UInteger](v U) lineprotocol.Value { + return lineprotocol.UintValue(uint64(v)) +} + +// NewValueFromString is a convenient function for creating a [lineprotocol.Value] from String. +// +// Parameters: +// - v: The value of the String value. +// +// Returns: +// - The created [lineprotocol.Value]. +// +// [lineprotocol.Value]: https://pkg.go.dev/github.com/influxdata/line-protocol/v2/lineprotocol#Value +func NewValueFromString[S String](v S) lineprotocol.Value { + data, ok := lineprotocol.StringValue(string(v)) + if !ok { + panic(fmt.Errorf("invalid utf-8 string value for NewValueFromString: %T (%#v)", v, v)) + } + return data +} + +// NewValueFromUInt is a convenient function for creating a [lineprotocol.Value] from [fmt.Stringer]. +// +// Examples: +// +// func example() { +// p := NewPoint("measurement", map[string]string{}, map[string]interface{}{}, time.Now()) +// p.AddFieldFromValue("supports time.Duration", NewValueFromStringer(4*time.Hour)) +// } +// +// Parameters: +// - v: The value of the UInteger value. +// +// Returns: +// - The created [lineprotocol.Value]. +// +// [lineprotocol.Value]: https://pkg.go.dev/github.com/influxdata/line-protocol/v2/lineprotocol#Value +func NewValueFromStringer[S fmt.Stringer](v S) lineprotocol.Value { + return NewValueFromString(v.String()) +} + +// NewValueFromBoolean is a convenient function for creating a [lineprotocol.Value] from Boolean. +// +// Parameters: +// - v: The value of the Boolean value. +// +// Returns: +// - The created [lineprotocol.Value]. +// +// [lineprotocol.Value]: https://pkg.go.dev/github.com/influxdata/line-protocol/v2/lineprotocol#Value +func NewValueFromBoolean[B Boolean](v B) lineprotocol.Value { + return lineprotocol.BoolValue(bool(v)) +} + +// NewValueFromBoolean is a convenient function for creating a [lineprotocol.Value] from [time.Time]. +// +// Parameters: +// - v: The value of the [time.Time] value. +// +// Returns: +// - The created [lineprotocol.Value]. +// +// [lineprotocol.Value]: https://pkg.go.dev/github.com/influxdata/line-protocol/v2/lineprotocol#Value +func NewValueFromTime(v time.Time) lineprotocol.Value { + return NewValueFromString(v.Format(time.RFC3339Nano)) +} From f8511927c861af81667ccf970bf94f5fb67cf3bd Mon Sep 17 00:00:00 2001 From: junya koyama Date: Sun, 1 Oct 2023 18:48:42 +0900 Subject: [PATCH 2/6] feat: add unit test Signed-off-by: junya koyama --- influxdb3/point_test.go | 77 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) diff --git a/influxdb3/point_test.go b/influxdb3/point_test.go index 0ed7bff..36b8992 100644 --- a/influxdb3/point_test.go +++ b/influxdb3/point_test.go @@ -41,6 +41,13 @@ type st struct { b bool } +type tfloat64u float64 +type tint64u int64 +type tuint64u uint64 +type tstringu string +type tbytesu []byte +type tboolu bool + func (s st) String() string { return fmt.Sprintf("%.2f d %v", s.d, s.b) } @@ -129,3 +136,73 @@ func TestPoint(t *testing.T) { require.NoError(t, err) assert.EqualValues(t, `test,host"name=ho\st\ "a",id=10ad\=,ven\=dor=GCP,x\"\ x=a\ b "string"="six, \"seven\", eight",bo\ol=false,duration="4h24m3s",float32=80,float64=80.1234567,int=-1234567890i,int16=-3456i,int32=-34567i,int64=-1234567890i,int8=-34i,stri\=ng="six=seven\\, eight",time="2020-03-20T10:30:23.123456789Z",uint=12345677890u,uint\ 64=41234567890u,uint16=3456u,uint32=345780u,uint8=34u 60000000070`+"\n", string(line)) } + +func TestAddFieldFromValue(t *testing.T) { + p := NewPoint( + "test", + map[string]string{ + "id": "10ad=", + "ven=dor": "AWS", + `host"name`: `ho\st "a"`, + `x\" x`: "a b", + }, + map[string]interface{}{}, + time.Unix(60, 70)) + + p.AddFieldFromValue("float64", NewValueFromFloat(tfloat64u(80.1234567))) + p.AddFieldFromValue("float32", NewValueFromFloat(float32(80.0))) + p.AddFieldFromValue("int", NewValueFromInt(-1234567890)) + p.AddFieldFromValue("int8", NewValueFromInt(int8(-34))) + p.AddFieldFromValue("int16", NewValueFromInt(int16(-3456))) + p.AddFieldFromValue("int32", NewValueFromInt(int32(-34567))) + p.AddFieldFromValue("int64", NewValueFromInt(tint64u(-1234567890))) + p.AddFieldFromValue("uint", NewValueFromUInt(uint(12345677890))) + p.AddFieldFromValue("uint8", NewValueFromUInt(uint8(34))) + p.AddFieldFromValue("uint16", NewValueFromUInt(uint16(3456))) + p.AddFieldFromValue("uint32", NewValueFromUInt(uint32(34578))) + p.AddFieldFromValue("uint 64", NewValueFromUInt(tuint64u(41234567890))) + p.AddFieldFromValue("bo\\ol", NewValueFromBoolean(tboolu(false))) + p.AddFieldFromValue(`"string"`, NewValueFromString(tstringu(`six, "seven", eight`))) + p.AddFieldFromValue("stri=ng", NewValueFromString(tbytesu([]byte(`six=seven\, eight`)))) + p.AddFieldFromValue("time", NewValueFromTime(time.Date(2020, time.March, 20, 10, 30, 23, 123456789, time.UTC))) + p.AddFieldFromValue("duration", NewValueFromStringer(4*time.Hour+24*time.Minute+3*time.Second)) + + // Test duplicate tag and duplicate field + p.AddTag("ven=dor", "GCP").AddField("uint32", uint32(345780)) + + line, err := p.MarshalBinary(lineprotocol.Nanosecond) + require.NoError(t, err) + assert.EqualValues(t, `test,host"name=ho\st\ "a",id=10ad\=,ven\=dor=GCP,x\"\ x=a\ b "string"="six, \"seven\", eight",bo\ol=false,duration="4h24m3s",float32=80,float64=80.1234567,int=-1234567890i,int16=-3456i,int32=-34567i,int64=-1234567890i,int8=-34i,stri\=ng="six=seven\\, eight",time="2020-03-20T10:30:23.123456789Z",uint=12345677890u,uint\ 64=41234567890u,uint16=3456u,uint32=345780u,uint8=34u 60000000070`+"\n", string(line)) + + assert.PanicsWithError(t, "invalid float value for NewValueFromFloat: float64 (+Inf)", func() { NewValueFromFloat(math.Inf(1)) }) + assert.PanicsWithError(t, "invalid float value for NewValueFromFloat: float64 (-Inf)", func() { NewValueFromFloat(math.Inf(-1)) }) + assert.PanicsWithError(t, "invalid utf-8 string value for NewValueFromString: string (\"\\xed\\x9f\\xc1\")", func() { NewValueFromString(string([]byte{237, 159, 193})) }) +} + +func TestNewValueFromNative(t *testing.T) { + p := NewPoint( + "test", + map[string]string{ + "id": "10ad=", + "ven=dor": "AWS", + `host"name`: `ho\st "a"`, + `x\" x`: "a b", + }, + map[string]interface{}{}, + time.Unix(60, 70)) + + p.AddFieldFromValue("float64", NewValueFromNative(80.1234567)) + p.AddFieldFromValue("int64", NewValueFromNative(int64(-1234567890))) + p.AddFieldFromValue("uint64", NewValueFromNative(uint64(12345677890))) + p.AddFieldFromValue("string", NewValueFromNative(`six, "seven", eight`)) + p.AddFieldFromValue("bytes", NewValueFromNative([]byte(`six=seven\, eight`))) + p.AddFieldFromValue("bool", NewValueFromNative(false)) + + line, err := p.MarshalBinary(lineprotocol.Nanosecond) + require.NoError(t, err) + assert.EqualValues(t, `test,host"name=ho\st\ "a",id=10ad\=,ven\=dor=AWS,x\"\ x=a\ b bool=false,bytes="six=seven\\, eight",float64=80.1234567,int64=-1234567890i,string="six, \"seven\", eight",uint64=12345677890u 60000000070`+"\n", string(line)) + + assert.PanicsWithError(t, "invalid value for NewValue: float64 (+Inf)", func() { NewValueFromNative(math.Inf(1)) }) + assert.PanicsWithError(t, "invalid value for NewValue: float64 (-Inf)", func() { NewValueFromNative(math.Inf(-1)) }) + assert.PanicsWithError(t, "invalid value for NewValue: string (\"\\xed\\x9f\\xc1\")", func() { NewValueFromNative(string([]byte{237, 159, 193})) }) +} From 85f69f15631505108aa05abf1f13cc828caa7590 Mon Sep 17 00:00:00 2001 From: junya koyama Date: Mon, 2 Oct 2023 08:16:53 +0900 Subject: [PATCH 3/6] feat: add examples, fix doc comments. Signed-off-by: junya koyama --- influxdb3/example_test.go | 50 ++++++++++++++++++++++++++++++++ influxdb3/point.go | 4 ++- influxdb3/point_test.go | 28 ------------------ influxdb3/value.go | 10 ++----- influxdb3/value_test.go | 61 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 116 insertions(+), 37 deletions(-) create mode 100644 influxdb3/example_test.go create mode 100644 influxdb3/value_test.go diff --git a/influxdb3/example_test.go b/influxdb3/example_test.go new file mode 100644 index 0000000..fa06a71 --- /dev/null +++ b/influxdb3/example_test.go @@ -0,0 +1,50 @@ +/* + The MIT License + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +package influxdb3 + +import ( + "fmt" + "time" + + "github.com/influxdata/line-protocol/v2/lineprotocol" +) + +func ExamplePoint_AddFieldFromValue() { + p := NewPoint("measurement", map[string]string{}, map[string]interface{}{}, time.Now()) + p.AddFieldFromValue("hello", NewValueFromString("world")) + p.AddFieldFromValue("float", NewValueFromFloat(55.101)) + p.AddFieldFromValue("time.Time", NewValueFromTime(time.Date(2020, time.March, 20, 10, 30, 23, 123456789, time.UTC))) + p.SetTimestamp(time.Date(2020, time.March, 20, 10, 30, 23, 123456789, time.UTC)) + line, _ := p.MarshalBinary(lineprotocol.Nanosecond) + fmt.Println(string(line)) + // Output: measurement float=55.101,hello="world",time.Time="2020-03-20T10:30:23.123456789Z" 1584700223123456789 +} + +func ExampleNewValueFromStringer() { + p := NewPoint("measurement", map[string]string{}, map[string]interface{}{}, time.Now()) + p.AddFieldFromValue("Supports time.Duration", NewValueFromStringer(4*time.Hour)) + p.SetTimestamp(time.Date(2020, time.March, 20, 10, 30, 23, 123456789, time.UTC)) + line, _ := p.MarshalBinary(lineprotocol.Nanosecond) + fmt.Println(string(line)) + // Output: measurement Supports\ time.Duration="4h0m0s" 1584700223123456789 +} diff --git a/influxdb3/point.go b/influxdb3/point.go index abd497f..b96aeb2 100644 --- a/influxdb3/point.go +++ b/influxdb3/point.go @@ -155,7 +155,7 @@ func (m *Point) AddField(k string, v interface{}) *Point { return m } -// AddFieldFromValue adds a [github.com/influxdata/line-protocol/v2/lineprotocol.Value] to the Point. +// AddFieldFromValue adds a [lineprotocol.Value] to the Point. // // Parameters: // - k: The key of the field. @@ -163,6 +163,8 @@ func (m *Point) AddField(k string, v interface{}) *Point { // // Returns: // - The updated Point with the field added. +// +// [lineprotocol.Value]: https://pkg.go.dev/github.com/influxdata/line-protocol/v2/lineprotocol#Value func (m *Point) AddFieldFromValue(k string, v lineprotocol.Value) *Point { for i, field := range m.Fields { if k == field.Key { diff --git a/influxdb3/point_test.go b/influxdb3/point_test.go index 36b8992..892dc43 100644 --- a/influxdb3/point_test.go +++ b/influxdb3/point_test.go @@ -178,31 +178,3 @@ func TestAddFieldFromValue(t *testing.T) { assert.PanicsWithError(t, "invalid float value for NewValueFromFloat: float64 (-Inf)", func() { NewValueFromFloat(math.Inf(-1)) }) assert.PanicsWithError(t, "invalid utf-8 string value for NewValueFromString: string (\"\\xed\\x9f\\xc1\")", func() { NewValueFromString(string([]byte{237, 159, 193})) }) } - -func TestNewValueFromNative(t *testing.T) { - p := NewPoint( - "test", - map[string]string{ - "id": "10ad=", - "ven=dor": "AWS", - `host"name`: `ho\st "a"`, - `x\" x`: "a b", - }, - map[string]interface{}{}, - time.Unix(60, 70)) - - p.AddFieldFromValue("float64", NewValueFromNative(80.1234567)) - p.AddFieldFromValue("int64", NewValueFromNative(int64(-1234567890))) - p.AddFieldFromValue("uint64", NewValueFromNative(uint64(12345677890))) - p.AddFieldFromValue("string", NewValueFromNative(`six, "seven", eight`)) - p.AddFieldFromValue("bytes", NewValueFromNative([]byte(`six=seven\, eight`))) - p.AddFieldFromValue("bool", NewValueFromNative(false)) - - line, err := p.MarshalBinary(lineprotocol.Nanosecond) - require.NoError(t, err) - assert.EqualValues(t, `test,host"name=ho\st\ "a",id=10ad\=,ven\=dor=AWS,x\"\ x=a\ b bool=false,bytes="six=seven\\, eight",float64=80.1234567,int64=-1234567890i,string="six, \"seven\", eight",uint64=12345677890u 60000000070`+"\n", string(line)) - - assert.PanicsWithError(t, "invalid value for NewValue: float64 (+Inf)", func() { NewValueFromNative(math.Inf(1)) }) - assert.PanicsWithError(t, "invalid value for NewValue: float64 (-Inf)", func() { NewValueFromNative(math.Inf(-1)) }) - assert.PanicsWithError(t, "invalid value for NewValue: string (\"\\xed\\x9f\\xc1\")", func() { NewValueFromNative(string([]byte{237, 159, 193})) }) -} diff --git a/influxdb3/value.go b/influxdb3/value.go index ee0aff5..3a499a4 100644 --- a/influxdb3/value.go +++ b/influxdb3/value.go @@ -39,7 +39,6 @@ type NativeType interface { } // [Float] is IEEE-754 64-bit floating-point numbers. Default numerical type. InfluxDB supports scientific notation in float field values. -// Non-finite floating-point field values (+/- infinity and NaN from IEEE 754) are not currently supported. // // [Float]: https://docs.influxdata.com/influxdb/cloud-serverless/reference/syntax/line-protocol/#float type Float interface { @@ -88,6 +87,7 @@ func NewValueFromNative[N NativeType](v N) lineprotocol.Value { } // NewValueFromFloat is a convenient function for creating a [lineprotocol.Value] from Float. +// Non-finite floating-point field values (+/- infinity and NaN from IEEE 754) are not currently supported. // // Parameters: // - v: The value of the Float value. @@ -131,6 +131,7 @@ func NewValueFromUInt[U UInteger](v U) lineprotocol.Value { } // NewValueFromString is a convenient function for creating a [lineprotocol.Value] from String. +// Non-UTF-8 string field values are not currently supported. // // Parameters: // - v: The value of the String value. @@ -149,13 +150,6 @@ func NewValueFromString[S String](v S) lineprotocol.Value { // NewValueFromUInt is a convenient function for creating a [lineprotocol.Value] from [fmt.Stringer]. // -// Examples: -// -// func example() { -// p := NewPoint("measurement", map[string]string{}, map[string]interface{}{}, time.Now()) -// p.AddFieldFromValue("supports time.Duration", NewValueFromStringer(4*time.Hour)) -// } -// // Parameters: // - v: The value of the UInteger value. // diff --git a/influxdb3/value_test.go b/influxdb3/value_test.go new file mode 100644 index 0000000..c25944c --- /dev/null +++ b/influxdb3/value_test.go @@ -0,0 +1,61 @@ +/* + The MIT License + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +package influxdb3 + +import ( + "math" + "testing" + "time" + + "github.com/influxdata/line-protocol/v2/lineprotocol" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestNewValueFromNative(t *testing.T) { + p := NewPoint( + "test", + map[string]string{ + "id": "10ad=", + "ven=dor": "AWS", + `host"name`: `ho\st "a"`, + `x\" x`: "a b", + }, + map[string]interface{}{}, + time.Unix(60, 70)) + + p.AddFieldFromValue("float64", NewValueFromNative(80.1234567)) + p.AddFieldFromValue("int64", NewValueFromNative(int64(-1234567890))) + p.AddFieldFromValue("uint64", NewValueFromNative(uint64(12345677890))) + p.AddFieldFromValue("string", NewValueFromNative(`six, "seven", eight`)) + p.AddFieldFromValue("bytes", NewValueFromNative([]byte(`six=seven\, eight`))) + p.AddFieldFromValue("bool", NewValueFromNative(false)) + + line, err := p.MarshalBinary(lineprotocol.Nanosecond) + require.NoError(t, err) + assert.EqualValues(t, `test,host"name=ho\st\ "a",id=10ad\=,ven\=dor=AWS,x\"\ x=a\ b bool=false,bytes="six=seven\\, eight",float64=80.1234567,int64=-1234567890i,string="six, \"seven\", eight",uint64=12345677890u 60000000070`+"\n", string(line)) + + assert.PanicsWithError(t, "invalid value for NewValue: float64 (+Inf)", func() { NewValueFromNative(math.Inf(1)) }) + assert.PanicsWithError(t, "invalid value for NewValue: float64 (-Inf)", func() { NewValueFromNative(math.Inf(-1)) }) + assert.PanicsWithError(t, "invalid value for NewValue: string (\"\\xed\\x9f\\xc1\")", func() { NewValueFromNative(string([]byte{237, 159, 193})) }) +} From 7b253af824666dc284c74f5c9f03c3991e1ec5ce Mon Sep 17 00:00:00 2001 From: arukiidou Date: Tue, 3 Oct 2023 02:24:19 +0000 Subject: [PATCH 4/6] fix: doc comment fixed in value.go --- influxdb3/value.go | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/influxdb3/value.go b/influxdb3/value.go index 3a499a4..2194a83 100644 --- a/influxdb3/value.go +++ b/influxdb3/value.go @@ -32,8 +32,6 @@ import ( // NativeType are unions of type sets that can converted to [lineprotocol.NewValue]. // // [lineprotocol.NewValue]: https://pkg.go.dev/github.com/influxdata/line-protocol/v2/lineprotocol#NewValue -// -// [line-protocol]: https://docs.influxdata.com/influxdb/cloud-serverless/reference/syntax/line-protocol/#field-set type NativeType interface { float64 | int64 | uint64 | string | []byte | bool } @@ -148,10 +146,10 @@ func NewValueFromString[S String](v S) lineprotocol.Value { return data } -// NewValueFromUInt is a convenient function for creating a [lineprotocol.Value] from [fmt.Stringer]. +// NewValueFromStringer is a convenient function for creating a [lineprotocol.Value] from [fmt.Stringer]. // // Parameters: -// - v: The value of the UInteger value. +// - v: The value of the [fmt.Stringer] value. // // Returns: // - The created [lineprotocol.Value]. @@ -174,7 +172,7 @@ func NewValueFromBoolean[B Boolean](v B) lineprotocol.Value { return lineprotocol.BoolValue(bool(v)) } -// NewValueFromBoolean is a convenient function for creating a [lineprotocol.Value] from [time.Time]. +// NewValueFromTime is a convenient function for creating a [lineprotocol.Value] from [time.Time]. // // Parameters: // - v: The value of the [time.Time] value. From 29e2d5dae52dca4d8038aea3668b0c74b1f8010b Mon Sep 17 00:00:00 2001 From: junya koyama Date: Wed, 18 Oct 2023 19:25:07 +0900 Subject: [PATCH 5/6] fix: fixed comment suggestion Signed-off-by: junya koyama --- influxdb3/value.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/influxdb3/value.go b/influxdb3/value.go index 2194a83..896a2f6 100644 --- a/influxdb3/value.go +++ b/influxdb3/value.go @@ -36,35 +36,35 @@ type NativeType interface { float64 | int64 | uint64 | string | []byte | bool } -// [Float] is IEEE-754 64-bit floating-point numbers. Default numerical type. InfluxDB supports scientific notation in float field values. +// Float [Float] is IEEE-754 64-bit floating-point numbers. Default numerical type. InfluxDB supports scientific notation in float field values. // // [Float]: https://docs.influxdata.com/influxdb/cloud-serverless/reference/syntax/line-protocol/#float type Float interface { ~float32 | ~float64 } -// [Integer] is signed 64-bit integers. +// Integer [Integer] is signed 64-bit integers. // // [Integer]: https://docs.influxdata.com/influxdb/cloud-serverless/reference/syntax/line-protocol/#integer type Integer interface { ~int | ~int8 | ~int16 | ~int32 | ~int64 } -// [UInteger] is unsigned 64-bit integers. +// UInteger [UInteger] is unsigned 64-bit integers. // // [UInteger]: https://docs.influxdata.com/influxdb/cloud-serverless/reference/syntax/line-protocol/#uinteger type UInteger interface { ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 } -// [String] is plain text string. Length limit 64KB. +// String [String] is plain text string. Length limit 64KB. // // [String]: https://docs.influxdata.com/influxdb/cloud-serverless/reference/syntax/line-protocol/#string type String interface { ~string | ~[]byte } -// [Boolean] is true or false values. +// Boolean [Boolean] is true or false values. // // [Boolean]: https://docs.influxdata.com/influxdb/cloud-serverless/reference/syntax/line-protocol/#boolean type Boolean interface { From 5ffea2d4c4e2c8f5c31427593eb65d82b043a2f6 Mon Sep 17 00:00:00 2001 From: junya koyama Date: Sun, 1 Oct 2023 23:46:19 +0900 Subject: [PATCH 6/6] feat: add CHANGELOG.md Signed-off-by: junya koyama --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 604c887..9d6b3dd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ ## 0.4.0 [unreleased] +### Features + +1. [#42](https://github.com/InfluxCommunity/influxdb3-go/pull/42): Add type-safe conversion for line-protocol + ## 0.3.0 [2023-10-02] ### Features