diff --git a/parquet_go18_test.go b/parquet_go18_test.go index a974e8d..481c62c 100644 --- a/parquet_go18_test.go +++ b/parquet_go18_test.go @@ -6,6 +6,8 @@ import ( "bytes" "fmt" "log" + "reflect" + "testing" "github.com/segmentio/parquet-go" ) @@ -116,3 +118,49 @@ func ExampleWrite_any() { // map["FirstName":"Han" "LastName":"Solo"] // map["FirstName":"R2" "LastName":"D2"] } + +func TestIssue360(t *testing.T) { + type TestType struct { + Key []int + } + + schema := parquet.SchemaOf(TestType{}) + buffer := parquet.NewGenericBuffer[any](schema) + + data := make([]any, 1) + data[0] = TestType{Key: []int{1}} + _, err := buffer.Write(data) + if err != nil { + fmt.Println("Exiting with error: ", err) + return + } + + var out bytes.Buffer + writer := parquet.NewGenericWriter[any](&out, schema) + + _, err = parquet.CopyRows(writer, buffer.Rows()) + if err != nil { + fmt.Println("Exiting with error: ", err) + return + } + writer.Close() + + br := bytes.NewReader(out.Bytes()) + rows, _ := parquet.Read[any](br, br.Size()) + + expect := []any{ + map[string]any{ + "Key": []any{ + int64(1), + }, + }, + } + + if !reflect.DeepEqual(rows, expect) { + t.Error("rows mismatch") + + for _, row := range rows { + t.Logf("%#v", row) + } + } +} diff --git a/row.go b/row.go index ab95ca7..a696255 100644 --- a/row.go +++ b/row.go @@ -578,27 +578,35 @@ func reconstructFuncOfRepeated(columnIndex int16, node Node) (int16, reconstruct rowLength := nextColumnIndex - columnIndex return nextColumnIndex, func(value reflect.Value, lvls levels, row Row) (Row, error) { t := value.Type() - c := value.Cap() + s := value + c := 0 n := 0 - if c > 0 { - value.Set(value.Slice(0, c)) - } else { - c = 10 - value.Set(reflect.MakeSlice(t, c, c)) - } + const defaultCapacity = 10 defer func() { - value.Set(value.Slice(0, n)) + value.Set(s.Slice(0, n)) }() + if t.Kind() == reflect.Interface { + var v []interface{} + c = defaultCapacity + t = reflect.TypeOf(v) + s = reflect.MakeSlice(t, c, c) + } else if c = s.Cap(); c > 0 { + s = s.Slice(0, c) + } else { + c = defaultCapacity + s = reflect.MakeSlice(t, c, c) + } + return reconstructRepeated(columnIndex, rowLength, lvls, row, func(levels levels, row Row) (Row, error) { if n == c { c *= 2 - newValue := reflect.MakeSlice(t, c, c) - reflect.Copy(newValue, value) - value.Set(newValue) + newSlice := reflect.MakeSlice(t, c, c) + reflect.Copy(newSlice, s) + s = newSlice } - row, err := reconstruct(value.Index(n), levels, row) + row, err := reconstruct(s.Index(n), levels, row) n++ return row, err })