blob: 6c513c8f144dda290bf553c7855ba2bbd2ec45b3 [file]
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package array_test
import (
"reflect"
"testing"
"github.com/apache/arrow-go/v18/arrow"
"github.com/apache/arrow-go/v18/arrow/array"
"github.com/apache/arrow-go/v18/arrow/memory"
"github.com/stretchr/testify/assert"
)
func TestListArray(t *testing.T) {
tests := []struct {
typeID arrow.Type
offsets interface{}
sizes interface{}
dt arrow.DataType
}{
{arrow.LIST, []int32{0, 3, 3, 3, 7}, nil, arrow.ListOf(arrow.PrimitiveTypes.Int32)},
{arrow.LARGE_LIST, []int64{0, 3, 3, 3, 7}, nil, arrow.LargeListOf(arrow.PrimitiveTypes.Int32)},
{arrow.LIST, []int32{0, 3, 3, 3, 7}, nil, arrow.ListOfField(arrow.Field{Name: "item", Type: arrow.PrimitiveTypes.Int32, Nullable: true})},
{arrow.LARGE_LIST, []int64{0, 3, 3, 3, 7}, nil, arrow.LargeListOfField(arrow.Field{Name: "item", Type: arrow.PrimitiveTypes.Int32, Nullable: true})},
{arrow.LIST_VIEW, []int32{0, 3, 3, 3}, []int32{3, 0, 0, 4}, arrow.ListViewOf(arrow.PrimitiveTypes.Int32)},
{arrow.LARGE_LIST_VIEW, []int64{0, 3, 3, 3}, []int64{3, 0, 0, 4}, arrow.LargeListViewOf(arrow.PrimitiveTypes.Int32)},
}
for _, tt := range tests {
t.Run(tt.typeID.String(), func(t *testing.T) {
pool := memory.NewCheckedAllocator(memory.NewGoAllocator())
defer pool.AssertSize(t, 0)
var (
vs = []int32{0, 1, 2, 3, 4, 5, 6}
lengths = []int{3, 0, 0, 4}
isValid = []bool{true, false, true, true}
)
lb := array.NewBuilder(pool, tt.dt).(array.VarLenListLikeBuilder)
defer lb.Release()
for i := 0; i < 10; i++ {
vb := lb.ValueBuilder().(*array.Int32Builder)
vb.Reserve(len(vs))
pos := 0
for i, length := range lengths {
lb.AppendWithSize(isValid[i], length)
for j := 0; j < length; j++ {
vb.Append(vs[pos])
pos++
}
}
arr := lb.NewArray().(array.ListLike)
defer arr.Release()
arr.Retain()
arr.Release()
if got, want := arr.DataType().ID(), tt.typeID; got != want {
t.Fatalf("got=%v, want=%v", got, want)
}
if got, want := arr.Len(), len(isValid); got != want {
t.Fatalf("got=%d, want=%d", got, want)
}
for i := range lengths {
if got, want := arr.IsValid(i), isValid[i]; got != want {
t.Fatalf("got[%d]=%v, want[%d]=%v", i, got, i, want)
}
if got, want := arr.IsNull(i), !isValid[i]; got != want {
t.Fatalf("got[%d]=%v, want[%d]=%v", i, got, i, want)
}
}
var gotOffsets, gotSizes interface{}
switch tt.typeID {
case arrow.LIST:
arr := arr.(*array.List)
gotOffsets = arr.Offsets()
case arrow.LARGE_LIST:
arr := arr.(*array.LargeList)
gotOffsets = arr.Offsets()
case arrow.LIST_VIEW:
arr := arr.(*array.ListView)
gotOffsets = arr.Offsets()
gotSizes = arr.Sizes()
case arrow.LARGE_LIST_VIEW:
arr := arr.(*array.LargeListView)
gotOffsets = arr.Offsets()
gotSizes = arr.Sizes()
}
if !reflect.DeepEqual(gotOffsets, tt.offsets) {
t.Fatalf("got=%v, want=%v", gotOffsets, tt.offsets)
}
if tt.typeID == arrow.LIST_VIEW || tt.typeID == arrow.LARGE_LIST_VIEW {
if !reflect.DeepEqual(gotSizes, tt.sizes) {
t.Fatalf("got=%v, want=%v", gotSizes, tt.sizes)
}
}
varr := arr.ListValues().(*array.Int32)
if got, want := varr.Int32Values(), vs; !reflect.DeepEqual(got, want) {
t.Fatalf("got=%v, want=%v", got, want)
}
}
})
}
}
// Like the list-view tests in TestListArray, but with out-of-order offsets.
func TestListViewArray(t *testing.T) {
tests := []struct {
typeID arrow.Type
offsets interface{}
sizes interface{}
dt arrow.DataType
}{
{arrow.LIST_VIEW, []int32{5, 0, 0, 1}, []int32{3, 0, 0, 4}, arrow.ListViewOf(arrow.PrimitiveTypes.Int32)},
{arrow.LARGE_LIST_VIEW, []int64{5, 0, 0, 1}, []int64{3, 0, 0, 4}, arrow.LargeListViewOf(arrow.PrimitiveTypes.Int32)},
}
for _, tt := range tests {
t.Run(tt.typeID.String(), func(t *testing.T) {
pool := memory.NewCheckedAllocator(memory.NewGoAllocator())
defer pool.AssertSize(t, 0)
var (
vs = []int32{-1, 3, 4, 5, 6, 0, 1, 2}
lengths = []int{3, 0, 0, 4}
isValid = []bool{true, false, true, true}
)
lb := array.NewBuilder(pool, tt.dt).(array.VarLenListLikeBuilder)
defer lb.Release()
for i := 0; i < 10; i++ {
switch lvb := lb.(type) {
case *array.ListViewBuilder:
lvb.AppendDimensions(5, 3)
lb.AppendNull()
lvb.AppendDimensions(0, 0)
lvb.AppendDimensions(1, 4)
case *array.LargeListViewBuilder:
lvb.AppendDimensions(5, 3)
lb.AppendNull()
lvb.AppendDimensions(0, 0)
lvb.AppendDimensions(1, 4)
}
vb := lb.ValueBuilder().(*array.Int32Builder)
vb.Reserve(len(vs))
vb.AppendValues(vs, []bool{false, true, true, true, true, true, true, true})
arr := lb.NewArray().(array.ListLike)
defer arr.Release()
arr.Retain()
arr.Release()
if got, want := arr.DataType().ID(), tt.typeID; got != want {
t.Fatalf("got=%v, want=%v", got, want)
}
if got, want := arr.Len(), len(isValid); got != want {
t.Fatalf("got=%d, want=%d", got, want)
}
for i := range lengths {
if got, want := arr.IsValid(i), isValid[i]; got != want {
t.Fatalf("got[%d]=%v, want[%d]=%v", i, got, i, want)
}
if got, want := arr.IsNull(i), !isValid[i]; got != want {
t.Fatalf("got[%d]=%v, want[%d]=%v", i, got, i, want)
}
}
var gotOffsets, gotSizes interface{}
switch tt.typeID {
case arrow.LIST_VIEW:
arr := arr.(*array.ListView)
gotOffsets = arr.Offsets()
gotSizes = arr.Sizes()
case arrow.LARGE_LIST_VIEW:
arr := arr.(*array.LargeListView)
gotOffsets = arr.Offsets()
gotSizes = arr.Sizes()
}
if !reflect.DeepEqual(gotOffsets, tt.offsets) {
t.Fatalf("got=%v, want=%v", gotOffsets, tt.offsets)
}
if !reflect.DeepEqual(gotSizes, tt.sizes) {
t.Fatalf("got=%v, want=%v", gotSizes, tt.sizes)
}
varr := arr.ListValues().(*array.Int32)
if got, want := varr.Int32Values(), vs; !reflect.DeepEqual(got, want) {
t.Fatalf("got=%v, want=%v", got, want)
}
}
})
}
}
func TestListArrayEmpty(t *testing.T) {
typ := []arrow.DataType{
arrow.ListOf(arrow.PrimitiveTypes.Int32),
arrow.LargeListOf(arrow.PrimitiveTypes.Int32),
arrow.ListViewOf(arrow.PrimitiveTypes.Int32),
arrow.LargeListViewOf(arrow.PrimitiveTypes.Int32),
}
for _, dt := range typ {
t.Run(dt.String(), func(t *testing.T) {
pool := memory.NewCheckedAllocator(memory.NewGoAllocator())
defer pool.AssertSize(t, 0)
lb := array.NewBuilder(pool, dt)
defer lb.Release()
arr := lb.NewArray()
defer arr.Release()
if got, want := arr.Len(), 0; got != want {
t.Fatalf("got=%d, want=%d", got, want)
}
})
}
}
func TestListArrayBulkAppend(t *testing.T) {
tests := []struct {
typeID arrow.Type
offsets interface{}
sizes interface{}
dt arrow.DataType
}{
{arrow.LIST, []int32{0, 3, 3, 3, 7}, nil, arrow.ListOf(arrow.PrimitiveTypes.Int32)},
{arrow.LARGE_LIST, []int64{0, 3, 3, 3, 7}, nil, arrow.LargeListOf(arrow.PrimitiveTypes.Int32)},
{arrow.LIST_VIEW, []int32{0, 3, 3, 3}, []int32{3, 0, 0, 4}, arrow.ListViewOf(arrow.PrimitiveTypes.Int32)},
{arrow.LARGE_LIST_VIEW, []int64{0, 3, 3, 3}, []int64{3, 0, 0, 4}, arrow.LargeListViewOf(arrow.PrimitiveTypes.Int32)},
}
for _, tt := range tests {
t.Run(tt.typeID.String(), func(t *testing.T) {
pool := memory.NewCheckedAllocator(memory.NewGoAllocator())
defer pool.AssertSize(t, 0)
var (
vs = []int32{0, 1, 2, 3, 4, 5, 6}
lengths = []int{3, 0, 0, 4}
isValid = []bool{true, false, true, true}
)
lb := array.NewBuilder(pool, tt.dt).(array.VarLenListLikeBuilder)
defer lb.Release()
vb := lb.ValueBuilder().(*array.Int32Builder)
vb.Reserve(len(vs))
switch tt.typeID {
case arrow.LIST:
lb.(*array.ListBuilder).AppendValues(tt.offsets.([]int32), isValid)
case arrow.LARGE_LIST:
lb.(*array.LargeListBuilder).AppendValues(tt.offsets.([]int64), isValid)
case arrow.LIST_VIEW:
lb.(*array.ListViewBuilder).AppendValuesWithSizes(tt.offsets.([]int32), tt.sizes.([]int32), isValid)
case arrow.LARGE_LIST_VIEW:
lb.(*array.LargeListViewBuilder).AppendValuesWithSizes(tt.offsets.([]int64), tt.sizes.([]int64), isValid)
}
for _, v := range vs {
vb.Append(v)
}
arr := lb.NewArray().(array.VarLenListLike)
defer arr.Release()
if got, want := arr.DataType().ID(), tt.typeID; got != want {
t.Fatalf("got=%v, want=%v", got, want)
}
if got, want := arr.Len(), len(isValid); got != want {
t.Fatalf("got=%d, want=%d", got, want)
}
for i := range lengths {
if got, want := arr.IsValid(i), isValid[i]; got != want {
t.Fatalf("got[%d]=%v, want[%d]=%v", i, got, i, want)
}
if got, want := arr.IsNull(i), !isValid[i]; got != want {
t.Fatalf("got[%d]=%v, want[%d]=%v", i, got, i, want)
}
}
var gotOffsets, gotSizes interface{}
switch tt.typeID {
case arrow.LIST:
arr := arr.(*array.List)
gotOffsets = arr.Offsets()
case arrow.LARGE_LIST:
arr := arr.(*array.LargeList)
gotOffsets = arr.Offsets()
case arrow.LIST_VIEW:
arr := arr.(*array.ListView)
gotOffsets = arr.Offsets()
gotSizes = arr.Sizes()
case arrow.LARGE_LIST_VIEW:
arr := arr.(*array.LargeListView)
gotOffsets = arr.Offsets()
gotSizes = arr.Sizes()
}
if !reflect.DeepEqual(gotOffsets, tt.offsets) {
t.Fatalf("got=%v, want=%v", gotOffsets, tt.offsets)
}
if tt.typeID == arrow.LIST_VIEW || tt.typeID == arrow.LARGE_LIST_VIEW {
if !reflect.DeepEqual(gotSizes, tt.sizes) {
t.Fatalf("got=%v, want=%v", gotSizes, tt.sizes)
}
}
varr := arr.ListValues().(*array.Int32)
if got, want := varr.Int32Values(), vs; !reflect.DeepEqual(got, want) {
t.Fatalf("got=%v, want=%v", got, want)
}
})
}
}
func TestListViewArrayBulkAppend(t *testing.T) {
tests := []struct {
typeID arrow.Type
offsets interface{}
sizes interface{}
dt arrow.DataType
}{
{arrow.LIST_VIEW, []int32{5, 0, 0, 1}, []int32{3, 0, 0, 4}, arrow.ListViewOf(arrow.PrimitiveTypes.Int32)},
{arrow.LARGE_LIST_VIEW, []int64{5, 0, 0, 1}, []int64{3, 0, 0, 4}, arrow.LargeListViewOf(arrow.PrimitiveTypes.Int32)},
}
for _, tt := range tests {
t.Run(tt.typeID.String(), func(t *testing.T) {
pool := memory.NewCheckedAllocator(memory.NewGoAllocator())
defer pool.AssertSize(t, 0)
var (
vs = []int32{-1, 3, 4, 5, 6, 0, 1, 2}
lengths = []int{3, 0, 0, 4}
isValid = []bool{true, false, true, true}
)
lb := array.NewBuilder(pool, tt.dt).(array.VarLenListLikeBuilder)
defer lb.Release()
vb := lb.ValueBuilder().(*array.Int32Builder)
vb.Reserve(len(vs))
switch tt.typeID {
case arrow.LIST_VIEW:
lb.(*array.ListViewBuilder).AppendValuesWithSizes(tt.offsets.([]int32), tt.sizes.([]int32), isValid)
case arrow.LARGE_LIST_VIEW:
lb.(*array.LargeListViewBuilder).AppendValuesWithSizes(tt.offsets.([]int64), tt.sizes.([]int64), isValid)
}
for _, v := range vs {
vb.Append(v)
}
arr := lb.NewArray().(array.VarLenListLike)
defer arr.Release()
if got, want := arr.DataType().ID(), tt.typeID; got != want {
t.Fatalf("got=%v, want=%v", got, want)
}
if got, want := arr.Len(), len(isValid); got != want {
t.Fatalf("got=%d, want=%d", got, want)
}
for i := range lengths {
if got, want := arr.IsValid(i), isValid[i]; got != want {
t.Fatalf("got[%d]=%v, want[%d]=%v", i, got, i, want)
}
if got, want := arr.IsNull(i), !isValid[i]; got != want {
t.Fatalf("got[%d]=%v, want[%d]=%v", i, got, i, want)
}
}
var gotOffsets, gotSizes interface{}
switch tt.typeID {
case arrow.LIST_VIEW:
arr := arr.(*array.ListView)
gotOffsets = arr.Offsets()
gotSizes = arr.Sizes()
case arrow.LARGE_LIST_VIEW:
arr := arr.(*array.LargeListView)
gotOffsets = arr.Offsets()
gotSizes = arr.Sizes()
}
if !reflect.DeepEqual(gotOffsets, tt.offsets) {
t.Fatalf("got=%v, want=%v", gotOffsets, tt.offsets)
}
if !reflect.DeepEqual(gotSizes, tt.sizes) {
t.Fatalf("got=%v, want=%v", gotSizes, tt.sizes)
}
varr := arr.ListValues().(*array.Int32)
if got, want := varr.Int32Values(), vs; !reflect.DeepEqual(got, want) {
t.Fatalf("got=%v, want=%v", got, want)
}
})
}
}
func TestListArraySlice(t *testing.T) {
tests := []struct {
typeID arrow.Type
offsets interface{}
sizes interface{}
dt arrow.DataType
}{
{arrow.LIST, []int32{0, 3, 3, 3, 7}, nil, arrow.ListOf(arrow.PrimitiveTypes.Int32)},
{arrow.LARGE_LIST, []int64{0, 3, 3, 3, 7}, nil, arrow.LargeListOf(arrow.PrimitiveTypes.Int32)},
{arrow.LIST_VIEW, []int32{0, 3, 3, 3, 7}, []int32{3, 0, 0, 4}, arrow.ListViewOf(arrow.PrimitiveTypes.Int32)},
{arrow.LARGE_LIST_VIEW, []int64{0, 3, 3, 3, 7}, []int64{3, 0, 0, 4}, arrow.LargeListViewOf(arrow.PrimitiveTypes.Int32)},
}
for _, tt := range tests {
t.Run(tt.typeID.String(), func(t *testing.T) {
pool := memory.NewCheckedAllocator(memory.NewGoAllocator())
defer pool.AssertSize(t, 0)
var (
vs = []int32{0, 1, 2, 3, 4, 5, 6}
lengths = []int{3, 0, 0, 4}
isValid = []bool{true, false, true, true}
)
lb := array.NewBuilder(pool, tt.dt).(array.VarLenListLikeBuilder)
defer lb.Release()
vb := lb.ValueBuilder().(*array.Int32Builder)
vb.Reserve(len(vs))
switch tt.typeID {
case arrow.LIST:
lb.(*array.ListBuilder).AppendValues(tt.offsets.([]int32), isValid)
case arrow.LARGE_LIST:
lb.(*array.LargeListBuilder).AppendValues(tt.offsets.([]int64), isValid)
case arrow.LIST_VIEW:
lb.(*array.ListViewBuilder).AppendValuesWithSizes(tt.offsets.([]int32), tt.sizes.([]int32), isValid)
case arrow.LARGE_LIST_VIEW:
lb.(*array.LargeListViewBuilder).AppendValuesWithSizes(tt.offsets.([]int64), tt.sizes.([]int64), isValid)
}
for _, v := range vs {
vb.Append(v)
}
arr := lb.NewArray().(array.VarLenListLike)
defer arr.Release()
if got, want := arr.DataType().ID(), tt.typeID; got != want {
t.Fatalf("got=%v, want=%v", got, want)
}
if got, want := arr.Len(), len(isValid); got != want {
t.Fatalf("got=%d, want=%d", got, want)
}
for i := range lengths {
if got, want := arr.IsValid(i), isValid[i]; got != want {
t.Fatalf("got[%d]=%v, want[%d]=%v", i, got, i, want)
}
if got, want := arr.IsNull(i), !isValid[i]; got != want {
t.Fatalf("got[%d]=%v, want[%d]=%v", i, got, i, want)
}
}
var gotOffsets, gotSizes interface{}
switch tt.typeID {
case arrow.LIST:
arr := arr.(*array.List)
gotOffsets = arr.Offsets()
case arrow.LARGE_LIST:
arr := arr.(*array.LargeList)
gotOffsets = arr.Offsets()
case arrow.LIST_VIEW:
arr := arr.(*array.ListView)
gotOffsets = arr.Offsets()
gotSizes = arr.Sizes()
case arrow.LARGE_LIST_VIEW:
arr := arr.(*array.LargeListView)
gotOffsets = arr.Offsets()
gotSizes = arr.Sizes()
}
if !reflect.DeepEqual(gotOffsets, tt.offsets) {
t.Fatalf("got=%v, want=%v", gotOffsets, tt.offsets)
}
if tt.typeID == arrow.LIST_VIEW || tt.typeID == arrow.LARGE_LIST_VIEW {
if !reflect.DeepEqual(gotSizes, tt.sizes) {
t.Fatalf("got=%v, want=%v", gotSizes, tt.sizes)
}
}
varr := arr.ListValues().(*array.Int32)
if got, want := varr.Int32Values(), vs; !reflect.DeepEqual(got, want) {
t.Fatalf("got=%v, want=%v", got, want)
}
if got, want := arr.String(), `[[0 1 2] (null) [] [3 4 5 6]]`; got != want {
t.Fatalf("got=%q, want=%q", got, want)
}
assert.Equal(t, "[0,1,2]", arr.ValueStr(0))
sub := array.NewSlice(arr, 1, 4).(array.ListLike)
defer sub.Release()
if got, want := sub.String(), `[(null) [] [3 4 5 6]]`; got != want {
t.Fatalf("got=%q, want=%q", got, want)
}
})
}
}
func TestListViewArraySlice(t *testing.T) {
tests := []struct {
typeID arrow.Type
offsets interface{}
sizes interface{}
dt arrow.DataType
}{
{arrow.LIST_VIEW, []int32{5, 0, 0, 1}, []int32{3, 0, 0, 4}, arrow.ListViewOf(arrow.PrimitiveTypes.Int32)},
{arrow.LARGE_LIST_VIEW, []int64{5, 0, 0, 1}, []int64{3, 0, 0, 4}, arrow.LargeListViewOf(arrow.PrimitiveTypes.Int32)},
}
for _, tt := range tests {
t.Run(tt.typeID.String(), func(t *testing.T) {
pool := memory.NewCheckedAllocator(memory.NewGoAllocator())
defer pool.AssertSize(t, 0)
var (
vs = []int32{-1, 3, 4, 5, 6, 0, 1, 2}
lengths = []int{3, 0, 0, 4}
isValid = []bool{true, false, true, true}
)
lb := array.NewBuilder(pool, tt.dt).(array.VarLenListLikeBuilder)
defer lb.Release()
vb := lb.ValueBuilder().(*array.Int32Builder)
vb.Reserve(len(vs))
switch tt.typeID {
case arrow.LIST_VIEW:
lb.(*array.ListViewBuilder).AppendValuesWithSizes(tt.offsets.([]int32), tt.sizes.([]int32), isValid)
case arrow.LARGE_LIST_VIEW:
lb.(*array.LargeListViewBuilder).AppendValuesWithSizes(tt.offsets.([]int64), tt.sizes.([]int64), isValid)
}
for _, v := range vs {
vb.Append(v)
}
arr := lb.NewArray().(array.VarLenListLike)
defer arr.Release()
if got, want := arr.DataType().ID(), tt.typeID; got != want {
t.Fatalf("got=%v, want=%v", got, want)
}
if got, want := arr.Len(), len(isValid); got != want {
t.Fatalf("got=%d, want=%d", got, want)
}
for i := range lengths {
if got, want := arr.IsValid(i), isValid[i]; got != want {
t.Fatalf("got[%d]=%v, want[%d]=%v", i, got, i, want)
}
if got, want := arr.IsNull(i), !isValid[i]; got != want {
t.Fatalf("got[%d]=%v, want[%d]=%v", i, got, i, want)
}
}
var gotOffsets, gotSizes interface{}
switch tt.typeID {
case arrow.LIST_VIEW:
arr := arr.(*array.ListView)
gotOffsets = arr.Offsets()
gotSizes = arr.Sizes()
case arrow.LARGE_LIST_VIEW:
arr := arr.(*array.LargeListView)
gotOffsets = arr.Offsets()
gotSizes = arr.Sizes()
}
if !reflect.DeepEqual(gotOffsets, tt.offsets) {
t.Fatalf("got=%v, want=%v", gotOffsets, tt.offsets)
}
if !reflect.DeepEqual(gotSizes, tt.sizes) {
t.Fatalf("got=%v, want=%v", gotSizes, tt.sizes)
}
varr := arr.ListValues().(*array.Int32)
if got, want := varr.Int32Values(), vs; !reflect.DeepEqual(got, want) {
t.Fatalf("got=%v, want=%v", got, want)
}
if got, want := arr.String(), `[[0 1 2] (null) [] [3 4 5 6]]`; got != want {
t.Fatalf("got=%q, want=%q", got, want)
}
assert.Equal(t, "[0,1,2]", arr.ValueStr(0))
sub := array.NewSlice(arr, 1, 4).(array.ListLike)
defer sub.Release()
if got, want := sub.String(), `[(null) [] [3 4 5 6]]`; got != want {
t.Fatalf("got=%q, want=%q", got, want)
}
})
}
}
func TestVarLenListLikeStringRoundTrip(t *testing.T) {
// 1. create array
mem := memory.NewCheckedAllocator(memory.NewGoAllocator())
defer mem.AssertSize(t, 0)
builders := []array.VarLenListLikeBuilder{
array.NewListBuilder(mem, arrow.PrimitiveTypes.Int32),
array.NewListViewBuilder(mem, arrow.PrimitiveTypes.Int32),
array.NewLargeListBuilder(mem, arrow.PrimitiveTypes.Int32),
array.NewLargeListViewBuilder(mem, arrow.PrimitiveTypes.Int32),
}
builders1 := []array.VarLenListLikeBuilder{
array.NewListBuilder(mem, arrow.PrimitiveTypes.Int32),
array.NewListViewBuilder(mem, arrow.PrimitiveTypes.Int32),
array.NewLargeListBuilder(mem, arrow.PrimitiveTypes.Int32),
array.NewLargeListViewBuilder(mem, arrow.PrimitiveTypes.Int32),
}
for i, b := range builders {
defer b.Release()
vb := b.ValueBuilder().(*array.Int32Builder)
var values = [][]int32{
{0, 1, 2, 3, 4, 5, 6},
{1, 2, 3, 4, 5, 6, 7},
{2, 3, 4, 5, 6, 7, 8},
{3, 4, 5, 6, 7, 8, 9},
}
for _, value := range values {
b.AppendNull()
b.AppendWithSize(true, 2*len(value))
for _, el := range value {
vb.Append(el)
vb.AppendNull()
}
b.AppendWithSize(false, 0)
}
arr := b.NewArray()
defer arr.Release()
// 2. create array via AppendValueFromString
b1 := builders1[i]
defer b1.Release()
for i := 0; i < arr.Len(); i++ {
assert.NoError(t, b1.AppendValueFromString(arr.ValueStr(i)))
}
arr1 := b1.NewArray()
defer arr1.Release()
assert.True(t, array.Equal(arr, arr1))
}
}
// Test the string roun-trip for a list-view containing out-of-order offsets.
func TestListViewStringRoundTrip(t *testing.T) {
// 1. create array
mem := memory.NewCheckedAllocator(memory.NewGoAllocator())
defer mem.AssertSize(t, 0)
builders := []array.VarLenListLikeBuilder{
array.NewListViewBuilder(mem, arrow.PrimitiveTypes.Int32),
array.NewLargeListViewBuilder(mem, arrow.PrimitiveTypes.Int32),
}
builders1 := []array.VarLenListLikeBuilder{
array.NewListViewBuilder(mem, arrow.PrimitiveTypes.Int32),
array.NewLargeListViewBuilder(mem, arrow.PrimitiveTypes.Int32),
}
for i, b := range builders {
defer b.Release()
switch lvb := b.(type) {
case *array.ListViewBuilder:
lvb.AppendDimensions(5, 3)
b.AppendNull()
lvb.AppendDimensions(0, 0)
lvb.AppendDimensions(1, 4)
case *array.LargeListViewBuilder:
lvb.AppendDimensions(5, 3)
b.AppendNull()
lvb.AppendDimensions(0, 0)
lvb.AppendDimensions(1, 4)
}
vb := b.ValueBuilder().(*array.Int32Builder)
vs := []int32{-1, 3, 4, 5, 6, 0, 1, 2}
isValid := []bool{false, true, true, true, true, true, true, true}
vb.Reserve(len(vs))
vb.AppendValues(vs, isValid)
arr := b.NewArray()
defer arr.Release()
// 2. create array via AppendValueFromString
b1 := builders1[i]
defer b1.Release()
for i := 0; i < arr.Len(); i++ {
assert.NoError(t, b1.AppendValueFromString(arr.ValueStr(i)))
}
arr1 := b1.NewArray()
defer arr1.Release()
assert.True(t, array.Equal(arr, arr1))
}
}
func TestRangeOfValuesUsed(t *testing.T) {
tests := []struct {
typeID arrow.Type
dt arrow.DataType
}{
{arrow.LIST, arrow.ListOf(arrow.PrimitiveTypes.Int16)},
{arrow.LARGE_LIST, arrow.LargeListOf(arrow.PrimitiveTypes.Int16)},
{arrow.LIST_VIEW, arrow.ListViewOf(arrow.PrimitiveTypes.Int16)},
{arrow.LARGE_LIST_VIEW, arrow.LargeListViewOf(arrow.PrimitiveTypes.Int16)},
}
for _, tt := range tests {
t.Run(tt.typeID.String(), func(t *testing.T) {
pool := memory.NewCheckedAllocator(memory.NewGoAllocator())
defer pool.AssertSize(t, 0)
isListView := tt.typeID == arrow.LIST_VIEW || tt.typeID == arrow.LARGE_LIST_VIEW
bldr := array.NewBuilder(pool, tt.dt).(array.VarLenListLikeBuilder)
defer bldr.Release()
var arr array.VarLenListLike
// Empty array
arr = bldr.NewArray().(array.VarLenListLike)
defer arr.Release()
offset, len := array.RangeOfValuesUsed(arr)
assert.Equal(t, 0, offset)
assert.Equal(t, 0, len)
// List-like array with only nulls
bldr.AppendNulls(3)
arr = bldr.NewArray().(array.VarLenListLike)
defer arr.Release()
offset, len = array.RangeOfValuesUsed(arr)
assert.Equal(t, 0, offset)
assert.Equal(t, 0, len)
// Array with nulls and non-nulls (starting at a non-zero offset)
vb := bldr.ValueBuilder().(*array.Int16Builder)
vb.Append(-2)
vb.Append(-1)
bldr.AppendWithSize(false, 0)
bldr.AppendWithSize(true, 2)
vb.Append(0)
vb.Append(1)
bldr.AppendWithSize(true, 3)
vb.Append(2)
vb.Append(3)
vb.Append(4)
if isListView {
vb.Append(10)
vb.Append(11)
}
arr = bldr.NewArray().(array.VarLenListLike)
defer arr.Release()
offset, len = array.RangeOfValuesUsed(arr)
assert.Equal(t, 2, offset)
assert.Equal(t, 5, len)
// Overlapping list-views
// [null, [0, 1, 2, 3, 4, 5], [1, 2], null, [4], null, null]
vb = bldr.ValueBuilder().(*array.Int16Builder)
vb.Append(-2)
vb.Append(-1)
bldr.AppendWithSize(false, 0)
if isListView {
bldr.AppendWithSize(true, 6)
vb.Append(0)
bldr.AppendWithSize(true, 2)
vb.Append(1)
vb.Append(2)
vb.Append(3)
bldr.AppendWithSize(false, 0)
bldr.AppendWithSize(true, 1)
vb.Append(4)
vb.Append(5)
// -- used range ends here --
vb.Append(10)
vb.Append(11)
} else {
bldr.AppendWithSize(true, 6)
vb.Append(0)
vb.Append(1)
vb.Append(2)
vb.Append(3)
vb.Append(4)
vb.Append(5)
bldr.AppendWithSize(true, 2)
vb.Append(1)
vb.Append(2)
bldr.AppendWithSize(false, 0)
bldr.AppendWithSize(true, 1)
vb.Append(4)
}
bldr.AppendNulls(2)
arr = bldr.NewArray().(array.VarLenListLike)
defer arr.Release()
// Check the range
offset, len = array.RangeOfValuesUsed(arr)
assert.Equal(t, 2, offset)
if isListView {
assert.Equal(t, 6, len)
} else {
assert.Equal(t, 9, len)
}
})
}
}