Skip to content

Commit d252e51

Browse files
authored
Data: (Breaking) Change enums to contain EnumItem (#632)
This makes FieldTypeFor and data.NewField work with enums This is a breaking change for the newer Enum Field type since before this field would be passed unit16 values and is now passed a data.EnumItemIndex valuies instead.
1 parent 375444b commit d252e51

File tree

9 files changed

+86
-39
lines changed

9 files changed

+86
-39
lines changed

data/arrow.go

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -607,17 +607,31 @@ func parseColumn(col array.Interface, i int, nullable []bool, frame *Frame) erro
607607
case arrow.UINT16:
608608
v := array.NewUint16Data(col.Data())
609609
for rIdx := 0; rIdx < col.Len(); rIdx++ {
610-
if nullable[i] {
611-
if v.IsNull(rIdx) {
612-
var ns *uint16
613-
frame.Fields[i].vector.Append(ns)
610+
if frame.Fields[i].Type().NullableType() == FieldTypeNullableEnum {
611+
if nullable[i] {
612+
if v.IsNull(rIdx) {
613+
var ns *EnumItemIndex
614+
frame.Fields[i].vector.Append(ns)
615+
continue
616+
}
617+
rv := EnumItemIndex(v.Value(rIdx))
618+
frame.Fields[i].vector.Append(&rv)
614619
continue
615620
}
616-
rv := v.Value(rIdx)
617-
frame.Fields[i].vector.Append(&rv)
618-
continue
621+
frame.Fields[i].vector.Append(EnumItemIndex(v.Value(rIdx)))
622+
} else {
623+
if nullable[i] {
624+
if v.IsNull(rIdx) {
625+
var ns *uint16
626+
frame.Fields[i].vector.Append(ns)
627+
continue
628+
}
629+
rv := v.Value(rIdx)
630+
frame.Fields[i].vector.Append(&rv)
631+
continue
632+
}
633+
frame.Fields[i].vector.Append(v.Value(rIdx))
619634
}
620-
frame.Fields[i].vector.Append(v.Value(rIdx))
621635
}
622636
case arrow.FLOAT32:
623637
v := array.NewFloat32Data(col.Data())

data/arrow_column_builders.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -467,7 +467,7 @@ func buildNullableEnumColumn(pool memory.Allocator, field arrow.Field, vec *null
467467
builder.AppendNull()
468468
continue
469469
}
470-
builder.Append(*v)
470+
builder.Append((uint16)(*v))
471471
}
472472

473473
chunked := array.NewChunked(field.Type, []array.Interface{builder.NewArray()})
@@ -481,7 +481,7 @@ func buildEnumColumn(pool memory.Allocator, field arrow.Field, vec *enumVector)
481481
defer builder.Release()
482482

483483
for _, v := range *vec {
484-
builder.Append(v)
484+
builder.Append(uint16(v))
485485
}
486486

487487
chunked := array.NewChunked(field.Type, []array.Interface{builder.NewArray()})

data/arrow_test.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,7 @@ func goldenDF() *data.Frame {
271271
jsonRawMessagePtr(json.RawMessage("[{\"c\":3},{\"d\":4}]")),
272272
jsonRawMessagePtr(json.RawMessage("{\"e\":{\"f\":5}}")),
273273
}),
274-
newField("enum", data.FieldTypeEnum, []uint16{
274+
data.NewField("enum", nil, []data.EnumItemIndex{
275275
1, 2, 2, 1, 1,
276276
}).SetConfig(&data.FieldConfig{
277277
TypeConfig: &data.FieldTypeConfig{
@@ -282,12 +282,12 @@ func goldenDF() *data.Frame {
282282
},
283283
},
284284
}),
285-
newField("nullable_enum", data.FieldTypeNullableEnum, []*uint16{
286-
uint16Ptr(1),
287-
uint16Ptr(2),
285+
data.NewField("nullable_enum", nil, []*data.EnumItemIndex{
286+
(*data.EnumItemIndex)(uint16Ptr(1)),
287+
(*data.EnumItemIndex)(uint16Ptr(2)),
288288
nil,
289-
uint16Ptr(3),
290-
uint16Ptr(0),
289+
(*data.EnumItemIndex)(uint16Ptr(3)),
290+
(*data.EnumItemIndex)(uint16Ptr(0)),
291291
}),
292292
).SetMeta(&data.FrameMeta{
293293
Custom: map[string]interface{}{"Hi": "there"},

data/field.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,10 @@ type Fields []*Field
5858
//
5959
// []json.RawMessage, []*json.RawMessage
6060
//
61+
// Enum:
62+
//
63+
// []data.EnumItemIndex, []*data.EnumItemIndex
64+
//
6165
// If an unsupported values type is passed, NewField will panic.
6266
// nolint:gocyclo
6367
func NewField(name string, labels Labels, values interface{}) *Field {
@@ -119,6 +123,10 @@ func NewField(name string, labels Labels, values interface{}) *Field {
119123
vec = newJsonRawMessageVectorWithValues(v)
120124
case []*json.RawMessage:
121125
vec = newNullableJsonRawMessageVectorWithValues(v)
126+
case []EnumItemIndex:
127+
vec = newEnumVectorWithValues(v)
128+
case []*EnumItemIndex:
129+
vec = newNullableEnumVectorWithValues(v)
122130
default:
123131
panic(fmt.Errorf("field '%s' specified with unsupported type %T", name, v))
124132
}

data/field_type.go

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -84,9 +84,9 @@ const (
8484
// FieldTypeNullableJSON indicates the underlying primitive is a []*json.RawMessage.
8585
FieldTypeNullableJSON
8686

87-
// FieldTypeEnum indicates the underlying primitive is a []uint16, with field mapping metadata
87+
// FieldTypeEnum indicates the underlying primitive is a []data.EnumItemIndex, with field mapping metadata
8888
FieldTypeEnum
89-
// FieldTypeNullableEnum indicates the underlying primitive is a []*uint16, with field mapping metadata
89+
// FieldTypeNullableEnum indicates the underlying primitive is a []*data.EnumItemIndex, with field mapping metadata
9090
FieldTypeNullableEnum
9191
)
9292

@@ -116,10 +116,9 @@ func (p *FieldType) UnmarshalJSON(b []byte) error {
116116

117117
// FieldTypeFor will return the FieldType that holds items of item's type.
118118
// If the FieldType is not recognized, FieldTypeUnknown is returned.
119-
// Enum fields are currently unrecognized.
120119
// For example, for an item of type *int8, FieldTypeNullableInt8 will be returned.
120+
// nolint:gocyclo
121121
func FieldTypeFor(item interface{}) FieldType {
122-
// NOTE: enum does not have a native mapping ;(
123122
switch item.(type) {
124123
case int8:
125124
return FieldTypeInt8
@@ -193,6 +192,11 @@ func FieldTypeFor(item interface{}) FieldType {
193192
return FieldTypeJSON
194193
case *json.RawMessage:
195194
return FieldTypeNullableJSON
195+
196+
case EnumItemIndex:
197+
return FieldTypeEnum
198+
case *EnumItemIndex:
199+
return FieldTypeNullableEnum
196200
}
197201

198202
return FieldTypeUnknown

data/field_type_enum.go

Lines changed: 29 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,35 @@
11
package data
22

33
// this supports the enum type
4-
// it is diffent than the rest since it is backed by
5-
// a uint16, but has special semantics and interacts with the metadata
4+
// it is different than the rest since it is backed by
5+
// a uint16 but maps to the EnumItemIndex type, and has special semantics and interacts with the metadata
66
// Unlike the other fields it can not be easily generated
77

8-
type enumVector []uint16
8+
type enumVector []EnumItemIndex
9+
10+
type EnumItemIndex uint16
911

1012
func newEnumVector(n int) *enumVector {
11-
v := enumVector(make([]uint16, n))
13+
v := enumVector(make([]EnumItemIndex, n))
1214
return &v
1315
}
1416

17+
func newEnumVectorWithValues(s []EnumItemIndex) *enumVector {
18+
v := make([]EnumItemIndex, len(s))
19+
copy(v, s)
20+
return (*enumVector)(&v)
21+
}
22+
1523
func (v *enumVector) Set(idx int, i interface{}) {
16-
(*v)[idx] = i.(uint16)
24+
(*v)[idx] = i.(EnumItemIndex)
1725
}
1826

1927
func (v *enumVector) SetConcrete(idx int, i interface{}) {
2028
v.Set(idx, i)
2129
}
2230

2331
func (v *enumVector) Append(i interface{}) {
24-
*v = append(*v, i.(uint16))
32+
*v = append(*v, i.(EnumItemIndex))
2533
}
2634

2735
func (v *enumVector) At(i int) interface{} {
@@ -49,7 +57,7 @@ func (v *enumVector) Type() FieldType {
4957
}
5058

5159
func (v *enumVector) Extend(i int) {
52-
*v = append(*v, make([]uint16, i)...)
60+
*v = append(*v, make([]EnumItemIndex, i)...)
5361
}
5462

5563
func (v *enumVector) Insert(i int, val interface{}) {
@@ -69,23 +77,29 @@ func (v *enumVector) Delete(i int) {
6977
*v = append((*v)[:i], (*v)[i+1:]...)
7078
}
7179

72-
type nullableEnumVector []*uint16
80+
type nullableEnumVector []*EnumItemIndex
7381

7482
func newNullableEnumVector(n int) *nullableEnumVector {
75-
v := nullableEnumVector(make([]*uint16, n))
83+
v := nullableEnumVector(make([]*EnumItemIndex, n))
7684
return &v
7785
}
7886

87+
func newNullableEnumVectorWithValues(s []*EnumItemIndex) *nullableEnumVector {
88+
v := make([]*EnumItemIndex, len(s))
89+
copy(v, s)
90+
return (*nullableEnumVector)(&v)
91+
}
92+
7993
func (v *nullableEnumVector) Set(idx int, i interface{}) {
8094
if i == nil {
8195
(*v)[idx] = nil
8296
return
8397
}
84-
(*v)[idx] = i.(*uint16)
98+
(*v)[idx] = i.(*EnumItemIndex)
8599
}
86100

87101
func (v *nullableEnumVector) SetConcrete(idx int, i interface{}) {
88-
val := i.(uint16)
102+
val := i.(EnumItemIndex)
89103
(*v)[idx] = &val
90104
}
91105

@@ -94,7 +108,7 @@ func (v *nullableEnumVector) Append(i interface{}) {
94108
*v = append(*v, nil)
95109
return
96110
}
97-
*v = append(*v, i.(*uint16))
111+
*v = append(*v, i.(*EnumItemIndex))
98112
}
99113

100114
func (v *nullableEnumVector) At(i int) interface{} {
@@ -103,15 +117,15 @@ func (v *nullableEnumVector) At(i int) interface{} {
103117

104118
func (v *nullableEnumVector) CopyAt(i int) interface{} {
105119
if (*v)[i] == nil {
106-
var g *uint16
120+
var g *EnumItemIndex
107121
return g
108122
}
109123
g := *(*v)[i]
110124
return &g
111125
}
112126

113127
func (v *nullableEnumVector) ConcreteAt(i int) (interface{}, bool) {
114-
var g uint16
128+
var g EnumItemIndex
115129
val := (*v)[i]
116130
if val == nil {
117131
return g, false
@@ -133,7 +147,7 @@ func (v *nullableEnumVector) Type() FieldType {
133147
}
134148

135149
func (v *nullableEnumVector) Extend(i int) {
136-
*v = append(*v, make([]*uint16, i)...)
150+
*v = append(*v, make([]*EnumItemIndex, i)...)
137151
}
138152

139153
func (v *nullableEnumVector) Insert(i int, val interface{}) {

data/frame_json.gen.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -888,7 +888,7 @@ func readEnumVectorJSON(iter *jsoniter.Iterator, size int) (*enumVector, error)
888888
iter.ReadNil()
889889
} else {
890890
v := iter.ReadUint16()
891-
arr.Set(i, v)
891+
arr.Set(i, EnumItemIndex(v))
892892
}
893893
}
894894

@@ -911,7 +911,8 @@ func readNullableEnumVectorJSON(iter *jsoniter.Iterator, size int) (*nullableEnu
911911
iter.ReadNil()
912912
} else {
913913
v := iter.ReadUint16()
914-
arr.Set(i, &v)
914+
eII := EnumItemIndex(v)
915+
arr.Set(i, &eII)
915916
}
916917
}
917918

data/frame_json.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -382,12 +382,18 @@ func jsonValuesToVector(ft FieldType, arr []interface{}) (vector, error) {
382382
return uint8(iV), err
383383
}
384384

385-
case FieldTypeUint16, FieldTypeEnum: // enums and uint16 share the same backings
385+
case FieldTypeUint16: // enums and uint16 share the same backings
386386
convert = func(v interface{}) (interface{}, error) {
387387
iV, err := int64FromJSON(v)
388388
return uint16(iV), err
389389
}
390390

391+
case FieldTypeEnum: // enums and uint16 share the same backings
392+
convert = func(v interface{}) (interface{}, error) {
393+
iV, err := int64FromJSON(v)
394+
return EnumItemIndex(iV), err
395+
}
396+
391397
case FieldTypeUint32:
392398
convert = func(v interface{}) (interface{}, error) {
393399
iV, err := int64FromJSON(v)

data/frame_json_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ func TestFieldTypeToJSON(t *testing.T) {
9696
assert.Equal(t, data.FieldTypeInt8, v.FType)
9797
assert.Equal(t, data.FieldTypeTime, *v.FType2)
9898

99-
field := newField("enum", data.FieldTypeEnum, []uint16{
99+
field := newField("enum", data.FieldTypeEnum, []data.EnumItemIndex{
100100
1, 2, 2, 1, 1,
101101
})
102102

0 commit comments

Comments
 (0)