Skip to content

Commit 36b65cb

Browse files
authored
fix: Conversion and test fixes (#1064)
Some fixes to the scalar and testing code: - use `AppendTime` in `AppendToBuilder` to take different time units into account - base64 decode binary-encoded JSON strings when the type calls for it in struct `Set()`, otherwise the binary data gets interpreted as a string and the results are incorrect - exclude the JSON type from list tests, we didn't support that before and don't need to introduce it now
1 parent f13e4cc commit 36b65cb

File tree

4 files changed

+80
-7
lines changed

4 files changed

+80
-7
lines changed

scalar/scalar.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ func AppendToBuilder(bldr array.Builder, s Scalar) {
182182
case arrow.BOOL:
183183
bldr.(*array.BooleanBuilder).Append(s.(*Bool).Value)
184184
case arrow.TIMESTAMP:
185-
bldr.(*array.TimestampBuilder).Append(arrow.Timestamp(s.(*Timestamp).Value.UnixMicro()))
185+
bldr.(*array.TimestampBuilder).AppendTime(s.(*Timestamp).Value)
186186
case arrow.DURATION:
187187
bldr.(*array.DurationBuilder).Append(arrow.Duration(s.(*Duration).Value))
188188
case arrow.DATE32:
@@ -217,7 +217,6 @@ func AppendToBuilder(bldr array.Builder, s Scalar) {
217217
st := sb.Type().(*arrow.StructType)
218218
for i, f := range st.Fields() {
219219
sc := NewScalar(sb.FieldBuilder(i).Type())
220-
221220
if sv, ok := m[f.Name]; ok {
222221
if err := sc.Set(sv); err != nil {
223222
panic(err)

scalar/struct.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package scalar
22

33
import (
4+
"encoding/base64"
45
"encoding/json"
56
"reflect"
67

@@ -61,6 +62,28 @@ func (s *Struct) Set(val any) error {
6162
if err := json.Unmarshal([]byte(value), &x); err != nil {
6263
return err
6364
}
65+
for name := range x {
66+
if f, ok := s.Type.FieldByName(name); ok {
67+
xs, ok := x[name].(string)
68+
if !ok {
69+
continue
70+
}
71+
switch {
72+
case arrow.TypeEqual(f.Type, arrow.BinaryTypes.Binary):
73+
v, err := base64.StdEncoding.DecodeString(xs)
74+
if err != nil {
75+
return err
76+
}
77+
x[name] = v
78+
case arrow.TypeEqual(f.Type, arrow.BinaryTypes.LargeBinary):
79+
v, err := base64.StdEncoding.DecodeString(xs)
80+
if err != nil {
81+
return err
82+
}
83+
x[name] = v
84+
}
85+
}
86+
}
6487
s.Value = x
6588

6689
case []byte:

scalar/struct_test.go

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,55 @@
11
package scalar
22

33
import (
4+
"encoding/json"
45
"strconv"
56
"testing"
67

78
"github.com/apache/arrow/go/v13/arrow"
89
"github.com/apache/arrow/go/v13/arrow/array"
910
"github.com/apache/arrow/go/v13/arrow/memory"
11+
"github.com/cloudquery/plugin-sdk/v4/types"
1012
"github.com/stretchr/testify/assert"
1113
)
1214

15+
func TestStructEncodeDecode(t *testing.T) {
16+
tl := []struct {
17+
name string
18+
dt *arrow.StructType
19+
input any
20+
}{
21+
{name: "binary", dt: arrow.StructOf(arrow.Field{Name: "binary", Type: arrow.BinaryTypes.Binary}), input: `{"binary":"7049Ug=="}`},
22+
{name: "uuid", dt: arrow.StructOf(arrow.Field{Name: "uuid", Type: types.ExtensionTypes.UUID}), input: `{"uuid":"f81d4fae-7dec-11d0-a765-00a0c91e6bf6"}`},
23+
}
24+
25+
for _, tc := range tl {
26+
t.Run(tc.name, func(t *testing.T) {
27+
bldr := array.NewBuilder(memory.DefaultAllocator, tc.dt)
28+
defer bldr.Release()
29+
30+
s := NewScalar(tc.dt)
31+
if !arrow.TypeEqual(s.DataType(), tc.dt) {
32+
t.Fatalf("expected %v, got %v", tc.dt, s.DataType())
33+
}
34+
35+
assert.NoError(t, s.Set(tc.input))
36+
if t.Failed() {
37+
return
38+
}
39+
40+
assert.True(t, s.IsValid())
41+
AppendToBuilder(bldr, s)
42+
arr := bldr.NewArray()
43+
one := arr.GetOneForMarshal(0)
44+
json, err := json.Marshal(one)
45+
if err != nil {
46+
t.Fatal(err)
47+
}
48+
assert.Equal(t, tc.input, string(json))
49+
})
50+
}
51+
}
52+
1353
func TestStructMissingKeys(t *testing.T) {
1454
tl := []struct {
1555
dt *arrow.StructType

schema/testdata.go

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -89,10 +89,10 @@ func TestTable(name string, opts TestSourceOptions) *Table {
8989
{Name: "boolean", Type: arrow.FixedWidthTypes.Boolean},
9090

9191
// extension types
92-
{Name: "uuid", Type: types.NewUUIDType()},
93-
{Name: "inet", Type: types.NewInetType()},
94-
{Name: "mac", Type: types.NewMACType()},
95-
{Name: "json", Type: types.NewJSONType()},
92+
{Name: "uuid", Type: types.ExtensionTypes.UUID},
93+
{Name: "inet", Type: types.ExtensionTypes.Inet},
94+
{Name: "mac", Type: types.ExtensionTypes.MAC},
95+
{Name: "json", Type: types.ExtensionTypes.JSON},
9696
}...)
9797
if !opts.SkipDates {
9898
columns = append(columns, ColumnList{
@@ -157,7 +157,8 @@ func TestTable(name string, opts TestSourceOptions) *Table {
157157
}
158158

159159
if !opts.SkipLists {
160-
columns = append(columns, listOfColumns(columns)...)
160+
cols := excludeType(columns, types.ExtensionTypes.JSON)
161+
columns = append(columns, listOfColumns(cols)...)
161162
}
162163

163164
if !opts.SkipMaps {
@@ -168,6 +169,16 @@ func TestTable(name string, opts TestSourceOptions) *Table {
168169
return t
169170
}
170171

172+
func excludeType(columns ColumnList, typ arrow.DataType) ColumnList {
173+
var cols ColumnList
174+
for _, c := range columns {
175+
if c.Type.ID() != typ.ID() {
176+
cols = append(cols, c)
177+
}
178+
}
179+
return cols
180+
}
181+
171182
// var PKColumnNames = []string{"uuid_pk"}
172183

173184
// GenTestDataOptions are options for generating test data

0 commit comments

Comments
 (0)