@@ -3616,6 +3616,135 @@ static void CheckListToList(const std::vector<std::shared_ptr<DataType>>& value_
36163616 }
36173617}
36183618
3619+ TEST (Cast, ListViewToList) {
3620+ // Views may be out of order or overlapping, so the referenced values have to
3621+ // be gathered rather than reinterpreted (GH-51612).
3622+ auto values = ArrayFromJSON (int32 (), " [1, 2, 3, 4]" );
3623+
3624+ // Out of order and overlapping views.
3625+ auto offsets = ArrayFromJSON (int32 (), " [2, 0, 1]" );
3626+ auto sizes = ArrayFromJSON (int32 (), " [2, 2, 1]" );
3627+ ASSERT_OK_AND_ASSIGN (auto list_view,
3628+ ListViewArray::FromArrays (*offsets, *sizes, *values));
3629+ CheckCast (list_view, ArrayFromJSON (list (int32 ()), " [[3, 4], [1, 2], [2]]" ));
3630+ // Same offset width, larger offset width, and a child type change.
3631+ CheckCast (list_view, ArrayFromJSON (large_list (int32 ()), " [[3, 4], [1, 2], [2]]" ));
3632+ CheckCast (list_view, ArrayFromJSON (list (int64 ()), " [[3, 4], [1, 2], [2]]" ));
3633+ CheckCast (list_view, ArrayFromJSON (large_list (float32 ()), " [[3, 4], [1, 2], [2]]" ));
3634+
3635+ // The large_list_view source, narrowing as well as widening the offset width.
3636+ ASSERT_OK_AND_ASSIGN (
3637+ auto large_list_view,
3638+ LargeListViewArray::FromArrays (*ArrayFromJSON (int64 (), " [2, 0, 1]" ),
3639+ *ArrayFromJSON (int64 (), " [2, 2, 1]" ), *values));
3640+ CheckCast (large_list_view, ArrayFromJSON (large_list (int32 ()), " [[3, 4], [1, 2], [2]]" ));
3641+ CheckCast (large_list_view, ArrayFromJSON (list (int32 ()), " [[3, 4], [1, 2], [2]]" ));
3642+
3643+ // Views that happen to be contiguous, i.e. what a list array would look like.
3644+ ASSERT_OK_AND_ASSIGN (list_view, ListViewArray::FromArrays (
3645+ *ArrayFromJSON (int32 (), " [0, 2, 4]" ),
3646+ *ArrayFromJSON (int32 (), " [2, 2, 0]" ), *values));
3647+ CheckCast (list_view, ArrayFromJSON (list (int32 ()), " [[1, 2], [3, 4], []]" ));
3648+
3649+ // Nulls.
3650+ {
3651+ auto list_view_w_nulls = MaskArrayWithNullsAt (list_view, {0 });
3652+ CheckCast (list_view_w_nulls, ArrayFromJSON (list (int32 ()), " [null, [3, 4], []]" ));
3653+ }
3654+ {
3655+ // A null view contributes no values, whatever size it declares.
3656+ ASSERT_OK_AND_ASSIGN (auto lv, ListViewArray::FromArrays (
3657+ *ArrayFromJSON (int32 (), " [0, 2, 2]" ),
3658+ *ArrayFromJSON (int32 (), " [2, 2, 2]" ), *values));
3659+ CheckCast (MaskArrayWithNullsAt (lv, {2 }),
3660+ ArrayFromJSON (list (int32 ()), " [[1, 2], [3, 4], null]" ));
3661+ }
3662+
3663+ // Sliced list-view.
3664+ {
3665+ ASSERT_OK_AND_ASSIGN (
3666+ auto lv, ListViewArray::FromArrays (*ArrayFromJSON (int32 (), " [0, 2, 0, 1, 2, 0]" ),
3667+ *ArrayFromJSON (int32 (), " [2, 2, 2, 0, 2, 2]" ),
3668+ *values));
3669+ CheckCast (lv->Slice (2 , 3 ), ArrayFromJSON (list (int32 ()), " [[1, 2], [], [3, 4]]" ));
3670+ CheckCast (lv->Slice (1 , 4 ),
3671+ ArrayFromJSON (large_list (int32 ()), " [[3, 4], [1, 2], [], [3, 4]]" ));
3672+ }
3673+
3674+ // Options pass through to the child cast.
3675+ {
3676+ ASSERT_OK_AND_ASSIGN (
3677+ auto lv, ListViewArray::FromArrays (
3678+ *ArrayFromJSON (int32 (), " [0, 2]" ), *ArrayFromJSON (int32 (), " [2, 2]" ),
3679+ *ArrayFromJSON (int64 (), " [87654321, 0, 0, 0]" )));
3680+ auto options = CastOptions::Safe (list (int16 ()));
3681+ CheckCastFails (lv, options);
3682+ options.allow_int_overflow = true ;
3683+ CheckCast (lv, ArrayFromJSON (list (int16 ()), " [[32689, 0], [0, 0]]" ), options);
3684+ }
3685+ }
3686+
3687+ TEST (Cast, ListViewToListEdgeCases) {
3688+ auto values = ArrayFromJSON (int32 (), " [1, 2, 3, 4]" );
3689+
3690+ auto make = [](const char * offsets, const char * sizes,
3691+ const std::shared_ptr<Array>& values) {
3692+ return ListViewArray::FromArrays (*ArrayFromJSON (int32 (), offsets),
3693+ *ArrayFromJSON (int32 (), sizes), *values);
3694+ };
3695+
3696+ // Zero-length list-view.
3697+ CheckCast (ArrayFromJSON (list_view (int32 ()), " []" ), ArrayFromJSON (list (int32 ()), " []" ));
3698+ CheckCast (ArrayFromJSON (large_list_view (int32 ()), " []" ),
3699+ ArrayFromJSON (large_list (int32 ()), " []" ));
3700+
3701+ // All views null, several with a non-zero declared size: no value is gathered.
3702+ {
3703+ ASSERT_OK_AND_ASSIGN (auto lv, make (" [0, 2, 4]" , " [2, 2, 2]" , values));
3704+ CheckCast (MaskArrayWithNullsAt (lv, {0 , 1 , 2 }),
3705+ ArrayFromJSON (list (int32 ()), " [null, null, null]" ));
3706+ }
3707+
3708+ // Out-of-order/overlapping views combined with nulls.
3709+ {
3710+ ASSERT_OK_AND_ASSIGN (auto lv, make (" [2, 0, 1]" , " [2, 2, 1]" , values));
3711+ CheckCast (MaskArrayWithNullsAt (lv, {1 }),
3712+ ArrayFromJSON (list (int32 ()), " [[3, 4], null, [2]]" ));
3713+ }
3714+
3715+ // A view of size zero interleaved with out-of-order views.
3716+ {
3717+ ASSERT_OK_AND_ASSIGN (auto lv, make (" [1, 3, 0, 2]" , " [0, 1, 4, 2]" , values));
3718+ CheckCast (lv, ArrayFromJSON (list (int32 ()), " [[], [4], [1, 2, 3, 4], [3, 4]]" ));
3719+ }
3720+
3721+ // The list-view's child array is itself sliced, i.e. has a non-zero offset.
3722+ {
3723+ auto sliced_values = ArrayFromJSON (int32 (), " [9, 1, 2, 3, 4, 9]" )->Slice (1 , 4 );
3724+ ASSERT_OK_AND_ASSIGN (auto lv, make (" [2, 0, 1]" , " [2, 2, 1]" , sliced_values));
3725+ CheckCast (lv, ArrayFromJSON (list (int32 ()), " [[3, 4], [1, 2], [2]]" ));
3726+ }
3727+
3728+ // Nested list-view, exercising the gather on a non-primitive child.
3729+ {
3730+ auto nested_values =
3731+ ArrayFromJSON (list (int32 ()), " [[10], [20, 21], [30, 31, 32], [40]]" );
3732+ ASSERT_OK_AND_ASSIGN (auto lv, make (" [1, 0, 2]" , " [1, 2, 2]" , nested_values));
3733+ CheckCast (lv, ArrayFromJSON (large_list (list (int64 ())),
3734+ " [[[20, 21]], [[10], [20, 21]], [[30, 31, 32], [40]]]" ));
3735+ }
3736+
3737+ // A sliced list-view whose validity bitmap bit offset is non-zero.
3738+ {
3739+ auto lv = ArrayFromJSON (list_view (int32 ()),
3740+ " [[1, 2], [3], null, [], [4], [5, 6], null, [7], [8, 9]]" );
3741+ CheckCast (lv->Slice (1 , 7 ),
3742+ ArrayFromJSON (list (int32 ()), " [[3], null, [], [4], [5, 6], null, [7]]" ));
3743+ CheckCast (lv->Slice (1 , 7 ), ArrayFromJSON (large_list (int64 ()),
3744+ " [[3], null, [], [4], [5, 6], null, [7]]" ));
3745+ }
3746+ }
3747+
36193748TEST (Cast, ListToList) {
36203749 CheckListToList ({int32 (), float32 (), int64 ()},
36213750 " [[0], [1], null, [2, 3, 4], [5, 6], null, [], [7], [8, 9]]" );
0 commit comments