github.com/apache/arrow/go/v16@v16.1.0/arrow/array/list_test.go (about) 1 // Licensed to the Apache Software Foundation (ASF) under one 2 // or more contributor license agreements. See the NOTICE file 3 // distributed with this work for additional information 4 // regarding copyright ownership. The ASF licenses this file 5 // to you under the Apache License, Version 2.0 (the 6 // "License"); you may not use this file except in compliance 7 // with the License. You may obtain a copy of the License at 8 // 9 // http://www.apache.org/licenses/LICENSE-2.0 10 // 11 // Unless required by applicable law or agreed to in writing, software 12 // distributed under the License is distributed on an "AS IS" BASIS, 13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 // See the License for the specific language governing permissions and 15 // limitations under the License. 16 17 package array_test 18 19 import ( 20 "reflect" 21 "testing" 22 23 "github.com/apache/arrow/go/v16/arrow" 24 "github.com/apache/arrow/go/v16/arrow/array" 25 "github.com/apache/arrow/go/v16/arrow/memory" 26 "github.com/stretchr/testify/assert" 27 ) 28 29 func TestListArray(t *testing.T) { 30 tests := []struct { 31 typeID arrow.Type 32 offsets interface{} 33 sizes interface{} 34 dt arrow.DataType 35 }{ 36 {arrow.LIST, []int32{0, 3, 3, 3, 7}, nil, arrow.ListOf(arrow.PrimitiveTypes.Int32)}, 37 {arrow.LARGE_LIST, []int64{0, 3, 3, 3, 7}, nil, arrow.LargeListOf(arrow.PrimitiveTypes.Int32)}, 38 {arrow.LIST, []int32{0, 3, 3, 3, 7}, nil, arrow.ListOfField(arrow.Field{Name: "item", Type: arrow.PrimitiveTypes.Int32, Nullable: true})}, 39 {arrow.LARGE_LIST, []int64{0, 3, 3, 3, 7}, nil, arrow.LargeListOfField(arrow.Field{Name: "item", Type: arrow.PrimitiveTypes.Int32, Nullable: true})}, 40 {arrow.LIST_VIEW, []int32{0, 3, 3, 3}, []int32{3, 0, 0, 4}, arrow.ListViewOf(arrow.PrimitiveTypes.Int32)}, 41 {arrow.LARGE_LIST_VIEW, []int64{0, 3, 3, 3}, []int64{3, 0, 0, 4}, arrow.LargeListViewOf(arrow.PrimitiveTypes.Int32)}, 42 } 43 44 for _, tt := range tests { 45 t.Run(tt.typeID.String(), func(t *testing.T) { 46 pool := memory.NewCheckedAllocator(memory.NewGoAllocator()) 47 defer pool.AssertSize(t, 0) 48 49 var ( 50 vs = []int32{0, 1, 2, 3, 4, 5, 6} 51 lengths = []int{3, 0, 0, 4} 52 isValid = []bool{true, false, true, true} 53 ) 54 55 lb := array.NewBuilder(pool, tt.dt).(array.VarLenListLikeBuilder) 56 defer lb.Release() 57 58 for i := 0; i < 10; i++ { 59 vb := lb.ValueBuilder().(*array.Int32Builder) 60 vb.Reserve(len(vs)) 61 62 pos := 0 63 for i, length := range lengths { 64 lb.AppendWithSize(isValid[i], length) 65 for j := 0; j < length; j++ { 66 vb.Append(vs[pos]) 67 pos++ 68 } 69 } 70 71 arr := lb.NewArray().(array.ListLike) 72 defer arr.Release() 73 74 arr.Retain() 75 arr.Release() 76 77 if got, want := arr.DataType().ID(), tt.typeID; got != want { 78 t.Fatalf("got=%v, want=%v", got, want) 79 } 80 81 if got, want := arr.Len(), len(isValid); got != want { 82 t.Fatalf("got=%d, want=%d", got, want) 83 } 84 85 for i := range lengths { 86 if got, want := arr.IsValid(i), isValid[i]; got != want { 87 t.Fatalf("got[%d]=%v, want[%d]=%v", i, got, i, want) 88 } 89 if got, want := arr.IsNull(i), !isValid[i]; got != want { 90 t.Fatalf("got[%d]=%v, want[%d]=%v", i, got, i, want) 91 } 92 } 93 94 var gotOffsets, gotSizes interface{} 95 switch tt.typeID { 96 case arrow.LIST: 97 arr := arr.(*array.List) 98 gotOffsets = arr.Offsets() 99 case arrow.LARGE_LIST: 100 arr := arr.(*array.LargeList) 101 gotOffsets = arr.Offsets() 102 case arrow.LIST_VIEW: 103 arr := arr.(*array.ListView) 104 gotOffsets = arr.Offsets() 105 gotSizes = arr.Sizes() 106 case arrow.LARGE_LIST_VIEW: 107 arr := arr.(*array.LargeListView) 108 gotOffsets = arr.Offsets() 109 gotSizes = arr.Sizes() 110 } 111 112 if !reflect.DeepEqual(gotOffsets, tt.offsets) { 113 t.Fatalf("got=%v, want=%v", gotOffsets, tt.offsets) 114 } 115 116 if tt.typeID == arrow.LIST_VIEW || tt.typeID == arrow.LARGE_LIST_VIEW { 117 if !reflect.DeepEqual(gotSizes, tt.sizes) { 118 t.Fatalf("got=%v, want=%v", gotSizes, tt.sizes) 119 } 120 } 121 122 varr := arr.ListValues().(*array.Int32) 123 if got, want := varr.Int32Values(), vs; !reflect.DeepEqual(got, want) { 124 t.Fatalf("got=%v, want=%v", got, want) 125 } 126 } 127 }) 128 } 129 } 130 131 // Like the list-view tests in TestListArray, but with out-of-order offsets. 132 func TestListViewArray(t *testing.T) { 133 tests := []struct { 134 typeID arrow.Type 135 offsets interface{} 136 sizes interface{} 137 dt arrow.DataType 138 }{ 139 {arrow.LIST_VIEW, []int32{5, 0, 0, 1}, []int32{3, 0, 0, 4}, arrow.ListViewOf(arrow.PrimitiveTypes.Int32)}, 140 {arrow.LARGE_LIST_VIEW, []int64{5, 0, 0, 1}, []int64{3, 0, 0, 4}, arrow.LargeListViewOf(arrow.PrimitiveTypes.Int32)}, 141 } 142 143 for _, tt := range tests { 144 t.Run(tt.typeID.String(), func(t *testing.T) { 145 pool := memory.NewCheckedAllocator(memory.NewGoAllocator()) 146 defer pool.AssertSize(t, 0) 147 148 var ( 149 vs = []int32{-1, 3, 4, 5, 6, 0, 1, 2} 150 lengths = []int{3, 0, 0, 4} 151 isValid = []bool{true, false, true, true} 152 ) 153 154 lb := array.NewBuilder(pool, tt.dt).(array.VarLenListLikeBuilder) 155 defer lb.Release() 156 157 for i := 0; i < 10; i++ { 158 switch lvb := lb.(type) { 159 case *array.ListViewBuilder: 160 lvb.AppendDimensions(5, 3) 161 lb.AppendNull() 162 lvb.AppendDimensions(0, 0) 163 lvb.AppendDimensions(1, 4) 164 case *array.LargeListViewBuilder: 165 lvb.AppendDimensions(5, 3) 166 lb.AppendNull() 167 lvb.AppendDimensions(0, 0) 168 lvb.AppendDimensions(1, 4) 169 } 170 171 vb := lb.ValueBuilder().(*array.Int32Builder) 172 vb.Reserve(len(vs)) 173 vb.AppendValues(vs, []bool{false, true, true, true, true, true, true, true}) 174 175 arr := lb.NewArray().(array.ListLike) 176 defer arr.Release() 177 178 arr.Retain() 179 arr.Release() 180 181 if got, want := arr.DataType().ID(), tt.typeID; got != want { 182 t.Fatalf("got=%v, want=%v", got, want) 183 } 184 185 if got, want := arr.Len(), len(isValid); got != want { 186 t.Fatalf("got=%d, want=%d", got, want) 187 } 188 189 for i := range lengths { 190 if got, want := arr.IsValid(i), isValid[i]; got != want { 191 t.Fatalf("got[%d]=%v, want[%d]=%v", i, got, i, want) 192 } 193 if got, want := arr.IsNull(i), !isValid[i]; got != want { 194 t.Fatalf("got[%d]=%v, want[%d]=%v", i, got, i, want) 195 } 196 } 197 198 var gotOffsets, gotSizes interface{} 199 switch tt.typeID { 200 case arrow.LIST_VIEW: 201 arr := arr.(*array.ListView) 202 gotOffsets = arr.Offsets() 203 gotSizes = arr.Sizes() 204 case arrow.LARGE_LIST_VIEW: 205 arr := arr.(*array.LargeListView) 206 gotOffsets = arr.Offsets() 207 gotSizes = arr.Sizes() 208 } 209 210 if !reflect.DeepEqual(gotOffsets, tt.offsets) { 211 t.Fatalf("got=%v, want=%v", gotOffsets, tt.offsets) 212 } 213 214 if !reflect.DeepEqual(gotSizes, tt.sizes) { 215 t.Fatalf("got=%v, want=%v", gotSizes, tt.sizes) 216 } 217 218 varr := arr.ListValues().(*array.Int32) 219 if got, want := varr.Int32Values(), vs; !reflect.DeepEqual(got, want) { 220 t.Fatalf("got=%v, want=%v", got, want) 221 } 222 } 223 }) 224 } 225 } 226 227 func TestListArrayEmpty(t *testing.T) { 228 typ := []arrow.DataType{ 229 arrow.ListOf(arrow.PrimitiveTypes.Int32), 230 arrow.LargeListOf(arrow.PrimitiveTypes.Int32), 231 arrow.ListViewOf(arrow.PrimitiveTypes.Int32), 232 arrow.LargeListViewOf(arrow.PrimitiveTypes.Int32), 233 } 234 235 for _, dt := range typ { 236 t.Run(dt.String(), func(t *testing.T) { 237 pool := memory.NewCheckedAllocator(memory.NewGoAllocator()) 238 defer pool.AssertSize(t, 0) 239 240 lb := array.NewBuilder(pool, dt) 241 defer lb.Release() 242 arr := lb.NewArray() 243 defer arr.Release() 244 if got, want := arr.Len(), 0; got != want { 245 t.Fatalf("got=%d, want=%d", got, want) 246 } 247 }) 248 } 249 } 250 251 func TestListArrayBulkAppend(t *testing.T) { 252 tests := []struct { 253 typeID arrow.Type 254 offsets interface{} 255 sizes interface{} 256 dt arrow.DataType 257 }{ 258 {arrow.LIST, []int32{0, 3, 3, 3, 7}, nil, arrow.ListOf(arrow.PrimitiveTypes.Int32)}, 259 {arrow.LARGE_LIST, []int64{0, 3, 3, 3, 7}, nil, arrow.LargeListOf(arrow.PrimitiveTypes.Int32)}, 260 {arrow.LIST_VIEW, []int32{0, 3, 3, 3}, []int32{3, 0, 0, 4}, arrow.ListViewOf(arrow.PrimitiveTypes.Int32)}, 261 {arrow.LARGE_LIST_VIEW, []int64{0, 3, 3, 3}, []int64{3, 0, 0, 4}, arrow.LargeListViewOf(arrow.PrimitiveTypes.Int32)}, 262 } 263 264 for _, tt := range tests { 265 t.Run(tt.typeID.String(), func(t *testing.T) { 266 pool := memory.NewCheckedAllocator(memory.NewGoAllocator()) 267 defer pool.AssertSize(t, 0) 268 269 var ( 270 vs = []int32{0, 1, 2, 3, 4, 5, 6} 271 lengths = []int{3, 0, 0, 4} 272 isValid = []bool{true, false, true, true} 273 ) 274 275 lb := array.NewBuilder(pool, tt.dt).(array.VarLenListLikeBuilder) 276 defer lb.Release() 277 vb := lb.ValueBuilder().(*array.Int32Builder) 278 vb.Reserve(len(vs)) 279 280 switch tt.typeID { 281 case arrow.LIST: 282 lb.(*array.ListBuilder).AppendValues(tt.offsets.([]int32), isValid) 283 case arrow.LARGE_LIST: 284 lb.(*array.LargeListBuilder).AppendValues(tt.offsets.([]int64), isValid) 285 case arrow.LIST_VIEW: 286 lb.(*array.ListViewBuilder).AppendValuesWithSizes(tt.offsets.([]int32), tt.sizes.([]int32), isValid) 287 case arrow.LARGE_LIST_VIEW: 288 lb.(*array.LargeListViewBuilder).AppendValuesWithSizes(tt.offsets.([]int64), tt.sizes.([]int64), isValid) 289 } 290 for _, v := range vs { 291 vb.Append(v) 292 } 293 294 arr := lb.NewArray().(array.VarLenListLike) 295 defer arr.Release() 296 297 if got, want := arr.DataType().ID(), tt.typeID; got != want { 298 t.Fatalf("got=%v, want=%v", got, want) 299 } 300 301 if got, want := arr.Len(), len(isValid); got != want { 302 t.Fatalf("got=%d, want=%d", got, want) 303 } 304 305 for i := range lengths { 306 if got, want := arr.IsValid(i), isValid[i]; got != want { 307 t.Fatalf("got[%d]=%v, want[%d]=%v", i, got, i, want) 308 } 309 if got, want := arr.IsNull(i), !isValid[i]; got != want { 310 t.Fatalf("got[%d]=%v, want[%d]=%v", i, got, i, want) 311 } 312 } 313 314 var gotOffsets, gotSizes interface{} 315 switch tt.typeID { 316 case arrow.LIST: 317 arr := arr.(*array.List) 318 gotOffsets = arr.Offsets() 319 case arrow.LARGE_LIST: 320 arr := arr.(*array.LargeList) 321 gotOffsets = arr.Offsets() 322 case arrow.LIST_VIEW: 323 arr := arr.(*array.ListView) 324 gotOffsets = arr.Offsets() 325 gotSizes = arr.Sizes() 326 case arrow.LARGE_LIST_VIEW: 327 arr := arr.(*array.LargeListView) 328 gotOffsets = arr.Offsets() 329 gotSizes = arr.Sizes() 330 } 331 332 if !reflect.DeepEqual(gotOffsets, tt.offsets) { 333 t.Fatalf("got=%v, want=%v", gotOffsets, tt.offsets) 334 } 335 if tt.typeID == arrow.LIST_VIEW || tt.typeID == arrow.LARGE_LIST_VIEW { 336 if !reflect.DeepEqual(gotSizes, tt.sizes) { 337 t.Fatalf("got=%v, want=%v", gotSizes, tt.sizes) 338 } 339 } 340 341 varr := arr.ListValues().(*array.Int32) 342 if got, want := varr.Int32Values(), vs; !reflect.DeepEqual(got, want) { 343 t.Fatalf("got=%v, want=%v", got, want) 344 } 345 }) 346 } 347 } 348 349 func TestListViewArrayBulkAppend(t *testing.T) { 350 tests := []struct { 351 typeID arrow.Type 352 offsets interface{} 353 sizes interface{} 354 dt arrow.DataType 355 }{ 356 {arrow.LIST_VIEW, []int32{5, 0, 0, 1}, []int32{3, 0, 0, 4}, arrow.ListViewOf(arrow.PrimitiveTypes.Int32)}, 357 {arrow.LARGE_LIST_VIEW, []int64{5, 0, 0, 1}, []int64{3, 0, 0, 4}, arrow.LargeListViewOf(arrow.PrimitiveTypes.Int32)}, 358 } 359 360 for _, tt := range tests { 361 t.Run(tt.typeID.String(), func(t *testing.T) { 362 pool := memory.NewCheckedAllocator(memory.NewGoAllocator()) 363 defer pool.AssertSize(t, 0) 364 365 var ( 366 vs = []int32{-1, 3, 4, 5, 6, 0, 1, 2} 367 lengths = []int{3, 0, 0, 4} 368 isValid = []bool{true, false, true, true} 369 ) 370 371 lb := array.NewBuilder(pool, tt.dt).(array.VarLenListLikeBuilder) 372 defer lb.Release() 373 vb := lb.ValueBuilder().(*array.Int32Builder) 374 vb.Reserve(len(vs)) 375 376 switch tt.typeID { 377 case arrow.LIST_VIEW: 378 lb.(*array.ListViewBuilder).AppendValuesWithSizes(tt.offsets.([]int32), tt.sizes.([]int32), isValid) 379 case arrow.LARGE_LIST_VIEW: 380 lb.(*array.LargeListViewBuilder).AppendValuesWithSizes(tt.offsets.([]int64), tt.sizes.([]int64), isValid) 381 } 382 for _, v := range vs { 383 vb.Append(v) 384 } 385 386 arr := lb.NewArray().(array.VarLenListLike) 387 defer arr.Release() 388 389 if got, want := arr.DataType().ID(), tt.typeID; got != want { 390 t.Fatalf("got=%v, want=%v", got, want) 391 } 392 393 if got, want := arr.Len(), len(isValid); got != want { 394 t.Fatalf("got=%d, want=%d", got, want) 395 } 396 397 for i := range lengths { 398 if got, want := arr.IsValid(i), isValid[i]; got != want { 399 t.Fatalf("got[%d]=%v, want[%d]=%v", i, got, i, want) 400 } 401 if got, want := arr.IsNull(i), !isValid[i]; got != want { 402 t.Fatalf("got[%d]=%v, want[%d]=%v", i, got, i, want) 403 } 404 } 405 406 var gotOffsets, gotSizes interface{} 407 switch tt.typeID { 408 case arrow.LIST_VIEW: 409 arr := arr.(*array.ListView) 410 gotOffsets = arr.Offsets() 411 gotSizes = arr.Sizes() 412 case arrow.LARGE_LIST_VIEW: 413 arr := arr.(*array.LargeListView) 414 gotOffsets = arr.Offsets() 415 gotSizes = arr.Sizes() 416 } 417 418 if !reflect.DeepEqual(gotOffsets, tt.offsets) { 419 t.Fatalf("got=%v, want=%v", gotOffsets, tt.offsets) 420 } 421 if !reflect.DeepEqual(gotSizes, tt.sizes) { 422 t.Fatalf("got=%v, want=%v", gotSizes, tt.sizes) 423 } 424 425 varr := arr.ListValues().(*array.Int32) 426 if got, want := varr.Int32Values(), vs; !reflect.DeepEqual(got, want) { 427 t.Fatalf("got=%v, want=%v", got, want) 428 } 429 }) 430 } 431 } 432 433 func TestListArraySlice(t *testing.T) { 434 tests := []struct { 435 typeID arrow.Type 436 offsets interface{} 437 sizes interface{} 438 dt arrow.DataType 439 }{ 440 {arrow.LIST, []int32{0, 3, 3, 3, 7}, nil, arrow.ListOf(arrow.PrimitiveTypes.Int32)}, 441 {arrow.LARGE_LIST, []int64{0, 3, 3, 3, 7}, nil, arrow.LargeListOf(arrow.PrimitiveTypes.Int32)}, 442 {arrow.LIST_VIEW, []int32{0, 3, 3, 3, 7}, []int32{3, 0, 0, 4}, arrow.ListViewOf(arrow.PrimitiveTypes.Int32)}, 443 {arrow.LARGE_LIST_VIEW, []int64{0, 3, 3, 3, 7}, []int64{3, 0, 0, 4}, arrow.LargeListViewOf(arrow.PrimitiveTypes.Int32)}, 444 } 445 446 for _, tt := range tests { 447 t.Run(tt.typeID.String(), func(t *testing.T) { 448 pool := memory.NewCheckedAllocator(memory.NewGoAllocator()) 449 defer pool.AssertSize(t, 0) 450 451 var ( 452 vs = []int32{0, 1, 2, 3, 4, 5, 6} 453 lengths = []int{3, 0, 0, 4} 454 isValid = []bool{true, false, true, true} 455 ) 456 457 lb := array.NewBuilder(pool, tt.dt).(array.VarLenListLikeBuilder) 458 defer lb.Release() 459 vb := lb.ValueBuilder().(*array.Int32Builder) 460 vb.Reserve(len(vs)) 461 462 switch tt.typeID { 463 case arrow.LIST: 464 lb.(*array.ListBuilder).AppendValues(tt.offsets.([]int32), isValid) 465 case arrow.LARGE_LIST: 466 lb.(*array.LargeListBuilder).AppendValues(tt.offsets.([]int64), isValid) 467 case arrow.LIST_VIEW: 468 lb.(*array.ListViewBuilder).AppendValuesWithSizes(tt.offsets.([]int32), tt.sizes.([]int32), isValid) 469 case arrow.LARGE_LIST_VIEW: 470 lb.(*array.LargeListViewBuilder).AppendValuesWithSizes(tt.offsets.([]int64), tt.sizes.([]int64), isValid) 471 } 472 for _, v := range vs { 473 vb.Append(v) 474 } 475 476 arr := lb.NewArray().(array.VarLenListLike) 477 defer arr.Release() 478 479 if got, want := arr.DataType().ID(), tt.typeID; got != want { 480 t.Fatalf("got=%v, want=%v", got, want) 481 } 482 483 if got, want := arr.Len(), len(isValid); got != want { 484 t.Fatalf("got=%d, want=%d", got, want) 485 } 486 487 for i := range lengths { 488 if got, want := arr.IsValid(i), isValid[i]; got != want { 489 t.Fatalf("got[%d]=%v, want[%d]=%v", i, got, i, want) 490 } 491 if got, want := arr.IsNull(i), !isValid[i]; got != want { 492 t.Fatalf("got[%d]=%v, want[%d]=%v", i, got, i, want) 493 } 494 } 495 496 var gotOffsets, gotSizes interface{} 497 switch tt.typeID { 498 case arrow.LIST: 499 arr := arr.(*array.List) 500 gotOffsets = arr.Offsets() 501 case arrow.LARGE_LIST: 502 arr := arr.(*array.LargeList) 503 gotOffsets = arr.Offsets() 504 case arrow.LIST_VIEW: 505 arr := arr.(*array.ListView) 506 gotOffsets = arr.Offsets() 507 gotSizes = arr.Sizes() 508 case arrow.LARGE_LIST_VIEW: 509 arr := arr.(*array.LargeListView) 510 gotOffsets = arr.Offsets() 511 gotSizes = arr.Sizes() 512 } 513 514 if !reflect.DeepEqual(gotOffsets, tt.offsets) { 515 t.Fatalf("got=%v, want=%v", gotOffsets, tt.offsets) 516 } 517 518 if tt.typeID == arrow.LIST_VIEW || tt.typeID == arrow.LARGE_LIST_VIEW { 519 if !reflect.DeepEqual(gotSizes, tt.sizes) { 520 t.Fatalf("got=%v, want=%v", gotSizes, tt.sizes) 521 } 522 } 523 524 varr := arr.ListValues().(*array.Int32) 525 if got, want := varr.Int32Values(), vs; !reflect.DeepEqual(got, want) { 526 t.Fatalf("got=%v, want=%v", got, want) 527 } 528 529 if got, want := arr.String(), `[[0 1 2] (null) [] [3 4 5 6]]`; got != want { 530 t.Fatalf("got=%q, want=%q", got, want) 531 } 532 assert.Equal(t, "[0,1,2]", arr.ValueStr(0)) 533 534 sub := array.NewSlice(arr, 1, 4).(array.ListLike) 535 defer sub.Release() 536 537 if got, want := sub.String(), `[(null) [] [3 4 5 6]]`; got != want { 538 t.Fatalf("got=%q, want=%q", got, want) 539 } 540 }) 541 } 542 } 543 544 func TestListViewArraySlice(t *testing.T) { 545 tests := []struct { 546 typeID arrow.Type 547 offsets interface{} 548 sizes interface{} 549 dt arrow.DataType 550 }{ 551 {arrow.LIST_VIEW, []int32{5, 0, 0, 1}, []int32{3, 0, 0, 4}, arrow.ListViewOf(arrow.PrimitiveTypes.Int32)}, 552 {arrow.LARGE_LIST_VIEW, []int64{5, 0, 0, 1}, []int64{3, 0, 0, 4}, arrow.LargeListViewOf(arrow.PrimitiveTypes.Int32)}, 553 } 554 555 for _, tt := range tests { 556 t.Run(tt.typeID.String(), func(t *testing.T) { 557 pool := memory.NewCheckedAllocator(memory.NewGoAllocator()) 558 defer pool.AssertSize(t, 0) 559 560 var ( 561 vs = []int32{-1, 3, 4, 5, 6, 0, 1, 2} 562 lengths = []int{3, 0, 0, 4} 563 isValid = []bool{true, false, true, true} 564 ) 565 566 lb := array.NewBuilder(pool, tt.dt).(array.VarLenListLikeBuilder) 567 defer lb.Release() 568 vb := lb.ValueBuilder().(*array.Int32Builder) 569 vb.Reserve(len(vs)) 570 571 switch tt.typeID { 572 case arrow.LIST_VIEW: 573 lb.(*array.ListViewBuilder).AppendValuesWithSizes(tt.offsets.([]int32), tt.sizes.([]int32), isValid) 574 case arrow.LARGE_LIST_VIEW: 575 lb.(*array.LargeListViewBuilder).AppendValuesWithSizes(tt.offsets.([]int64), tt.sizes.([]int64), isValid) 576 } 577 for _, v := range vs { 578 vb.Append(v) 579 } 580 581 arr := lb.NewArray().(array.VarLenListLike) 582 defer arr.Release() 583 584 if got, want := arr.DataType().ID(), tt.typeID; got != want { 585 t.Fatalf("got=%v, want=%v", got, want) 586 } 587 588 if got, want := arr.Len(), len(isValid); got != want { 589 t.Fatalf("got=%d, want=%d", got, want) 590 } 591 592 for i := range lengths { 593 if got, want := arr.IsValid(i), isValid[i]; got != want { 594 t.Fatalf("got[%d]=%v, want[%d]=%v", i, got, i, want) 595 } 596 if got, want := arr.IsNull(i), !isValid[i]; got != want { 597 t.Fatalf("got[%d]=%v, want[%d]=%v", i, got, i, want) 598 } 599 } 600 601 var gotOffsets, gotSizes interface{} 602 switch tt.typeID { 603 case arrow.LIST_VIEW: 604 arr := arr.(*array.ListView) 605 gotOffsets = arr.Offsets() 606 gotSizes = arr.Sizes() 607 case arrow.LARGE_LIST_VIEW: 608 arr := arr.(*array.LargeListView) 609 gotOffsets = arr.Offsets() 610 gotSizes = arr.Sizes() 611 } 612 613 if !reflect.DeepEqual(gotOffsets, tt.offsets) { 614 t.Fatalf("got=%v, want=%v", gotOffsets, tt.offsets) 615 } 616 617 if !reflect.DeepEqual(gotSizes, tt.sizes) { 618 t.Fatalf("got=%v, want=%v", gotSizes, tt.sizes) 619 } 620 621 varr := arr.ListValues().(*array.Int32) 622 if got, want := varr.Int32Values(), vs; !reflect.DeepEqual(got, want) { 623 t.Fatalf("got=%v, want=%v", got, want) 624 } 625 626 if got, want := arr.String(), `[[0 1 2] (null) [] [3 4 5 6]]`; got != want { 627 t.Fatalf("got=%q, want=%q", got, want) 628 } 629 assert.Equal(t, "[0,1,2]", arr.ValueStr(0)) 630 631 sub := array.NewSlice(arr, 1, 4).(array.ListLike) 632 defer sub.Release() 633 634 if got, want := sub.String(), `[(null) [] [3 4 5 6]]`; got != want { 635 t.Fatalf("got=%q, want=%q", got, want) 636 } 637 }) 638 } 639 } 640 641 func TestVarLenListLikeStringRoundTrip(t *testing.T) { 642 // 1. create array 643 mem := memory.NewCheckedAllocator(memory.NewGoAllocator()) 644 defer mem.AssertSize(t, 0) 645 646 builders := []array.VarLenListLikeBuilder{ 647 array.NewListBuilder(mem, arrow.PrimitiveTypes.Int32), 648 array.NewListViewBuilder(mem, arrow.PrimitiveTypes.Int32), 649 array.NewLargeListBuilder(mem, arrow.PrimitiveTypes.Int32), 650 array.NewLargeListViewBuilder(mem, arrow.PrimitiveTypes.Int32), 651 } 652 653 builders1 := []array.VarLenListLikeBuilder{ 654 array.NewListBuilder(mem, arrow.PrimitiveTypes.Int32), 655 array.NewListViewBuilder(mem, arrow.PrimitiveTypes.Int32), 656 array.NewLargeListBuilder(mem, arrow.PrimitiveTypes.Int32), 657 array.NewLargeListViewBuilder(mem, arrow.PrimitiveTypes.Int32), 658 } 659 660 for i, b := range builders { 661 defer b.Release() 662 663 vb := b.ValueBuilder().(*array.Int32Builder) 664 665 var values = [][]int32{ 666 {0, 1, 2, 3, 4, 5, 6}, 667 {1, 2, 3, 4, 5, 6, 7}, 668 {2, 3, 4, 5, 6, 7, 8}, 669 {3, 4, 5, 6, 7, 8, 9}, 670 } 671 for _, value := range values { 672 b.AppendNull() 673 b.AppendWithSize(true, 2*len(value)) 674 for _, el := range value { 675 vb.Append(el) 676 vb.AppendNull() 677 } 678 b.AppendWithSize(false, 0) 679 } 680 681 arr := b.NewArray() 682 defer arr.Release() 683 684 // 2. create array via AppendValueFromString 685 b1 := builders1[i] 686 defer b1.Release() 687 688 for i := 0; i < arr.Len(); i++ { 689 assert.NoError(t, b1.AppendValueFromString(arr.ValueStr(i))) 690 } 691 692 arr1 := b1.NewArray() 693 defer arr1.Release() 694 695 assert.True(t, array.Equal(arr, arr1)) 696 } 697 } 698 699 // Test the string roun-trip for a list-view containing out-of-order offsets. 700 func TestListViewStringRoundTrip(t *testing.T) { 701 // 1. create array 702 mem := memory.NewCheckedAllocator(memory.NewGoAllocator()) 703 defer mem.AssertSize(t, 0) 704 705 builders := []array.VarLenListLikeBuilder{ 706 array.NewListViewBuilder(mem, arrow.PrimitiveTypes.Int32), 707 array.NewLargeListViewBuilder(mem, arrow.PrimitiveTypes.Int32), 708 } 709 710 builders1 := []array.VarLenListLikeBuilder{ 711 array.NewListViewBuilder(mem, arrow.PrimitiveTypes.Int32), 712 array.NewLargeListViewBuilder(mem, arrow.PrimitiveTypes.Int32), 713 } 714 715 for i, b := range builders { 716 defer b.Release() 717 718 switch lvb := b.(type) { 719 case *array.ListViewBuilder: 720 lvb.AppendDimensions(5, 3) 721 b.AppendNull() 722 lvb.AppendDimensions(0, 0) 723 lvb.AppendDimensions(1, 4) 724 case *array.LargeListViewBuilder: 725 lvb.AppendDimensions(5, 3) 726 b.AppendNull() 727 lvb.AppendDimensions(0, 0) 728 lvb.AppendDimensions(1, 4) 729 } 730 731 vb := b.ValueBuilder().(*array.Int32Builder) 732 733 vs := []int32{-1, 3, 4, 5, 6, 0, 1, 2} 734 isValid := []bool{false, true, true, true, true, true, true, true} 735 vb.Reserve(len(vs)) 736 vb.AppendValues(vs, isValid) 737 738 arr := b.NewArray() 739 defer arr.Release() 740 741 // 2. create array via AppendValueFromString 742 b1 := builders1[i] 743 defer b1.Release() 744 745 for i := 0; i < arr.Len(); i++ { 746 assert.NoError(t, b1.AppendValueFromString(arr.ValueStr(i))) 747 } 748 749 arr1 := b1.NewArray() 750 defer arr1.Release() 751 752 assert.True(t, array.Equal(arr, arr1)) 753 } 754 } 755 756 func TestRangeOfValuesUsed(t *testing.T) { 757 tests := []struct { 758 typeID arrow.Type 759 dt arrow.DataType 760 }{ 761 {arrow.LIST, arrow.ListOf(arrow.PrimitiveTypes.Int16)}, 762 {arrow.LARGE_LIST, arrow.LargeListOf(arrow.PrimitiveTypes.Int16)}, 763 {arrow.LIST_VIEW, arrow.ListViewOf(arrow.PrimitiveTypes.Int16)}, 764 {arrow.LARGE_LIST_VIEW, arrow.LargeListViewOf(arrow.PrimitiveTypes.Int16)}, 765 } 766 for _, tt := range tests { 767 t.Run(tt.typeID.String(), func(t *testing.T) { 768 pool := memory.NewCheckedAllocator(memory.NewGoAllocator()) 769 defer pool.AssertSize(t, 0) 770 771 isListView := tt.typeID == arrow.LIST_VIEW || tt.typeID == arrow.LARGE_LIST_VIEW 772 773 bldr := array.NewBuilder(pool, tt.dt).(array.VarLenListLikeBuilder) 774 defer bldr.Release() 775 776 var arr array.VarLenListLike 777 778 // Empty array 779 arr = bldr.NewArray().(array.VarLenListLike) 780 defer arr.Release() 781 offset, len := array.RangeOfValuesUsed(arr) 782 assert.Equal(t, 0, offset) 783 assert.Equal(t, 0, len) 784 785 // List-like array with only nulls 786 bldr.AppendNulls(3) 787 arr = bldr.NewArray().(array.VarLenListLike) 788 defer arr.Release() 789 offset, len = array.RangeOfValuesUsed(arr) 790 assert.Equal(t, 0, offset) 791 assert.Equal(t, 0, len) 792 793 // Array with nulls and non-nulls (starting at a non-zero offset) 794 vb := bldr.ValueBuilder().(*array.Int16Builder) 795 vb.Append(-2) 796 vb.Append(-1) 797 bldr.AppendWithSize(false, 0) 798 bldr.AppendWithSize(true, 2) 799 vb.Append(0) 800 vb.Append(1) 801 bldr.AppendWithSize(true, 3) 802 vb.Append(2) 803 vb.Append(3) 804 vb.Append(4) 805 if isListView { 806 vb.Append(10) 807 vb.Append(11) 808 } 809 arr = bldr.NewArray().(array.VarLenListLike) 810 defer arr.Release() 811 offset, len = array.RangeOfValuesUsed(arr) 812 assert.Equal(t, 2, offset) 813 assert.Equal(t, 5, len) 814 815 // Overlapping list-views 816 // [null, [0, 1, 2, 3, 4, 5], [1, 2], null, [4], null, null] 817 vb = bldr.ValueBuilder().(*array.Int16Builder) 818 vb.Append(-2) 819 vb.Append(-1) 820 bldr.AppendWithSize(false, 0) 821 if isListView { 822 bldr.AppendWithSize(true, 6) 823 vb.Append(0) 824 bldr.AppendWithSize(true, 2) 825 vb.Append(1) 826 vb.Append(2) 827 vb.Append(3) 828 bldr.AppendWithSize(false, 0) 829 bldr.AppendWithSize(true, 1) 830 vb.Append(4) 831 vb.Append(5) 832 // -- used range ends here -- 833 vb.Append(10) 834 vb.Append(11) 835 } else { 836 bldr.AppendWithSize(true, 6) 837 vb.Append(0) 838 vb.Append(1) 839 vb.Append(2) 840 vb.Append(3) 841 vb.Append(4) 842 vb.Append(5) 843 bldr.AppendWithSize(true, 2) 844 vb.Append(1) 845 vb.Append(2) 846 bldr.AppendWithSize(false, 0) 847 bldr.AppendWithSize(true, 1) 848 vb.Append(4) 849 } 850 bldr.AppendNulls(2) 851 arr = bldr.NewArray().(array.VarLenListLike) 852 defer arr.Release() 853 854 // Check the range 855 offset, len = array.RangeOfValuesUsed(arr) 856 assert.Equal(t, 2, offset) 857 if isListView { 858 assert.Equal(t, 6, len) 859 } else { 860 assert.Equal(t, 9, len) 861 } 862 }) 863 } 864 }