diff --git a/.github/workflows/cpp_extra.yml b/.github/workflows/cpp_extra.yml index 9a863d2a5ff..8b072ed90af 100644 --- a/.github/workflows/cpp_extra.yml +++ b/.github/workflows/cpp_extra.yml @@ -66,7 +66,6 @@ permissions: jobs: check-labels: - if: github.event_name == 'pull_request' uses: ./.github/workflows/check_labels.yml with: parent-workflow: cpp_extra @@ -80,6 +79,7 @@ jobs: steps: - id: set_enabled if: >- + github.ref_type == 'tag' || (github.event_name == 'schedule' && github.repository == 'apache/arrow') || contains(fromJSON(needs.check-labels.outputs.ci-extra-labels || '[]'), 'CI: Extra') || contains(fromJSON(needs.check-labels.outputs.ci-extra-labels || '[]'), 'CI: Extra: C++') diff --git a/.github/workflows/cuda_extra.yml b/.github/workflows/cuda_extra.yml index 64f2597fe89..f58ee86e6fa 100644 --- a/.github/workflows/cuda_extra.yml +++ b/.github/workflows/cuda_extra.yml @@ -49,7 +49,6 @@ permissions: jobs: check-labels: - if: github.event_name == 'pull_request' uses: ./.github/workflows/check_labels.yml with: parent-workflow: cuda_extra @@ -63,6 +62,7 @@ jobs: steps: - id: set_enabled if: >- + github.ref_type == 'tag' || (github.event_name == 'schedule' && github.repository == 'apache/arrow') || contains(fromJSON(needs.check-labels.outputs.ci-extra-labels || '[]'), 'CI: Extra') || contains(fromJSON(needs.check-labels.outputs.ci-extra-labels || '[]'), 'CI: Extra: CUDA') diff --git a/.github/workflows/package_linux.yml b/.github/workflows/package_linux.yml index b5afb7f36a0..b96627f49ff 100644 --- a/.github/workflows/package_linux.yml +++ b/.github/workflows/package_linux.yml @@ -58,7 +58,6 @@ permissions: jobs: check-labels: - if: github.event_name == 'pull_request' uses: ./.github/workflows/check_labels.yml with: parent-workflow: package_linux @@ -72,6 +71,7 @@ jobs: steps: - id: set_enabled if: >- + github.ref_type == 'tag' || (github.event_name == 'schedule' && github.repository == 'apache/arrow') || contains(fromJSON(needs.check-labels.outputs.ci-extra-labels || '[]'), 'CI: Extra') || contains(fromJSON(needs.check-labels.outputs.ci-extra-labels || '[]'), 'CI: Extra: Package: Linux') diff --git a/.github/workflows/r_extra.yml b/.github/workflows/r_extra.yml index 1ba7d2247ce..142464dabc7 100644 --- a/.github/workflows/r_extra.yml +++ b/.github/workflows/r_extra.yml @@ -61,7 +61,6 @@ permissions: jobs: check-labels: - if: github.event_name == 'pull_request' uses: ./.github/workflows/check_labels.yml with: parent-workflow: r_extra @@ -75,6 +74,7 @@ jobs: steps: - id: set_enabled if: >- + github.ref_type == 'tag' || (github.event_name == 'schedule' && github.repository == 'apache/arrow') || contains(fromJSON(needs.check-labels.outputs.ci-extra-labels || '[]'), 'CI: Extra') || contains(fromJSON(needs.check-labels.outputs.ci-extra-labels || '[]'), 'CI: Extra: R') diff --git a/ci/scripts/r_install_system_dependencies.sh b/ci/scripts/r_install_system_dependencies.sh index 237e0e9408b..042d6a5c9ad 100755 --- a/ci/scripts/r_install_system_dependencies.sh +++ b/ci/scripts/r_install_system_dependencies.sh @@ -38,10 +38,11 @@ fi # Install curl, OpenSSL, and libuv # - curl/OpenSSL: technically only needed for S3/GCS support, but # installing the R curl package fails without it +# - libpng: required by the png R package # - libuv: required by the fs R package (no longer bundles libuv by default) case "$PACKAGE_MANAGER" in apt-get) - apt-get install -y libcurl4-openssl-dev libssl-dev libuv1-dev + apt-get install -y libcurl4-openssl-dev libpng-dev libssl-dev libuv1-dev ;; apk) $PACKAGE_MANAGER add curl-dev openssl-dev libuv-dev diff --git a/cpp/src/arrow/compute/kernels/select_k_test.cc b/cpp/src/arrow/compute/kernels/select_k_test.cc index 67e5d214636..47e4af58001 100644 --- a/cpp/src/arrow/compute/kernels/select_k_test.cc +++ b/cpp/src/arrow/compute/kernels/select_k_test.cc @@ -276,6 +276,26 @@ TEST_F(TestSelectKWithArray, FullSelectKNull) { Check(uint8(), array_input, options, expected); } +TEST_F(TestSelectKWithArray, PartialSelectKAllNull) { + auto array_input = R"([null, null, null, null, null])"; + std::vector sort_keys{SortKey("a", SortOrder::Ascending)}; + auto options = SelectKOptions(4, sort_keys); + auto expected = R"([null, null, null, null])"; + Check(uint8(), array_input, options, expected); + options.sort_keys[0].null_placement = NullPlacement::AtStart; + Check(uint8(), array_input, options, expected); +} + +TEST_F(TestSelectKWithArray, FullSelectKAllNull) { + auto array_input = R"([null, null, null, null, null])"; + std::vector sort_keys{SortKey("a", SortOrder::Ascending)}; + auto options = SelectKOptions(10, sort_keys); + auto expected = R"([null, null, null, null, null])"; + Check(uint8(), array_input, options, expected); + options.sort_keys[0].null_placement = NullPlacement::AtStart; + Check(uint8(), array_input, options, expected); +} + TEST_F(TestSelectKWithArray, PartialSelectKNullNaN) { auto array_input = R"([null, 30, NaN, 20, 10, null])"; std::vector sort_keys{SortKey("a", SortOrder::Descending)}; @@ -293,9 +313,31 @@ TEST_F(TestSelectKWithArray, FullSelectKNullNaN) { options.sort_keys[0].null_placement = NullPlacement::AtStart; Check(float64(), array_input, options, "[null, null, NaN, 30, 20, 10]"); } + +TEST_F(TestSelectKWithArray, PartialSelectKAllNullAndNaN) { + auto array_input = R"([null, NaN, NaN, null, null])"; + std::vector sort_keys{SortKey("a", SortOrder::Ascending)}; + auto options = SelectKOptions(4, sort_keys); + auto expected = R"([NaN, NaN, null, null])"; + Check(float64(), array_input, options, expected); + options.sort_keys[0].null_placement = NullPlacement::AtStart; + expected = R"([null, null, null, NaN])"; + Check(float64(), array_input, options, expected); +} + +TEST_F(TestSelectKWithArray, FullSelectKAllNullAndNaN) { + auto array_input = R"([null, NaN, NaN, null, null])"; + std::vector sort_keys{SortKey("a", SortOrder::Ascending)}; + auto options = SelectKOptions(10, sort_keys); + auto expected = R"([NaN, NaN, null, null, null])"; + Check(float64(), array_input, options, expected); + options.sort_keys[0].null_placement = NullPlacement::AtStart; + expected = R"([null, null, null, NaN, NaN])"; + Check(float64(), array_input, options, expected); +} + // Test basic cases for chunked array -template struct TestSelectKWithChunkedArray : public ::testing::Test { TestSelectKWithChunkedArray() {} @@ -323,6 +365,15 @@ struct TestSelectKWithChunkedArray : public ::testing::Test { AssertSelectK(chunked_array, k); } + void Check(const std::shared_ptr& type, const std::vector& input, + const SelectKOptions& options, const std::string& expected) { + std::shared_ptr actual; + auto input_array = ChunkedArrayFromJSON(type, input); + auto expected_array = ChunkedArrayFromJSON(type, {expected}); + ASSERT_OK(this->DoSelectK(input_array, options, &actual)); + AssertChunkedEqual(*expected_array, *actual); + } + void Check(const std::shared_ptr& chunked_array, const SelectKOptions& options, const std::shared_ptr& expected_array) { @@ -343,9 +394,12 @@ struct TestSelectKWithChunkedArray : public ::testing::Test { } }; -TYPED_TEST_SUITE(TestSelectKWithChunkedArray, SelectKableTypes); +template +struct TestSelectKWithChunkedArrayTyped : public TestSelectKWithChunkedArray {}; + +TYPED_TEST_SUITE(TestSelectKWithChunkedArrayTyped, SelectKableTypes); -TYPED_TEST(TestSelectKWithChunkedArray, RandomValuesWithSlices) { +TYPED_TEST(TestSelectKWithChunkedArrayTyped, RandomValuesWithSlices) { Random rand(0x61549225); int length = 100; for (auto null_probability : {0.0, 0.1, 0.5, 1.0}) { @@ -361,62 +415,119 @@ TYPED_TEST(TestSelectKWithChunkedArray, RandomValuesWithSlices) { } } -TYPED_TEST(TestSelectKWithChunkedArray, PartialSelectKNull) { - auto chunked_array = ChunkedArrayFromJSON(uint8(), { - "[null, 1]", - "[3, null, 2]", - "[1]", - }); +TEST_F(TestSelectKWithChunkedArray, PartialSelectKNull) { + auto chunked_array = std::vector{ + "[null, 1]", + "[3, null, 2]", + "[1]", + }; std::vector sort_keys{SortKey("a", SortOrder::Ascending)}; auto options = SelectKOptions(3, sort_keys); - auto expected = ChunkedArrayFromJSON(uint8(), {"[1, 1, 2]"}); - this->Check(chunked_array, options, expected); + auto expected = "[1, 1, 2]"; + this->Check(uint8(), chunked_array, options, expected); options.sort_keys[0].null_placement = NullPlacement::AtStart; - expected = ChunkedArrayFromJSON(uint8(), {"[null, null, 1]"}); - this->Check(chunked_array, options, expected); + expected = "[null, null, 1]"; + this->Check(uint8(), chunked_array, options, expected); } -TYPED_TEST(TestSelectKWithChunkedArray, FullSelectKNull) { - auto chunked_array = ChunkedArrayFromJSON(uint8(), { - "[null, 1]", - "[3, null, 2]", - "[1]", - }); +TEST_F(TestSelectKWithChunkedArray, FullSelectKNull) { + auto chunked_array = std::vector{ + "[null, 1]", + "[3, null, 2]", + "[1]", + }; std::vector sort_keys{SortKey("a", SortOrder::Ascending)}; auto options = SelectKOptions(10, sort_keys); options.sort_keys[0].null_placement = NullPlacement::AtStart; - auto expected = ChunkedArrayFromJSON(uint8(), {"[null, null, 1, 1, 2, 3]"}); - this->Check(chunked_array, options, expected); + auto expected = "[null, null, 1, 1, 2, 3]"; + this->Check(uint8(), chunked_array, options, expected); options.sort_keys[0].null_placement = NullPlacement::AtEnd; - expected = ChunkedArrayFromJSON(uint8(), {"[1, 1, 2, 3, null, null]"}); - this->Check(chunked_array, options, expected); + expected = "[1, 1, 2, 3, null, null]"; + this->Check(uint8(), chunked_array, options, expected); } -TYPED_TEST(TestSelectKWithChunkedArray, PartialSelectKNullNaN) { - auto chunked_array = ChunkedArrayFromJSON( - float64(), {"[null, 1]", "[3, null, NaN]", "[10, NaN, 2]", "[1]"}); +TEST_F(TestSelectKWithChunkedArray, PartialSelectKAllNull) { + auto chunked_array = std::vector{ + "[null, null]", + "[null, null, null]", + "[null]", + }; + std::vector sort_keys{SortKey("a", SortOrder::Ascending)}; + auto options = SelectKOptions(3, sort_keys); + auto expected = "[null, null, null]"; + this->Check(uint8(), chunked_array, options, expected); + options.sort_keys[0].null_placement = NullPlacement::AtStart; + this->Check(uint8(), chunked_array, options, expected); +} + +TEST_F(TestSelectKWithChunkedArray, FullSelectKAllNull) { + auto chunked_array = std::vector{ + "[null, null]", + "[null, null, null]", + "[null]", + }; + std::vector sort_keys{SortKey("a", SortOrder::Ascending)}; + auto options = SelectKOptions(10, sort_keys); + auto expected = "[null, null, null, null, null, null]"; + this->Check(uint8(), chunked_array, options, expected); + options.sort_keys[0].null_placement = NullPlacement::AtStart; + this->Check(uint8(), chunked_array, options, expected); +} + +TEST_F(TestSelectKWithChunkedArray, PartialSelectKNullNaN) { + auto chunked_array = + std::vector{"[null, 1]", "[3, null, NaN]", "[10, NaN, 2]", "[1]"}; std::vector sort_keys{SortKey("a", SortOrder::Descending)}; auto options = SelectKOptions(3, sort_keys); options.sort_keys[0].null_placement = NullPlacement::AtStart; - auto expected = ChunkedArrayFromJSON(float64(), {"[null, null, NaN]"}); - this->Check(chunked_array, options, expected); + auto expected = "[null, null, NaN]"; + this->Check(float64(), chunked_array, options, expected); options.sort_keys[0].null_placement = NullPlacement::AtEnd; - expected = ChunkedArrayFromJSON(float64(), {"[10, 3, 2]"}); - this->Check(chunked_array, options, expected); + expected = "[10, 3, 2]"; + this->Check(float64(), chunked_array, options, expected); } -TYPED_TEST(TestSelectKWithChunkedArray, FullSelectKNullNaN) { - auto chunked_array = ChunkedArrayFromJSON( - float64(), {"[null, 1]", "[3, null, NaN]", "[10, NaN, 2]", "[1]"}); +TEST_F(TestSelectKWithChunkedArray, FullSelectKNullNaN) { + auto chunked_array = + std::vector{"[null, 1]", "[3, null, NaN]", "[10, NaN, 2]", "[1]"}; std::vector sort_keys{SortKey("a", SortOrder::Descending)}; auto options = SelectKOptions(10, sort_keys); options.sort_keys[0].null_placement = NullPlacement::AtStart; - auto expected = - ChunkedArrayFromJSON(float64(), {"[null, null, NaN, NaN, 10, 3, 2, 1, 1]"}); - this->Check(chunked_array, options, expected); + auto expected = "[null, null, NaN, NaN, 10, 3, 2, 1, 1]"; + this->Check(float64(), chunked_array, options, expected); options.sort_keys[0].null_placement = NullPlacement::AtEnd; - expected = ChunkedArrayFromJSON(float64(), {"[10, 3, 2, 1, 1, NaN, NaN, null, null]"}); - this->Check(chunked_array, options, expected); + expected = "[10, 3, 2, 1, 1, NaN, NaN, null, null]"; + this->Check(float64(), chunked_array, options, expected); +} + +TEST_F(TestSelectKWithChunkedArray, PartialSelectKAllNullAndNaN) { + auto chunked_array = std::vector{ + "[null, NaN]", + "[NaN, null, null]", + "[null]", + }; + std::vector sort_keys{SortKey("a", SortOrder::Ascending)}; + auto options = SelectKOptions(3, sort_keys); + auto expected = "[NaN, NaN, null]"; + this->Check(float64(), chunked_array, options, expected); + options.sort_keys[0].null_placement = NullPlacement::AtStart; + expected = "[null, null, null]"; + this->Check(float64(), chunked_array, options, expected); +} + +TEST_F(TestSelectKWithChunkedArray, FullSelectKAllNullAndNaN) { + auto chunked_array = std::vector{ + "[null, NaN]", + "[NaN, null, null]", + "[null]", + }; + std::vector sort_keys{SortKey("a", SortOrder::Ascending)}; + auto options = SelectKOptions(10, sort_keys); + auto expected = "[NaN, NaN, null, null, null, null]"; + this->Check(float64(), chunked_array, options, expected); + options.sort_keys[0].null_placement = NullPlacement::AtStart; + expected = "[null, null, null, null, NaN, NaN]"; + this->Check(float64(), chunked_array, options, expected); } template @@ -790,6 +901,39 @@ TEST_F(TestSelectKWithRecordBatch, PartialSelectKNullNaN) { Check(schema, batch_input, options, expected); } +TEST_F(TestSelectKWithRecordBatch, PartialSelectKAllNullNaN) { + auto schema = ::arrow::schema({ + {field("a", float32())}, + {field("b", float64())}, + }); + auto batch_input = R"([ + {"a": null, "b": null}, + {"a": null, "b": null}, + {"a": NaN, "b": null}, + {"a": null, "b": NaN}, + {"a": NaN, "b": NaN}, + {"a": null, "b": NaN} + ])"; + std::vector sort_keys{ + SortKey("a", SortOrder::Ascending, NullPlacement::AtStart), + SortKey("b", SortOrder::Descending)}; + auto options = SelectKOptions(3, sort_keys); + auto expected = R"([{"a": null, "b": NaN}, + {"a": null, "b": NaN}, + {"a": null, "b": null}])"; + Check(schema, batch_input, options, expected); + options.sort_keys[1].null_placement = NullPlacement::AtStart; + expected = R"([{"a": null, "b": null}, + {"a": null, "b": null}, + {"a": null, "b": NaN}])"; + Check(schema, batch_input, options, expected); + options.sort_keys[0].null_placement = NullPlacement::AtEnd; + expected = R"([{"a": NaN, "b": null}, + {"a": NaN, "b": NaN}, + {"a": null, "b": null}])"; + Check(schema, batch_input, options, expected); +} + TEST_F(TestSelectKWithRecordBatch, FullSelectKNullNaN) { auto schema = ::arrow::schema({ {field("a", float32())}, @@ -834,6 +978,51 @@ TEST_F(TestSelectKWithRecordBatch, FullSelectKNullNaN) { Check(schema, batch_input, options, expected); } +TEST_F(TestSelectKWithRecordBatch, FullSelectKAllNullNaN) { + auto schema = ::arrow::schema({ + {field("a", float32())}, + {field("b", float64())}, + }); + auto batch_input = R"([ + {"a": null, "b": null}, + {"a": null, "b": null}, + {"a": NaN, "b": null}, + {"a": null, "b": NaN}, + {"a": NaN, "b": NaN}, + {"a": null, "b": NaN} + ])"; + std::vector sort_keys{ + SortKey("a", SortOrder::Ascending, NullPlacement::AtStart), + SortKey("b", SortOrder::Descending)}; + auto options = SelectKOptions(10, sort_keys); + auto expected = R"([{"a": null, "b": NaN}, + {"a": null, "b": NaN}, + {"a": null, "b": null}, + {"a": null, "b": null}, + {"a": NaN, "b": NaN}, + {"a": NaN, "b": null} + ])"; + Check(schema, batch_input, options, expected); + options.sort_keys[1].null_placement = NullPlacement::AtStart; + expected = R"([{"a": null, "b": null}, + {"a": null, "b": null}, + {"a": null, "b": NaN}, + {"a": null, "b": NaN}, + {"a": NaN, "b": null}, + {"a": NaN, "b": NaN} + ])"; + Check(schema, batch_input, options, expected); + options.sort_keys[0].null_placement = NullPlacement::AtEnd; + expected = R"([{"a": NaN, "b": null}, + {"a": NaN, "b": NaN}, + {"a": null, "b": null}, + {"a": null, "b": null}, + {"a": null, "b": NaN}, + {"a": null, "b": NaN} + ])"; + Check(schema, batch_input, options, expected); +} + TEST_F(TestSelectKWithRecordBatch, BottomKOneColumnKey) { auto schema = ::arrow::schema({ {field("country", utf8())}, @@ -1147,26 +1336,26 @@ TEST_F(TestSelectKWithTable, FullSelectKNullNaN) { {"a": 1, "b": 3}, {"a": 3, "b": null}, {"a": 6, "b": NaN}, - {"a": 6, "b": null}, + {"a": 6, "b": null}, {"a": NaN, "b": 5}, - {"a": null, "b": 5}, + {"a": null, "b": 5}, {"a": null, "b": null}])"}; Check(schema, input, options, expected); options.sort_keys[0].null_placement = NullPlacement::AtStart; expected = {R"([ - {"a": null, "b": 5}, + {"a": null, "b": 5}, {"a": null, "b": null}, {"a": NaN, "b": 5}, {"a": 1, "b": 5}, {"a": 1, "b": 3}, {"a": 3, "b": null}, {"a": 6, "b": NaN}, - {"a": 6, "b": null} + {"a": 6, "b": null} ])"}; Check(schema, input, options, expected); options.sort_keys[1].null_placement = NullPlacement::AtStart; expected = {R"([ - {"a": null, "b": null}, + {"a": null, "b": null}, {"a": null, "b": 5}, {"a": NaN, "b": 5}, {"a": 1, "b": 5}, @@ -1178,5 +1367,96 @@ TEST_F(TestSelectKWithTable, FullSelectKNullNaN) { Check(schema, input, options, expected); } +TEST_F(TestSelectKWithTable, PartialSelectKAllNullNaN) { + auto schema = ::arrow::schema({ + {field("a", float32())}, + {field("b", float64())}, + }); + std::vector input = { + R"([{"a": null, "b": null}, + {"a": NaN, "b": null}, + {"a": null, "b": NaN} + ])", + R"([{"a": null, "b": null}, + {"a": NaN, "b": null}, + {"a": NaN, "b": NaN} + ])"}; + + std::vector sort_keys{SortKey("a", SortOrder::Ascending), + SortKey("b", SortOrder::Descending)}; + auto options = SelectKOptions(3, sort_keys); + + std::vector expected = { + R"([{"a": NaN, "b": NaN}, + {"a": NaN, "b": null}, + {"a": NaN, "b": null} + ])"}; + Check(schema, input, options, expected); + options.sort_keys[0].null_placement = NullPlacement::AtStart; + expected = { + R"([{"a": null, "b": NaN}, + {"a": null, "b": null}, + {"a": null, "b": null} + ])"}; + Check(schema, input, options, expected); + options.sort_keys[1].null_placement = NullPlacement::AtStart; + expected = { + R"([{"a": null, "b": null}, + {"a": null, "b": null}, + {"a": null, "b": NaN} + ])"}; + Check(schema, input, options, expected); +} + +TEST_F(TestSelectKWithTable, FullSelectKAllNullNaN) { + auto schema = ::arrow::schema({ + {field("a", float32())}, + {field("b", float64())}, + }); + std::vector input = { + R"([{"a": null, "b": null}, + {"a": NaN, "b": null}, + {"a": null, "b": NaN} + ])", + R"([{"a": null, "b": null}, + {"a": NaN, "b": null}, + {"a": NaN, "b": NaN} + ])"}; + + std::vector sort_keys{SortKey("a", SortOrder::Ascending), + SortKey("b", SortOrder::Descending)}; + auto options = SelectKOptions(10, sort_keys); + + std::vector expected = { + R"([{"a": NaN, "b": NaN}, + {"a": NaN, "b": null}, + {"a": NaN, "b": null}, + {"a": null, "b": NaN}, + {"a": null, "b": null}, + {"a": null, "b": null} + ])"}; + Check(schema, input, options, expected); + options.sort_keys[0].null_placement = NullPlacement::AtStart; + expected = { + R"([{"a": null, "b": NaN}, + {"a": null, "b": null}, + {"a": null, "b": null}, + {"a": NaN, "b": NaN}, + {"a": NaN, "b": null}, + {"a": NaN, "b": null} + ])"}; + Check(schema, input, options, expected); + options.sort_keys[1].null_placement = NullPlacement::AtStart; + expected = { + R"([{"a": null, "b": null}, + {"a": null, "b": null}, + {"a": null, "b": NaN}, + {"a": NaN, "b": null}, + {"a": NaN, "b": null}, + {"a": NaN, "b": NaN} + ])"}; + Check(schema, input, options, expected); +} + } // namespace compute } // namespace arrow diff --git a/cpp/src/arrow/compute/kernels/vector_select_k.cc b/cpp/src/arrow/compute/kernels/vector_select_k.cc index cc375919658..ea072d179ee 100644 --- a/cpp/src/arrow/compute/kernels/vector_select_k.cc +++ b/cpp/src/arrow/compute/kernels/vector_select_k.cc @@ -17,7 +17,6 @@ #include #include -#include #include #include "arrow/compute/function.h" @@ -118,22 +117,22 @@ void HeapSortNonNullsToOutput(std::span non_null_input_range, Comparat return; } std::span heap = non_null_input_range.subspan(0, output_range.size()); - std::ranges::make_heap(heap, cmp); + std::make_heap(heap.begin(), heap.end(), cmp); std::span remaining_input = non_null_input_range.subspan(output_range.size()); for (uint64_t x_index : remaining_input) { if (cmp(x_index, heap.front())) { - std::ranges::pop_heap(heap, cmp); + std::pop_heap(heap.begin(), heap.end(), cmp); heap.back() = x_index; - std::ranges::push_heap(heap, cmp); + std::push_heap(heap.begin(), heap.end(), cmp); } } // fill output in reverse when destructing, // as the "worst" (next-to-would-have-been-replaced) element is at heap-top - for (auto& reverse_out_iter : std::ranges::reverse_view(output_range)) { - reverse_out_iter = heap.front(); // heap-top has the next element - std::ranges::pop_heap(heap, cmp); + for (int64_t i = output_range.size(); i > 0; --i) { + output_range[i - 1] = heap.front(); // heap-top has the next element + std::pop_heap(heap.begin(), heap.end(), cmp); // Decrease heap-size by one heap = heap.first(heap.size() - 1); } @@ -422,9 +421,8 @@ class ChunkedArraySelector : public TypeVisitor { // so the heap must have been completely filled DCHECK_EQ(heap.size(), output.non_null_like_range.size()); - for (uint64_t& reverse_out_iter : - std::ranges::reverse_view(output.non_null_like_range)) { - reverse_out_iter = + for (int64_t i = output.non_null_like_range.size(); i > 0; --i) { + output.non_null_like_range[i - 1] = heap.top().index + heap.top().offset; // heap-top has the next element heap.pop(); } diff --git a/cpp/src/arrow/util/rle_encoding_internal.h b/cpp/src/arrow/util/rle_encoding_internal.h index 825cd253df9..5dc94f368d3 100644 --- a/cpp/src/arrow/util/rle_encoding_internal.h +++ b/cpp/src/arrow/util/rle_encoding_internal.h @@ -811,7 +811,8 @@ auto RleBitPackedDecoder::GetBatch(value_type* out, } parser_.ParseWithCallable([&](auto run) { - using RunDecoder = RleBitPackedDecoderGetRunDecoder::type; + using RunDecoder = + typename RleBitPackedDecoderGetRunDecoder::type; ARROW_DCHECK_LT(values_read, batch_size); RunDecoder decoder(run, value_bit_width_); @@ -1124,7 +1125,8 @@ auto RleBitPackedDecoder::GetSpaced(Converter converter, } parser_.ParseWithCallable([&](auto run) { - using RunDecoder = RleBitPackedDecoderGetRunDecoder::type; + using RunDecoder = + typename RleBitPackedDecoderGetRunDecoder::type; RunDecoder decoder(run, value_bit_width_); @@ -1306,7 +1308,8 @@ auto RleBitPackedDecoder::GetBatchWithDict(const V* dictionary, } parser_.ParseWithCallable([&](auto run) { - using RunDecoder = RleBitPackedDecoderGetRunDecoder::type; + using RunDecoder = + typename RleBitPackedDecoderGetRunDecoder::type; RunDecoder decoder(run, value_bit_width_); diff --git a/dev/archery/archery/crossbow/cli.py b/dev/archery/archery/crossbow/cli.py index 35e0d4d2c02..56c319fe7ef 100644 --- a/dev/archery/archery/crossbow/cli.py +++ b/dev/archery/archery/crossbow/cli.py @@ -208,7 +208,7 @@ def verify_release_candidate(obj, base_branch, create_pr, for flag, group in zip(verify_flags, verify_groups): if flag: job_groups += f" --group {group}" - response.create_comment( + response.create_issue_comment( f"{command} {job_groups} --param " + f"release={version} --param rc={rc}") @@ -300,6 +300,10 @@ def asset_callback(task_name, task, asset): @crossbow.command() +@click.option('--base-branch', default='main', + help='Set base branch for the PR.') +@click.option('--head-branch', default=None, + help='Set head branch for the PR.') @click.option('--arrow-remote', '-r', default=None, help='Set GitHub remote explicitly, which is going to be cloned ' 'on the CI services. Note, that no validation happens ' @@ -313,7 +317,8 @@ def asset_callback(task_name, task, asset): @click.option('--pr-title', required=True, help='Track the job submitted on PR with given title') @click.pass_obj -def report_pr(obj, arrow_remote, crossbow, fetch, job_name, pr_title): +def report_pr(obj, base_branch, head_branch, arrow_remote, crossbow, + fetch, job_name, pr_title): arrow = obj['arrow'] queue = obj['queue'] if fetch: @@ -322,11 +327,12 @@ def report_pr(obj, arrow_remote, crossbow, fetch, job_name, pr_title): report = CommentReport(job, crossbow_repo=crossbow) target_arrow = Repo(path=arrow.path, remote_url=arrow_remote) - pull_request = target_arrow.github_pr(title=pr_title, + pull_request = target_arrow.github_pr(base=base_branch, head=head_branch, + title=pr_title, github_token=queue.github_token, create=False) # render the response comment's content on the PR - pull_request.create_comment(report.show()) + pull_request.create_issue_comment(report.show()) click.echo(f'Job is tracked on PR {pull_request.html_url}') diff --git a/dev/release/03-binary-submit.sh b/dev/release/03-binary-submit.sh index e3a0fc4ee7a..acd0af5be49 100755 --- a/dev/release/03-binary-submit.sh +++ b/dev/release/03-binary-submit.sh @@ -34,6 +34,7 @@ version_with_rc="${version}-rc${rc}" crossbow_job_prefix="release-${version_with_rc}" release_tag="apache-arrow-${version}-rc${rc}" rc_branch="release-${version_with_rc}" +maint_branch="maint-${version}" : ${ARROW_REPOSITORY:="apache/arrow"} : ${ARROW_BRANCH:=${release_tag}} @@ -57,5 +58,7 @@ job_name=$(archery crossbow latest-prefix --no-fetch ${crossbow_job_prefix}) archery crossbow report-pr \ --no-fetch \ --arrow-remote "https://github.com/${ARROW_REPOSITORY}" \ + --base-branch ${maint_branch} \ + --head-branch ${rc_branch} \ --job-name ${job_name} \ --pr-title "WIP: [Release] Verify ${rc_branch}"