sparrow 2.5.0
C++20 idiomatic APIs for the Apache Arrow Columnar Format
Loading...
Searching...
No Matches
map_array.hpp
Go to the documentation of this file.
1// Copyright 2024 Man Group Operations Limited
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#pragma once
16
17#include <span>
18
19#include "sparrow/array_api.hpp"
27
28namespace sparrow
29{
30 class map_array;
31
32 template <>
44
45 template <class T>
46 constexpr bool is_map_array_v = std::same_as<T, map_array>;
47
48 namespace detail
49 {
50 template <>
52 {
53 [[nodiscard]] static constexpr sparrow::data_type get()
54 {
56 }
57 };
58 }
59
89 class map_array final : public mutable_array_bitmap_base<map_array>
90 {
91 public:
92
96 using value_iterator = inner_types::value_iterator;
97 using const_value_iterator = inner_types::const_value_iterator;
99 using offset_type = const std::int32_t;
101 using offset_span_type = std::span<const std::int32_t>;
102
105
107
108 using inner_value_type = inner_types::inner_value_type;
109 using inner_reference = inner_types::inner_reference;
110 using inner_const_reference = inner_types::inner_const_reference;
111
115 using iterator = typename base_type::iterator;
116 using const_iterator = typename base_type::const_iterator;
117
118 using base_type::insert;
119 using base_type::push_back;
120 using base_type::resize;
121
136
152 template <class... Args>
154 explicit map_array(Args&&... args)
155 : self_type(create_proxy(std::forward<Args>(args)...))
156 {
157 }
158
169
182
183 map_array(map_array&&) noexcept = default;
184 map_array& operator=(map_array&&) noexcept = default;
185
193 [[nodiscard]] SPARROW_API const array_wrapper* raw_keys_array() const;
194
203
211 [[nodiscard]] SPARROW_API const array_wrapper* raw_items_array() const;
212
221
239 template <std::ranges::range SIZES_RANGE>
240 [[nodiscard]] static auto offset_from_sizes(SIZES_RANGE&& sizes) -> offset_buffer_type;
241
242 private:
243
251 [[nodiscard]] SPARROW_API value_iterator value_begin();
252
260 [[nodiscard]] SPARROW_API value_iterator value_end();
261
269 [[nodiscard]] SPARROW_API const_value_iterator value_cbegin() const;
270
278 [[nodiscard]] SPARROW_API const_value_iterator value_cend() const;
279
280 SPARROW_API void resize_values(size_type new_length, const map_value& value);
281
282 template <std::input_iterator InputIt>
283 requires std::convertible_to<typename std::iterator_traits<InputIt>::value_type, map_value>
284 constexpr value_iterator insert_values(const_value_iterator pos, InputIt first, InputIt last);
285
286 SPARROW_API value_iterator insert_value(const_value_iterator pos, const map_value& value, size_type count);
287
289
299 [[nodiscard]] SPARROW_API inner_reference value(size_type i);
300
310 [[nodiscard]] SPARROW_API inner_const_reference value(size_type i) const;
311
320 [[nodiscard]] SPARROW_API offset_span_type make_list_offsets() const;
321
330 [[nodiscard]] SPARROW_API cloning_ptr<array_wrapper> make_entries_array() const;
331
339 [[nodiscard]] SPARROW_API bool get_keys_sorted() const;
340
356 [[nodiscard]] SPARROW_API static bool
357 check_keys_sorted(const array& flat_keys, const offset_buffer_type& offsets);
358
359 SPARROW_API void replace_contents(
360 std::vector<array_traits::value_type>&& flat_keys,
361 std::vector<array_traits::value_type>&& flat_items,
362 offset_buffer_type&& list_offsets
363 );
364
383 template <input_metadata_container METADATA_RANGE = std::vector<metadata_pair>>
384 [[nodiscard]] static arrow_proxy create_proxy_impl(
385 array&& flat_keys,
386 array&& flat_items,
387 offset_buffer_type&& list_offsets,
388 buffer<std::uint8_t>&& validity_buffer,
389 std::int64_t null_count,
390 std::optional<std::unordered_set<ArrowFlag>> flags,
391 std::optional<std::string_view> name,
392 std::optional<METADATA_RANGE> metadata
393 );
394
418 template <
420 input_metadata_container METADATA_RANGE = std::vector<metadata_pair>>
421 [[nodiscard]] static arrow_proxy create_proxy(
422 array&& flat_keys,
423 array&& flat_items,
424 offset_buffer_type&& list_offsets,
425 VB&& validity_input,
426 std::optional<std::string_view> name = std::nullopt,
427 std::optional<METADATA_RANGE> metadata = std::nullopt
428 );
429
452 template <
454 std::ranges::input_range OFFSET_BUFFER_RANGE,
455 input_metadata_container METADATA_RANGE = std::vector<metadata_pair>>
456 requires std::convertible_to<std::ranges::range_value_t<OFFSET_BUFFER_RANGE>, offset_type>
457 [[nodiscard]] static arrow_proxy create_proxy(
458 array&& flat_keys,
459 array&& flat_items,
460 OFFSET_BUFFER_RANGE&& list_offsets_range,
461 VB&& validity_input,
462 std::optional<std::string_view> name = std::nullopt,
463 std::optional<METADATA_RANGE> metadata = std::nullopt
464 )
465 {
466 offset_buffer_type list_offsets{std::move(list_offsets_range)};
467 return map_array::create_proxy(
468 std::move(flat_keys),
469 std::move(flat_items),
470 std::move(list_offsets),
471 std::forward<VB>(validity_input),
472 std::forward<std::optional<std::string_view>>(name),
473 std::forward<std::optional<METADATA_RANGE>>(metadata)
474 );
475 }
476
477 /*
478 * @brief Creates Arrow proxy from keys, values, offsets, and nullable flag.
479 *
480 * @tparam METADATA_RANGE Type of metadata container
481 * @param flat_keys Array containing all map keys
482 * @param flat_values Array containing all map values
483 * @param list_offsets Buffer of offsets indicating map boundaries
484 * @param nullable Whether the array should support null values
485 * @param name Optional name for the array
486 * @param metadata Optional metadata for the array
487 * @return Arrow proxy containing the map array data and schema
488 *
489 * @pre flat_keys must be a valid array
490 * @pre flat_values must be a valid array
491 * @pre flat_keys.size() must equal flat_values.size()
492 * @pre list_offsets.size() must be >= 1
493 * @pre Last offset must not exceed flat_keys.size()
494 * @post If nullable is true, array supports null values (though none initially set)
495 * @post If nullable is false, array does not support null values
496 * @post Keys sorted flag is determined from actual key ordering
497 */
498 template <
500 input_metadata_container METADATA_RANGE = std::vector<metadata_pair>>
501 [[nodiscard]] static arrow_proxy create_proxy(
502 array&& flat_keys,
503 array&& flat_values,
504 offset_buffer_type&& list_offsets,
505 bool nullable = true,
506 std::optional<std::string_view> name = std::nullopt,
507 std::optional<METADATA_RANGE> metadata = std::nullopt
508 );
509
532 template <
534 std::ranges::input_range OFFSET_BUFFER_RANGE,
535 input_metadata_container METADATA_RANGE = std::vector<metadata_pair>>
536 requires std::convertible_to<std::ranges::range_value_t<OFFSET_BUFFER_RANGE>, offset_type>
537 [[nodiscard]] static arrow_proxy create_proxy(
538 array&& flat_keys,
539 array&& flat_items,
540 OFFSET_BUFFER_RANGE&& list_offsets_range,
541 bool nullable = true,
542 std::optional<std::string_view> name = std::nullopt,
543 std::optional<METADATA_RANGE> metadata = std::nullopt
544 )
545 {
546 offset_buffer_type list_offsets{std::move(list_offsets_range)};
547 return map_array::create_proxy(
548 std::move(flat_keys),
549 std::move(flat_items),
550 std::move(list_offsets),
551 nullable,
552 std::forward<std::optional<std::string_view>>(name),
553 std::forward<std::optional<METADATA_RANGE>>(metadata)
554 );
555 }
556
557 static constexpr std::size_t OFFSET_BUFFER_INDEX = 1;
558 cloning_ptr<array_wrapper> p_entries_array;
559 bool m_keys_sorted{};
560
561 // friend classes
562 friend class array_crtp_base<map_array>;
563 friend class mutable_array_base<map_array>;
566 };
567
568 template <std::ranges::range SIZES_RANGE>
570 {
572 std::forward<SIZES_RANGE>(sizes)
573 );
574 }
575
576 template <std::input_iterator InputIt>
577 requires std::convertible_to<typename std::iterator_traits<InputIt>::value_type, map_value>
578 constexpr auto map_array::insert_values(const_value_iterator pos, InputIt first, InputIt last)
580 {
581 const auto index = static_cast<size_type>(std::distance(value_cbegin(), pos));
582 size_type count = 0;
583 for (auto it = first; it != last; ++it, ++count)
584 {
585 insert_value(
586 std::next(value_cbegin(), static_cast<std::ptrdiff_t>(index + count)),
587 *it,
588 1
589 );
590 }
591 return std::next(value_begin(), static_cast<std::ptrdiff_t>(index));
592 }
593
594 template <input_metadata_container METADATA_RANGE>
595 arrow_proxy map_array::create_proxy_impl(
596 array&& flat_keys,
597 array&& flat_items,
598 offset_buffer_type&& list_offsets,
599 buffer<std::uint8_t>&& validity_buffer,
600 std::int64_t null_count,
601 std::optional<std::unordered_set<ArrowFlag>> flags,
602 std::optional<std::string_view> name,
603 std::optional<METADATA_RANGE> metadata
604 )
605 {
606 const auto size = list_offsets.size() - 1;
607
608 std::array<sparrow::array, 2> struct_children = {std::move(flat_keys), std::move(flat_items)};
609 struct_array entries(std::move(struct_children), false, std::string("entries"));
610
611 auto [entries_arr, entries_schema] = extract_arrow_structures(std::move(entries));
612
613 const repeat_view<bool> children_ownership{true, 1};
614
615 ArrowSchema** child_schemas = new ArrowSchema*[1];
616 child_schemas[0] = new ArrowSchema(std::move(entries_schema));
617
618 ArrowSchema schema = make_arrow_schema(
619 std::string("+m"),
620 name, // name
621 metadata, // metadata
622 flags, // flags,
623 child_schemas,
624 children_ownership, // children ownership
625 nullptr, // dictionary
626 true // dictionary ownership
627
628 );
629
630 std::vector<buffer<std::uint8_t>> arr_buffs;
631 arr_buffs.reserve(2);
632 arr_buffs.emplace_back(std::move(validity_buffer));
633 arr_buffs.emplace_back(std::move(list_offsets).extract_storage());
634
635 ArrowArray** child_arrays = new ArrowArray*[1];
636 child_arrays[0] = new ArrowArray(std::move(entries_arr));
637
638 ArrowArray arr = make_arrow_array(
639 static_cast<std::int64_t>(size), // length
640 null_count,
641 0, // offset
642 std::move(arr_buffs),
643 child_arrays,
644 children_ownership, // children ownership
645 nullptr, // dictionary
646 true // dictionary ownership
647 );
648 return arrow_proxy{std::move(arr), std::move(schema)};
649 }
650
651 template <validity_bitmap_input VB, input_metadata_container METADATA_RANGE>
652 arrow_proxy map_array::create_proxy(
653 array&& flat_keys,
654 array&& flat_items,
655 offset_buffer_type&& list_offsets,
656 VB&& validity_input,
657 std::optional<std::string_view> name,
658 std::optional<METADATA_RANGE> metadata
659 )
660 {
661 const auto size = list_offsets.size() - 1;
662 validity_bitmap vbitmap = ensure_validity_bitmap(size, std::forward<VB>(validity_input));
663
664 std::optional<std::unordered_set<ArrowFlag>> flags{{ArrowFlag::NULLABLE}};
665 const bool keys_sorted = check_keys_sorted(flat_keys, list_offsets);
666 if (keys_sorted)
667 {
668 flags.value().insert(ArrowFlag::MAP_KEYS_SORTED);
669 }
670
671 const auto null_count = vbitmap.null_count();
672 buffer<std::uint8_t> validity_buffer = std::move(vbitmap).extract_storage();
673
674 return create_proxy_impl(
675 std::move(flat_keys),
676 std::move(flat_items),
677 std::move(list_offsets),
678 std::move(validity_buffer),
679 static_cast<std::int64_t>(null_count),
680 std::move(flags),
681 name,
682 std::forward<std::optional<METADATA_RANGE>>(metadata)
683 );
684 }
685
686 template <validity_bitmap_input VB, input_metadata_container METADATA_RANGE>
687 arrow_proxy map_array::create_proxy(
688 array&& flat_keys,
689 array&& flat_items,
690 offset_buffer_type&& list_offsets,
691 bool nullable,
692 std::optional<std::string_view> name,
693 std::optional<METADATA_RANGE> metadata
694 )
695 {
696 if (nullable)
697 {
698 return map_array::create_proxy(
699 std::move(flat_keys),
700 std::move(flat_items),
701 std::move(list_offsets),
703 name,
704 metadata
705 );
706 }
707 else
708 {
709 bool keys_sorted = check_keys_sorted(flat_keys, list_offsets);
710 auto flags = keys_sorted
711 ? std::optional<std::unordered_set<ArrowFlag>>{{ArrowFlag::MAP_KEYS_SORTED}}
712 : std::nullopt;
713
714 return create_proxy_impl(
715 std::move(flat_keys),
716 std::move(flat_items),
717 std::move(list_offsets),
718 buffer<std::uint8_t>{nullptr, 0, buffer<std::uint8_t>::default_allocator()}, // no validity
719 // bitmap
720 0, // null_count
721 std::move(flags),
722 name,
723 std::forward<std::optional<METADATA_RANGE>>(metadata)
724 );
725 }
726 }
727}
void struct_array()
typename base_type::const_bitmap_range const_bitmap_range
typename base_type::iterator_tag iterator_tag
typename base_type::bitmap_const_reference bitmap_const_reference
typename base_type::bitmap_type bitmap_type
Base class for array type erasure.
Dynamically typed array encapsulating an Arrow layout.
Definition array_api.hpp:50
Object that owns a piece of contiguous memory.
Definition buffer.hpp:142
xsimd::aligned_allocator< T > default_allocator
Definition buffer.hpp:155
typename storage_type::default_allocator default_allocator
inner_types::inner_const_reference inner_const_reference
inner_types::const_value_iterator const_value_iterator
Definition map_array.hpp:97
typename base_type::iterator_tag iterator_tag
nullable< inner_value_type > value_type
std::span< const std::int32_t > offset_span_type
SPARROW_API map_array & operator=(const self_type &rhs)
Copy assignment operator.
SPARROW_API map_array(const self_type &rhs)
Copy constructor.
inner_types::inner_value_type inner_value_type
map_array(Args &&... args)
Generic constructor for creating map array from various inputs.
typename base_type::iterator iterator
map_array self_type
Definition map_array.hpp:93
mutable_array_bitmap_base< self_type > base_type
Definition map_array.hpp:94
typename base_type::const_bitmap_range const_bitmap_range
SPARROW_API const array_wrapper * raw_items_array() const
Gets read-only access to the values array.
inner_types::value_iterator value_iterator
Definition map_array.hpp:96
static auto offset_from_sizes(SIZES_RANGE &&sizes) -> offset_buffer_type
Creates offset buffer from map sizes.
map_array(map_array &&) noexcept=default
SPARROW_API const array_wrapper * raw_keys_array() const
Gets read-only access to the keys array.
inner_types::inner_reference inner_reference
const std::int32_t offset_type
Definition map_array.hpp:99
u8_buffer< std::remove_const_t< offset_type > > offset_buffer_type
typename base_type::bitmap_type bitmap_type
SPARROW_API map_array(arrow_proxy proxy)
Constructs map array from Arrow proxy.
nullable< inner_const_reference, bitmap_const_reference > const_reference
array_inner_types< self_type > inner_types
Definition map_array.hpp:95
typename base_type::size_type size_type
Definition map_array.hpp:98
typename base_type::const_iterator const_iterator
typename base_type::bitmap_const_reference bitmap_const_reference
Base class definining common interface for arrays with a bitmap.
This buffer class is used as storage buffer for all sparrow arrays.
Concept for input containers that can provide metadata pairs.
Definition metadata.hpp:332
Concept defining valid input types for validity bitmap creation.
#define SPARROW_API
Definition config.hpp:38
constexpr sparrow::u8_buffer< OFFSET_TYPE > offset_buffer_from_sizes(SIZES_RANGE &&sizes)
constexpr std::size_t size(typelist< T... >={})
Gets the count of types contained in a typelist.
Definition mp_utils.hpp:216
constexpr bool excludes_copy_and_move_ctor_v
Convenience variable template for excludes_copy_and_move_ctor.
array_bitmap_base_impl< D, true > mutable_array_bitmap_base
Convenient alias for arrays with mutable validity bitmaps.
ArrowSchema make_arrow_schema(F format, N name, std::optional< M > metadata, std::optional< std::unordered_set< ArrowFlag > > flags, ArrowSchema **children, const CHILDREN_OWNERSHIP &children_ownership, ArrowSchema *dictionary, bool dictionary_ownership)
Creates an ArrowSchema owned by a unique_ptr and holding the provided data.
std::pair< ArrowArray, ArrowSchema > extract_arrow_structures(A &&a)
Extracts the internal ArrowArray and ArrowSchema structures from the given array or typed layout.
Definition array.hpp:110
ArrowArray make_arrow_array(int64_t length, int64_t null_count, int64_t offset, B buffers, ArrowArray **children, const CHILDREN_OWNERSHIP &children_ownership, ArrowArray *dictionary, bool dictionary_ownership)
Creates an ArrowArray.
dynamic_bitset< std::uint8_t > validity_bitmap
Type alias for a validity bitmap using 8-bit storage blocks.
constexpr bool is_map_array_v
Definition map_array.hpp:46
validity_bitmap ensure_validity_bitmap(std::size_t size, R &&validity_input)
Ensures a validity bitmap of the specified size from various input types.
std::pair< metadata_key, metadata_value > metadata_pair
Type alias for metadata key-value pairs.
Definition metadata.hpp:61
repeat_view(T &, size_t) -> repeat_view< T & >
data_type
Runtime identifier of arrow data types, usually associated with raw bytes with the associated value.
Extensions to the C++ standard library.
functor_index_iterator< detail::layout_value_functor< array_type, inner_value_type > > value_iterator
Definition map_array.hpp:39
std::random_access_iterator_tag iterator_tag
Definition map_array.hpp:42
functor_index_iterator< detail::layout_value_functor< const array_type, inner_value_type > > const_value_iterator
Definition map_array.hpp:40
Base class for array_inner_types specializations.
Traits class that must be specialized by array implementations.
Metafunction for retrieving the data_type of a typed array.