| // 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) |
| } |
| }) |
| } |
| } |