diff --git a/cpp/src/lists/explode.cu b/cpp/src/lists/explode.cu index 2b495deb47f..5f6f1c308ac 100644 --- a/cpp/src/lists/explode.cu +++ b/cpp/src/lists/explode.cu @@ -62,22 +62,27 @@ std::unique_ptr build_table( std::vector> columns = gathered_table.release()->release(); - columns.insert(columns.begin() + explode_column_idx, - explode_col_gather_map - ? std::move(detail::gather(table_view({sliced_child}), - explode_col_gather_map->begin(), - explode_col_gather_map->end(), - cudf::out_of_bounds_policy::NULLIFY, - stream, - mr) - ->release()[0]) - : std::make_unique(sliced_child, stream, mr)); + auto inserted = columns.insert(columns.begin() + explode_column_idx, + explode_col_gather_map + ? std::move(detail::gather(table_view({sliced_child}), + explode_col_gather_map->begin(), + explode_col_gather_map->end(), + cudf::out_of_bounds_policy::NULLIFY, + stream, + mr) + ->release()[0]) + : std::make_unique(sliced_child, stream, mr)); if (position_array) { size_type position_size = position_array->size(); + // the null mask for position matches the exploded column's gather map, so copy it over + rmm::device_buffer nullmask = + explode_col_gather_map ? copy_bitmask(*inserted->get()) : rmm::device_buffer(0, stream); columns.insert(columns.begin() + explode_column_idx, - std::make_unique( - data_type(type_to_id()), position_size, position_array->release())); + std::make_unique(data_type(type_to_id()), + position_size, + position_array->release(), + std::move(nullmask))); } return std::make_unique
(std::move(columns)); diff --git a/cpp/tests/lists/explode_tests.cpp b/cpp/tests/lists/explode_tests.cpp index 4c7ded0efd7..ded3d2b9193 100644 --- a/cpp/tests/lists/explode_tests.cpp +++ b/cpp/tests/lists/explode_tests.cpp @@ -530,7 +530,7 @@ TEST_F(ExplodeOuterTest, SingleNull) auto ret = cudf::explode_outer(t, 0); CUDF_TEST_EXPECT_TABLES_EQUAL(ret->view(), expected); - FCW expected_pos_col{0, 0, 1, 0, 0, 1}; + FCW expected_pos_col{{0, 0, 1, 0, 0, 1}, {0, 1, 1, 0, 1, 1}}; cudf::table_view pos_expected({expected_pos_col, expected_a, expected_b}); auto pos_ret = cudf::explode_outer_position(t, 0); @@ -561,7 +561,7 @@ TEST_F(ExplodeOuterTest, Nulls) auto ret = cudf::explode_outer(t, 0); CUDF_TEST_EXPECT_TABLES_EQUAL(ret->view(), expected); - FCW expected_pos_col{0, 1, 2, 0, 0, 1}; + FCW expected_pos_col{{0, 1, 2, 0, 0, 1}, {1, 1, 1, 0, 1, 1}}; cudf::table_view pos_expected({expected_pos_col, expected_a, expected_b}); auto pos_ret = cudf::explode_outer_position(t, 0); @@ -591,7 +591,7 @@ TEST_F(ExplodeOuterTest, AllNulls) auto ret = cudf::explode_outer(t, 0); CUDF_TEST_EXPECT_TABLES_EQUAL(ret->view(), expected); - FCW expected_pos_col{0, 0, 0}; + FCW expected_pos_col{{0, 0, 0}, {0, 0, 0}}; cudf::table_view pos_expected({expected_pos_col, expected_a, expected_b}); auto pos_ret = cudf::explode_outer_position(t, 0); @@ -624,7 +624,7 @@ TEST_F(ExplodeOuterTest, SequentialNulls) auto ret = cudf::explode_outer(t, 0); CUDF_TEST_EXPECT_TABLES_EQUAL(ret->view(), expected); - FCW expected_pos_col{0, 1, 2, 0, 1, 0, 0, 0, 1, 2}; + FCW expected_pos_col{{0, 1, 2, 0, 1, 0, 0, 0, 1, 2}, {1, 1, 0, 1, 1, 0, 0, 1, 1, 1}}; cudf::table_view pos_expected({expected_pos_col, expected_a, expected_b}); auto pos_ret = cudf::explode_outer_position(t, 0); @@ -655,7 +655,7 @@ TEST_F(ExplodeOuterTest, MoreEmptyThanData) auto ret = cudf::explode_outer(t, 0); CUDF_TEST_EXPECT_TABLES_EQUAL(ret->view(), expected); - FCW expected_pos_col{0, 1, 0, 0, 0, 0, 0}; + FCW expected_pos_col{{0, 1, 0, 0, 0, 0, 0}, {1, 1, 0, 0, 0, 0, 1}}; cudf::table_view pos_expected({expected_pos_col, expected_a, expected_b}); auto pos_ret = cudf::explode_outer_position(t, 0); @@ -685,7 +685,7 @@ TEST_F(ExplodeOuterTest, TrailingEmptys) auto ret = cudf::explode_outer(t, 0); CUDF_TEST_EXPECT_TABLES_EQUAL(ret->view(), expected); - FCW expected_pos_col{0, 1, 0, 0, 0, 0}; + FCW expected_pos_col{{0, 1, 0, 0, 0, 0}, {1, 1, 0, 0, 0, 0}}; cudf::table_view pos_expected({expected_pos_col, expected_a, expected_b}); auto pos_ret = cudf::explode_outer_position(t, 0); @@ -718,7 +718,7 @@ TEST_F(ExplodeOuterTest, LeadingNulls) auto ret = cudf::explode_outer(t, 0); CUDF_TEST_EXPECT_TABLES_EQUAL(ret->view(), expected); - FCW expected_pos_col{0, 0, 0, 0, 0, 1}; + FCW expected_pos_col{{0, 0, 0, 0, 0, 1}, {0, 0, 0, 0, 1, 1}}; cudf::table_view pos_expected({expected_pos_col, expected_a, expected_b}); auto pos_ret = cudf::explode_outer_position(t, 0); @@ -753,7 +753,7 @@ TEST_F(ExplodeOuterTest, NullsInList) CUDF_TEST_EXPECT_TABLES_EQUAL(ret->view(), expected); - FCW expected_pos_col{0, 1, 2, 0, 1, 2, 3, 0, 0, 1, 2}; + FCW expected_pos_col{{0, 1, 2, 0, 1, 2, 3, 0, 0, 1, 2}, {1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1}}; cudf::table_view pos_expected({expected_pos_col, expected_a, expected_b}); auto pos_ret = cudf::explode_outer_position(t, 0); @@ -813,7 +813,7 @@ TEST_F(ExplodeOuterTest, NestedNulls) auto ret = cudf::explode_outer(t, 0); CUDF_TEST_EXPECT_TABLES_EQUAL(ret->view(), expected); - FCW expected_pos_col{0, 1, 0, 0, 1, 2}; + FCW expected_pos_col{{0, 1, 0, 0, 1, 2}, {1, 1, 0, 1, 1, 1}}; cudf::table_view pos_expected({expected_pos_col, expected_a, expected_b}); auto pos_ret = cudf::explode_outer_position(t, 0); @@ -884,7 +884,8 @@ TEST_F(ExplodeOuterTest, NullsInNestedDoubleExplode) CUDF_TEST_EXPECT_TABLES_EQUAL(ret->view(), expected); - FCW expected_pos_col{0, 1, 0, 0, 1, 2, 0, 1, 0, 1, 0, 0, 1}; + FCW expected_pos_col{{0, 1, 0, 0, 1, 2, 0, 1, 0, 1, 0, 0, 1}, + {1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0}}; cudf::table_view pos_expected({expected_pos_col, expected_a, expected_b}); auto pos_ret = cudf::explode_outer_position(first_explode_ret->view(), 0);