78 inline constexpr std::size_t
union_no_child = std::numeric_limits<std::size_t>::max();
170 template <
class DERIVED>
197 [[nodiscard]]
constexpr std::optional<std::string_view>
name()
const;
276 [[nodiscard]]
constexpr bool empty()
const;
406 template <std::input_iterator InputIt>
489 template <std::ranges::input_range R>
508 template <std::ranges::input_range R>
509 requires(std::convertible_to<std::ranges::range_value_t<R>, std::uint8_t>)
510 static constexpr std::string
567 template <
class VALUE>
570 const auto current_size =
size();
571 if (new_length < current_size)
575 else if (new_length > current_size)
577 insert(
cend(), std::forward<VALUE>(value), new_length - current_size);
591 std::vector<detail::union_rebuild_value>& entries,
596 for (
size_type index = from; index < to; ++index)
613 std::vector<array_traits::value_type> inserted,
641 std::vector<std::uint8_t>& child_type_ids,
642 std::array<bool, TYPE_ID_MAP_SIZE>& used_type_ids
660 std::span<const array_traits::value_type> inserted,
661 std::vector<union_child_schema>& child_schemas,
662 std::vector<std::uint8_t>& child_type_ids,
663 std::array<bool, TYPE_ID_MAP_SIZE>& used_type_ids,
664 std::vector<array>& new_child_templates
682 const std::vector<union_child_schema>& child_schemas,
683 std::vector<std::size_t>& inserted_children,
684 std::vector<array_traits::value_type>& inserted
700 std::span<const detail::union_rebuild_value> values,
701 std::span<const std::size_t> inserted_children,
702 std::span<const std::uint8_t> child_type_ids,
703 std::span<const detail::union_rebuild_value> fillers
719 std::span<const array_traits::value_type> inserted,
720 std::span<const std::size_t> inserted_children,
722 std::vector<array>& new_child_templates
731 std::vector<array> children,
733 std::span<const std::uint8_t> child_type_ids
742 std::vector<std::uint8_t> child_type_ids,
749 std::vector<detail::union_rebuild_value> values,
750 std::vector<array_traits::value_type> inserted,
780#if defined(__cpp_lib_format)
781 friend struct std::formatter<DERIVED>;
854 template <
class... Args>
922 std::ranges::input_range TYPE_MAPPING = std::vector<std::uint8_t>,
924 requires(std::convertible_to<std::ranges::range_value_t<TYPE_MAPPING>, std::uint8_t>)
925 [[nodiscard]]
static auto create_proxy(
926 std::vector<array>&& children,
929 std::optional<TYPE_MAPPING>&& type_mapping = std::nullopt,
930 std::optional<std::string_view>
name = std::nullopt,
931 std::optional<METADATA_RANGE>
metadata = std::nullopt
953 std::ranges::input_range TYPE_ID_BUFFER_RANGE,
954 std::ranges::input_range OFFSET_BUFFER_RANGE,
955 std::ranges::input_range TYPE_MAPPING = std::vector<std::uint8_t>,
957 requires(std::convertible_to<std::ranges::range_value_t<TYPE_MAPPING>, std::uint8_t>)
959 std::vector<array>&& children,
960 TYPE_ID_BUFFER_RANGE&& element_type,
961 OFFSET_BUFFER_RANGE&& offsets,
962 std::optional<TYPE_MAPPING>&& type_mapping = std::nullopt,
963 std::optional<std::string_view>
name = std::nullopt,
964 std::optional<METADATA_RANGE>
metadata = std::nullopt
970 return dense_union_array::create_proxy(
972 std::move(element_type_buffer),
973 std::move(offsets_buffer),
974 std::move(type_mapping),
996 template <input_metadata_container METADATA_RANGE = std::vector<metadata_pair>>
997 [[nodiscard]]
static arrow_proxy create_proxy_impl(
998 std::vector<array>&& children,
1001 std::string&& format,
1002 std::optional<std::string_view>
name = std::nullopt,
1003 std::optional<METADATA_RANGE>
metadata = std::nullopt
1023 std::ranges::input_range TYPE_ID_BUFFER_RANGE,
1024 std::ranges::input_range OFFSET_BUFFER_RANGE,
1026 [[nodiscard]]
static arrow_proxy create_proxy_impl(
1027 std::vector<array>&& children,
1028 TYPE_ID_BUFFER_RANGE&& element_type,
1029 OFFSET_BUFFER_RANGE&& offsets,
1030 std::string&& format,
1031 std::optional<std::string_view>
name = std::nullopt,
1032 std::optional<METADATA_RANGE>
metadata = std::nullopt
1035 SPARROW_ASSERT_TRUE(std::ranges::distance(element_type) == std::ranges::distance(offsets));
1039 return dense_union_array::create_proxy_impl(
1040 std::move(children),
1041 std::move(element_type_buffer),
1042 std::move(offsets_buffer),
1059 SPARROW_API std::size_t element_offset(std::size_t i)
const;
1062 std::vector<detail::union_rebuild_value> values,
1063 std::vector<array_traits::value_type> inserted,
1067 const std::int32_t* p_offsets;
1120 template <
class... Args>
1163 std::ranges::input_range TYPE_MAPPING = std::vector<std::uint8_t>,
1165 requires(std::convertible_to<std::ranges::range_value_t<TYPE_MAPPING>, std::uint8_t>)
1166 static auto create_proxy(
1167 std::vector<array>&& children,
1169 std::optional<TYPE_MAPPING>&& type_mapping = std::nullopt,
1170 std::optional<std::string_view>
name = std::nullopt,
1171 std::optional<METADATA_RANGE>
metadata = std::nullopt
1189 template <input_metadata_container METADATA_RANGE>
1190 static auto create_proxy_impl(
1191 std::vector<array>&& children,
1193 std::string&& format,
1194 std::optional<std::string_view>
name = std::nullopt,
1195 std::optional<METADATA_RANGE>
metadata = std::nullopt
1211 [[nodiscard]]
SPARROW_API std::size_t element_offset(std::size_t i)
const;
1214 std::vector<detail::union_rebuild_value> values,
1215 std::vector<array_traits::value_type> inserted,
1226 template <
class DERIVED>
1228 -> std::vector<std::uint8_t>
1230 SPARROW_ASSERT_TRUE(format_string.starts_with(
"+ud:") || format_string.starts_with(
"+us:"));
1231 format_string.remove_prefix(4);
1233 std::vector<std::uint8_t> result;
1234 while (!format_string.empty())
1236 const auto separator = format_string.find(
',');
1237 const auto token = format_string.substr(0, separator);
1238 std::uint32_t type_id = 0;
1239 const auto [
end, error] = std::from_chars(token.data(), token.data() + token.size(), type_id);
1242 result.push_back(
static_cast<std::uint8_t
>(type_id));
1243 if (separator == std::string_view::npos)
1247 format_string.remove_prefix(separator + 1);
1252 template <
class DERIVED>
1258 std::array<bool, TYPE_ID_MAP_SIZE> seen{};
1259 for (std::size_t child_index = 0; child_index < child_type_ids.size(); ++child_index)
1261 const auto type_id = child_type_ids[child_index];
1264 seen[type_id] =
true;
1265 result[type_id] =
static_cast<std::uint8_t
>(child_index);
1270 template <
class DERIVED>
1271 template <std::ranges::input_range R>
1277 if (!child_index_to_type_id.has_value())
1279 constexpr std::array<std::uint8_t, TYPE_ID_MAP_SIZE> default_mapping = []
1281 std::array<std::uint8_t, TYPE_ID_MAP_SIZE> arr{};
1282 std::iota(arr.begin(), arr.end(), 0);
1285 return default_mapping;
1289 std::size_t child_index = 0;
1290 for (
const auto type_id : *child_index_to_type_id)
1293 const auto id =
static_cast<std::size_t
>(type_id);
1295 ret[id] =
static_cast<std::uint8_t
>(child_index++);
1301 template <
class DERIVED>
1302 template <std::ranges::input_range R>
1303 requires(std::convertible_to<std::ranges::range_value_t<R>, std::uint8_t>)
1304 constexpr std::string
1307 const auto range_size = range.has_value() ? std::ranges::size(*range) : 0;
1310 throw std::invalid_argument(
"Invalid type-id map");
1313 std::string result = dense ?
"+ud:" :
"+us:";
1315 const auto append_type_id = [&result, &first](
const auto type_id)
1319 result.push_back(
',');
1321 result += std::to_string(type_id);
1327 for (
const auto type_id : std::views::iota(std::size_t{0}, n))
1329 append_type_id(type_id);
1334 for (
const auto type_id : *range)
1336 append_type_id(type_id);
1342 template <
class DERIVED>
1348 template <
class DERIVED>
1354 template <
class DERIVED>
1360 template <
class DERIVED>
1366 template <
class DERIVED>
1376 template <
class DERIVED>
1382 template <
class DERIVED>
1396 template <
class DERIVED>
1399 const auto type_id =
static_cast<std::size_t
>(
p_type_ids[i +
m_proxy.offset()]);
1401 const auto offset = this->
derived_cast().element_offset(i);
1405 template <
class DERIVED>
1411 template <
class DERIVED>
1417 template <
class DERIVED>
1423 template <
class DERIVED>
1429 template <
class DERIVED>
1435 template <
class DERIVED>
1441 template <
class DERIVED>
1447 template <
class DERIVED>
1453 template <
class DERIVED>
1459 template <
class DERIVED>
1465 template <
class DERIVED>
1471 template <
class DERIVED>
1477 template <
class DERIVED>
1483 template <
class DERIVED>
1489 template <
class DERIVED>
1492 return (*
this)[this->
size() - 1];
1495 template <
class DERIVED>
1499 for (std::size_t i = 0; i < children.size(); ++i)
1509 return std::ranges::equal(lhs, rhs);
1512 template <
class DERIVED>
1513 template <std::input_iterator InputIt>
1522 return insert_materialized(pos, std::vector<array_traits::value_type>(first, last), count);
1525 template <
class DERIVED>
1531 template <
class DERIVED>
1537 template <
class DERIVED>
1543 template <
class DERIVED>
1549 template <
class DERIVED>
1555 template <
class DERIVED>
1563 template <
class DERIVED>
1570 return erase_values(first_index, last_index - first_index);
1573 template <
class DERIVED>
1575 std::vector<std::uint8_t>& child_type_ids,
1576 std::array<bool, TYPE_ID_MAP_SIZE>& used_type_ids
1577 )
const -> std::vector<union_child_schema>
1583 std::vector<union_child_schema> child_schemas;
1584 child_schemas.reserve(child_count);
1585 for (std::size_t child_index = 0; child_index < child_count; ++child_index)
1587 used_type_ids[child_type_ids[child_index]] =
true;
1588 child_schemas.emplace_back(
1593 return child_schemas;
1596 template <
class DERIVED>
1601 const auto current_size =
size();
1609 std::vector<rebuild_value> values;
1610 values.reserve(current_size - count);
1613 return this->
derived_cast().rebuild_in_place(std::move(values), {}, first);
1628 return static_cast<std::size_t
>(std::ranges::find(used_type_ids,
false) - used_type_ids.begin());
1638 return inserted_children[value.
row];
1659 using stored_type = std::remove_cvref_t<T>;
1675#if SPARROW_GCC_11_2_WORKAROUND
1676 static_cast<const dynamic_value::base_type&
>(value)
1691 std::span<const rebuild_value> values,
1692 std::span<const std::size_t> inserted_children,
1693 std::span<const std::uint8_t> child_type_ids
1701 std::vector<std::size_t> child_value_counts(child_type_ids.size(), 0);
1702 for (
const auto& value : values)
1704 ++child_value_counts[
child_of(value, inserted_children)];
1706 for (std::size_t child_index = 0; child_index < child_type_ids.size(); ++child_index)
1708 payload.
child_values[child_index].reserve(child_value_counts[child_index]);
1711 for (
const auto& value : values)
1713 const auto child_index =
child_of(value, inserted_children);
1717 <=
static_cast<std::size_t
>(std::numeric_limits<std::int32_t>::max())
1734 std::span<const rebuild_value> values,
1735 std::span<const std::size_t> inserted_children,
1736 std::span<const std::uint8_t> child_type_ids,
1737 std::span<const rebuild_value> fillers
1743 for (
const auto& value : values)
1748 for (std::size_t child_index = 0; child_index < child_type_ids.size(); ++child_index)
1751 auto& child_values = payload.
child_values[child_index];
1752 child_values.reserve(values.size());
1753 for (
const auto& value : values)
1755 child_values.push_back(
1756 child_of(value, inserted_children) == child_index ? value : fillers[child_index]
1771 array filler = old_child_view.
slice(row, row + 1);
1773 if (
auto& bitmap = proxy.bitmap(); bitmap.has_value())
1775 *bitmap->begin() =
false;
1776 proxy.set_null_count(1);
1787 const array rows = old_child_view.
slice_view(first_row, first_row + count);
1798 template <
typename CHILDREN>
1801 std::span<const rebuild_value> values,
1802 std::span<const dynamic_value> inserted,
1803 std::span<const std::size_t> inserted_children,
1804 const CHILDREN& old_children
1810 std::optional<array> old_child_view;
1811 std::optional<array> filler_row;
1813 for (std::size_t index = 0; index < values.size();)
1815 const auto child_index =
child_of(values[index], inserted_children);
1816 const bool is_inserted = values[index].inserted;
1817 const bool force_null = values[index].force_null;
1818 const auto row = values[index].row;
1821 std::size_t count = 1;
1822 while (index + count < values.size())
1824 const auto&
next = values[index + count];
1825 if (
child_of(
next, inserted_children) != child_index ||
next.inserted != is_inserted
1826 ||
next.force_null != force_null
1827 ||
next.row != (force_null || is_inserted ? row : row + count))
1842 if (!old_child_view.has_value())
1844 old_child_view =
array{old_children[child_index]->get_arrow_proxy().view()};
1849 if (!filler_row.has_value())
1853 destination.
insert(destination.
cend(), filler_row->cbegin(), filler_row->cend(), count);
1864 template <
class DERIVED>
1866 std::span<const array_traits::value_type> inserted,
1867 std::vector<union_child_schema>& child_schemas,
1868 std::vector<std::uint8_t>& child_type_ids,
1869 std::array<bool, TYPE_ID_MAP_SIZE>& used_type_ids,
1870 std::vector<array>& new_child_templates
1871 ) -> std::vector<std::size_t>
1873 std::vector<std::size_t> inserted_children;
1874 inserted_children.reserve(inserted.size());
1875 for (
const auto& value : inserted)
1882 const auto existing = std::ranges::find(child_schemas, schema);
1883 if (existing != child_schemas.end())
1885 inserted_children.push_back(
static_cast<std::size_t
>(existing - child_schemas.begin()));
1892 used_type_ids[type_id] =
true;
1894 inserted_children.push_back(child_schemas.size());
1895 child_schemas.push_back(schema);
1896 child_type_ids.push_back(
static_cast<std::uint8_t
>(type_id));
1897 new_child_templates.push_back(std::move(child));
1899 return inserted_children;
1902 template <
class DERIVED>
1905 const std::vector<union_child_schema>& child_schemas,
1906 std::vector<std::size_t>& inserted_children,
1907 std::vector<array_traits::value_type>& inserted
1908 )
const -> std::vector<detail::union_rebuild_value>
1910 std::vector<detail::union_rebuild_value> fillers(child_schemas.size());
1911 for (std::size_t child_index = 0; child_index < fillers.size(); ++child_index)
1916 .child = child_index,
1926 if (child_index < old_child_count)
1932 const auto creator = std::ranges::find(inserted_children, child_index);
1934 default_value = inserted[
static_cast<std::size_t
>(creator - inserted_children.begin())];
1939 inserted_children.push_back(child_index);
1945 template <
class DERIVED>
1947 std::span<const detail::union_rebuild_value> values,
1948 std::span<const std::size_t> inserted_children,
1949 std::span<const std::uint8_t> child_type_ids,
1950 std::span<const detail::union_rebuild_value> fillers
1968 template <
class DERIVED>
1971 std::span<const array_traits::value_type> inserted,
1972 std::span<const std::size_t> inserted_children,
1974 std::vector<array>& new_child_templates
1975 )
const -> std::vector<array>
1977 const auto old_child_count = old_children.size();
1978 std::vector<array> new_children;
1979 new_children.reserve(payload.child_values.size());
1980 for (std::size_t child_index = 0; child_index < payload.child_values.size(); ++child_index)
1982 array child = child_index < old_child_count
1984 : std::move(new_child_templates[child_index - old_child_count]);
1985 auto& values_for_child = payload.child_values[child_index];
2002 new_children.push_back(std::move(child));
2004 return new_children;
2007 template <
class DERIVED>
2009 std::vector<array> children,
2011 std::span<const std::uint8_t> child_type_ids
2015 std::optional<std::vector<std::uint8_t>> type_id_mapping{
2016 std::vector<std::uint8_t>{child_type_ids.begin(), child_type_ids.end()}
2020 return DERIVED::create_proxy(
2021 std::move(children),
2022 std::move(payload.type_ids),
2023 std::move(payload.offsets),
2024 std::move(type_id_mapping),
2031 return DERIVED::create_proxy(
2032 std::move(children),
2033 std::move(payload.type_ids),
2034 std::move(type_id_mapping),
2041 template <
class DERIVED>
2044 std::vector<std::uint8_t> child_type_ids,
2048 m_proxy = std::move(replacement);
2055 this->
derived_cast().p_offsets =
reinterpret_cast<std::int32_t*
>(
m_proxy.buffers()[1].data());
2060 template <
class DERIVED>
2062 std::vector<detail::union_rebuild_value> values,
2063 std::vector<array_traits::value_type> inserted,
2067 const auto old_child_count =
m_children.size();
2069 std::vector<std::uint8_t> child_type_ids;
2070 std::array<bool, TYPE_ID_MAP_SIZE> used_type_ids{};
2071 std::vector<union_child_schema> child_schemas =
make_child_schemas(child_type_ids, used_type_ids);
2074 std::vector<array> new_child_templates;
2083 std::vector<detail::union_rebuild_value> fillers;
2086 fillers =
make_union_fillers(old_child_count, child_schemas, inserted_children, inserted);
2090 std::span<const detail::union_rebuild_value>{values},
2091 std::span<const std::size_t>{inserted_children},
2093 std::span<const detail::union_rebuild_value>{fillers}
2104 auto replacement =
create_rebuild_proxy(std::move(new_children), std::move(payload), child_type_ids);
2105 return adopt_rebuilt_array(std::move(replacement), std::move(child_type_ids), return_index);
2108 template <
class DERIVED>
2120 template <
class DERIVED>
2135 template <
class DERIVED>
2138 std::vector<array_traits::value_type> inserted,
2143 if (inserted.empty())
2152 const auto old_size =
size();
2153 const auto value_count =
static_cast<size_type>(inserted.size());
2154 std::vector<detail::union_rebuild_value> entries;
2155 entries.reserve(old_size + value_count * count);
2158 for (
size_type repetition = 0; repetition < count; ++repetition)
2160 for (
size_type value_index = 0; value_index < value_count; ++value_index)
2169 return this->
derived_cast().rebuild_in_place(std::move(entries), std::move(inserted), pos_index);
2178 template <input_metadata_container METADATA_RANGE = std::vector<metadata_pair>>
2180 std::vector<array>&& children,
2183 std::string&& format,
2184 std::optional<std::string_view> name,
2185 std::optional<METADATA_RANGE> metadata
2188 const auto n_children = children.size();
2192 for (std::size_t i = 0; i < n_children; ++i)
2194 auto& child = children[i];
2196 child_arrays[i] =
new ArrowArray(std::move(flat_arr));
2197 child_schemas[i] =
new ArrowSchema(std::move(flat_schema));
2203 child_schemas + n_children,
2212 const std::optional<std::unordered_set<sparrow::ArrowFlag>>
2220 std::move(metadata),
2229 static_cast<std::int64_t
>(size),
2239 return arrow_proxy{std::move(arr), std::move(schema)};
2247 template <std::ranges::input_range TYPE_MAPPING, input_metadata_container METADATA_RANGE>
2248 requires(std::convertible_to<std::ranges::range_value_t<TYPE_MAPPING>, std::uint8_t>)
2249 auto dense_union_array::create_proxy(
2250 std::vector<array>&& children,
2251 type_id_buffer_type&& element_type,
2252 offset_buffer_type&& offsets,
2253 std::optional<TYPE_MAPPING>&& child_index_to_type_id,
2254 std::optional<std::string_view> name,
2255 std::optional<METADATA_RANGE> metadata
2259 const auto n_children = children.size();
2261 std::string format = make_format_string(
true , n_children, child_index_to_type_id);
2263 return create_proxy_impl(
2264 std::move(children),
2265 std::move(element_type),
2273 template <input_metadata_container METADATA_RANGE>
2274 auto dense_union_array::create_proxy_impl(
2275 std::vector<array>&& children,
2276 type_id_buffer_type&& element_type,
2277 offset_buffer_type&& offsets,
2278 std::string&& format,
2279 std::optional<std::string_view> name,
2280 std::optional<METADATA_RANGE> metadata
2284 const auto size = element_type.size();
2286 std::vector<buffer<std::uint8_t>> arr_buffs;
2287 arr_buffs.reserve(2);
2288 arr_buffs.emplace_back(std::move(element_type).extract_storage());
2289 arr_buffs.emplace_back(std::move(offsets).extract_storage());
2292 std::move(children),
2293 std::move(arr_buffs),
2305 template <std::ranges::input_range TYPE_MAPPING, input_metadata_container METADATA_RANGE>
2306 requires(std::convertible_to<std::ranges::range_value_t<TYPE_MAPPING>, std::uint8_t>)
2307 auto sparse_union_array::create_proxy(
2308 std::vector<array>&& children,
2309 type_id_buffer_type&& element_type,
2310 std::optional<TYPE_MAPPING>&& child_index_to_type_id,
2311 std::optional<std::string_view> name,
2312 std::optional<METADATA_RANGE> metadata
2315 const auto n_children = children.size();
2316 if (child_index_to_type_id.has_value())
2321 std::string format = make_format_string(
false , n_children, child_index_to_type_id);
2323 return create_proxy_impl(
2324 std::move(children),
2325 std::move(element_type),
2332 template <input_metadata_container METADATA_RANGE>
2333 auto sparse_union_array::create_proxy_impl(
2334 std::vector<array>&& children,
2335 type_id_buffer_type&& element_type,
2336 std::string&& format,
2337 std::optional<std::string_view> name,
2338 std::optional<METADATA_RANGE> metadata
2341 for (
const auto& child : children)
2345 const auto size = element_type.size();
2347 std::vector<buffer<std::uint8_t>> arr_buffs;
2348 arr_buffs.reserve(1);
2349 arr_buffs.emplace_back(std::move(element_type).extract_storage());
2352 std::move(children),
2353 std::move(arr_buffs),
2362#if defined(__cpp_lib_format)
2372template <
typename U>
2373 requires std::derived_from<U, sparrow::union_array_crtp_base<U>>
2374struct std::formatter<U>
2382 constexpr auto parse(std::format_parse_context& ctx)
2397 auto format(
const U& ar, std::format_context& ctx)
const
2399 if constexpr (std::is_same_v<U, sparrow::dense_union_array>)
2401 std::format_to(ctx.out(),
"DenseUnion");
2403 else if constexpr (std::is_same_v<U, sparrow::sparse_union_array>)
2405 std::format_to(ctx.out(),
"SparseUnion");
2409 static_assert(sparrow::mpl::dependent_false<U>::value,
"Unknown union array type");
2412 const auto& proxy = ar.get_arrow_proxy();
2413 std::format_to(ctx.out(),
" [name={} | size={}] <", proxy.name().value_or(
"nullptr"), proxy.length());
2417 std::prev(ar.cend()),
2418 [&ctx](
const auto& value)
2420 std::format_to(ctx.out(),
"{}, ", value);
2424 return std::format_to(ctx.out(),
"{}>", ar.back());
2440 template <
typename U>
2441 requires std::derived_from<U, union_array_crtp_base<U>>
2442 std::ostream&
operator<<(std::ostream& os,
const U& value)
2444 os << std::format(
"{}", value);
Base class for array type erasure.
constexpr arrow_proxy & get_arrow_proxy()
Dynamically typed array encapsulating an Arrow layout.
SPARROW_API iterator erase(const_iterator pos)
Inserts a copy of value before pos in the array, repeating the insertion count times.
SPARROW_API array slice(size_type start, size_type end) const
Returns a deep-copy of the array restricted to the elements in the half-open range [start,...
SPARROW_API const_iterator cend() const
Returns a constant iterator to the end of the array.
SPARROW_API enum data_type data_type() const
SPARROW_API iterator insert(const_iterator pos, const_iterator first, const_iterator last)
Inserts elements from the range [first, last) before the element at the specified position.
SPARROW_API const_iterator cbegin() const
Returns a constant iterator to the beginning of the array.
SPARROW_API array slice_view(size_type start, size_type end) const
Returns a zero-copy view of the array restricted to the elements in the half-open range [start,...
SPARROW_API arrow_proxy view() const
Get a non-owning view of the arrow_proxy.
constexpr void push_back(const value_type &value)
Adds an element to the end.
constexpr void reserve(size_type new_cap)
Reserves storage for at least the specified number of elements.
Object that owns a piece of contiguous memory.
Base class for CRTP base classes.
constexpr derived_type & derived_cast()
Dense union array implementation with offset buffer.
SPARROW_API dense_union_array & operator=(const dense_union_array &rhs)
Copy assignment operator.
u8_buffer< std::uint32_t > offset_buffer_type
union_array_crtp_base< dense_union_array > base_type
typename base_type::type_id_buffer_type type_id_buffer_type
dense_union_array(Args &&... args)
Generic constructor for creating dense union arrays.
SPARROW_API dense_union_array(arrow_proxy proxy)
Constructs dense union array from Arrow proxy.
SPARROW_API dense_union_array(const dense_union_array &rhs)
Copy constructor.
dense_union_array(dense_union_array &&rhs)=default
dense_union_array & operator=(dense_union_array &&rhs)=default
static const sparrow::arrow_proxy & get_arrow_proxy(const ARRAY &array)
A view that repeats a value a given number of times.
Sparse union array implementation without offset buffer.
SPARROW_API sparse_union_array & operator=(const sparse_union_array &)
sparse_union_array(Args &&... args)
Generic constructor for creating sparse union arrays.
union_array_crtp_base< sparse_union_array > base_type
typename base_type::type_id_buffer_type type_id_buffer_type
SPARROW_API sparse_union_array(const sparse_union_array &)
SPARROW_API sparse_union_array(arrow_proxy proxy)
Constructs sparse union array from Arrow proxy.
This buffer class is used as storage buffer for all sparrow arrays.
CRTP base class providing shared functionality for union array implementations.
array_traits::inner_value_type inner_value_type
std::reverse_iterator< const_iterator > const_reverse_iterator
static std::vector< std::uint8_t > child_type_ids_from_format(std::string_view format_string)
Extracts child type IDs from an Arrow union format string.
const std::uint8_t * p_type_ids
constexpr iterator begin()
Gets iterator to the beginning of the array.
detail::layout_bracket_functor< const derived_type, value_type > const_functor_type
constexpr std::optional< std::string_view > name() const
Gets the optional name of the union array.
iterator insert_materialized(const_iterator pos, std::vector< array_traits::value_type > inserted, size_type count)
Rebuilds the array with the owned inserted values repeated count times before pos.
array_traits::const_reference value_type
void resize(size_type new_length)
Resizes the array, default-inserting any appended values.
void push_back(const array_traits::value_type &value)
Appends an owned value.
iterator iterator_at(size_type index)
constexpr union_array_crtp_base(const self_type &rhs)
Copy constructor.
u8_buffer< std::uint8_t > type_id_buffer_type
iterator insert(const_iterator pos, const array_traits::value_type &value, size_type count=1)
Inserts copies of an owned value before pos.
static constexpr std::string make_format_string(bool dense, std::size_t n, const std::optional< R > &child_index_to_type_id)
Creates Arrow format string for union arrays.
SPARROW_CONSTEXPR_CLANG value_type front() const
Gets reference to the first element.
iterator rebuild_values(std::vector< detail::union_rebuild_value > values, std::vector< array_traits::value_type > inserted, size_type return_index)
Rebuilds this array from values, the inserted values they reference, and.
constexpr const_reverse_iterator crbegin() const
Gets const reverse iterator to the beginning of reversed array.
void resize(size_type new_length, const array_traits::value_type &value)
Resizes the array, inserting value when it grows.
std::array< std::uint8_t, TYPE_ID_MAP_SIZE > m_type_id_map
constexpr arrow_proxy & get_arrow_proxy()
Gets mutable reference to the Arrow proxy.
std::vector< union_child_schema > make_child_schemas(std::vector< std::uint8_t > &child_type_ids, std::array< bool, TYPE_ID_MAP_SIZE > &used_type_ids) const
Initializes the schema bookkeeping of a rebuild from the current children.
static std::vector< std::size_t > resolve_inserted_children(std::span< const array_traits::value_type > inserted, std::vector< union_child_schema > &child_schemas, std::vector< std::uint8_t > &child_type_ids, std::array< bool, TYPE_ID_MAP_SIZE > &used_type_ids, std::vector< array > &new_child_templates)
Maps each inserted value to the child it belongs to.
union_array_crtp_base< DERIVED > self_type
constexpr self_type & operator=(self_type &&rhs)=default
union_array_crtp_base(arrow_proxy proxy)
Protected constructor from Arrow proxy.
void resize_impl(size_type new_length, VALUE &&value)
array_traits::const_reference const_reference
detail::layout_bracket_functor< derived_type, value_type > functor_type
SPARROW_CONSTEXPR_CLANG value_type operator[](size_type i) const
Gets element at specified position without bounds checking.
std::array< std::uint8_t, TYPE_ID_MAP_SIZE > type_id_map
iterator insert(const_iterator pos, const_reference value, size_type count=1)
Inserts copies of a value before pos.
void resize(size_type new_length, const_reference value)
Resizes the array, inserting value when it grows.
iterator adopt_rebuilt_array(arrow_proxy replacement, std::vector< std::uint8_t > child_type_ids, size_type return_index)
Replaces this array's data with the rebuilt replacement.
iterator erase(const_iterator pos)
Erases the value at pos.
std::vector< detail::union_rebuild_value > make_union_fillers(size_type old_child_count, const std::vector< union_child_schema > &child_schemas, std::vector< std::size_t > &inserted_children, std::vector< array_traits::value_type > &inserted) const
Builds the row padding the output rows a child is not selected for.
functor_index_iterator< const_functor_type > const_iterator
static constexpr type_id_map type_id_map_from_child_to_type_id(const std::optional< R > &child_index_to_type_id)
Creates type ID mapping from child index to type ID mapping.
iterator insert(const_iterator pos, InputIt first, InputIt last, size_type count=1)
Inserts a range before pos, repeated count times.
constexpr const_reverse_iterator rbegin() const
Gets reverse iterator to the beginning of reversed array.
iterator erase_values(size_type first, size_type count)
constexpr const_iterator begin() const
Gets const iterator to the beginning of the array.
SPARROW_CONSTEXPR_CLANG std::optional< key_value_view > metadata() const
Gets the metadata associated with the union array.
functor_index_iterator< functor_type > iterator
constexpr self_type & operator=(const self_type &rhs)
Copy assignment operator.
std::vector< array > build_rebuilt_children(const detail::union_rebuild_payload &payload, std::span< const array_traits::value_type > inserted, std::span< const std::size_t > inserted_children, const children_type &old_children, std::vector< array > &new_child_templates) const
Rebuilds each child array from the payload rows planned for it.
constexpr bool empty() const
Checks if the union array is empty.
SPARROW_CONSTEXPR_CLANG value_type at(size_type i) const
Gets element at specified position with bounds checking.
constexpr const_iterator cbegin() const
Gets const iterator to the beginning of the array.
std::vector< std::uint8_t > m_child_type_ids
constexpr const_reverse_iterator crend() const
Gets const reverse iterator to the end of reversed array.
void append_rebuild_entries(std::vector< detail::union_rebuild_value > &entries, size_type from, size_type to) const
Appends one rebuild entry per element in [from, to), each referring to its current child slot.
static constexpr type_id_map make_type_id_map(std::span< const std::uint8_t > child_type_ids)
Creates a type-ID lookup table from child type IDs.
constexpr const_iterator end() const
Gets const iterator to the end of the array.
arrow_proxy create_rebuild_proxy(std::vector< array > children, detail::union_rebuild_payload &&payload, std::span< const std::uint8_t > child_type_ids) const
Creates the Arrow proxy of a rebuilt array from its children and buffers.
static constexpr size_t TYPE_ID_MAP_SIZE
SPARROW_CONSTEXPR_CLANG value_type operator[](size_type i)
Gets mutable element at specified position.
constexpr const_iterator cend() const
Gets const iterator to the end of the array.
SPARROW_CONSTEXPR_CLANG value_type back() const
Gets reference to the last element.
constexpr union_array_crtp_base(self_type &&rhs)=default
void push_back(const_reference value)
Appends a borrowed value.
constexpr const arrow_proxy & get_arrow_proxy() const
Gets const reference to the Arrow proxy.
iterator erase(const_iterator first, const_iterator last)
Erases the half-open range [first, last).
constexpr iterator end()
Gets iterator to the end of the array.
constexpr size_type size() const
Gets the number of elements in the union array.
constexpr const_reverse_iterator rend() const
Gets reverse iterator to the end of reversed array.
constexpr void zero_null_values(const inner_value_type &value)
Replaces stored values at null positions.
std::vector< cloning_ptr< array_wrapper > > children_type
detail::union_rebuild_payload make_rebuild_payload(std::span< const detail::union_rebuild_value > values, std::span< const std::size_t > inserted_children, std::span< const std::uint8_t > child_type_ids, std::span< const detail::union_rebuild_value > fillers) const
Plans the rebuilt data from the row plan and the inserted-value resolution.
constexpr children_type make_children(arrow_proxy &proxy)
Creates child array wrappers from Arrow proxy.
#define SPARROW_CONSTEXPR_CLANG
#define SPARROW_ASSERT_TRUE(expr__)
union_rebuild_payload make_sparse_rebuild_payload(std::span< const rebuild_value > values, std::span< const std::size_t > inserted_children, std::span< const std::uint8_t > child_type_ids, std::span< const rebuild_value > fillers)
Creates a rebuild payload for a sparse union array.
void append_old_child_values(array &destination, const array &old_child_view, std::size_t first_row, std::size_t count)
Appends count consecutive rows of an old child, in a single insertion.
std::size_t child_of(const rebuild_value &value, std::span< const std::size_t > inserted_children)
Resolves the child a plan entry targets: inserted values carry no child index, only the index of the ...
dynamic_value make_null_dynamic_value(const T &value)
Builds a null dynamic value holding the type of the given inner value.
SPARROW_API array make_null_child(std::size_t count, const arrow_proxy &child_proxy)
detail::union_rebuild_payload union_rebuild_payload
union_rebuild_payload make_dense_rebuild_payload(std::span< const rebuild_value > values, std::span< const std::size_t > inserted_children, std::span< const std::uint8_t > child_type_ids)
Creates a rebuild payload for a dense union array.
std::size_t next_free_type_id(std::span< const bool > used_type_ids)
Finds an existing type ID not yet assigned, or TYPE_ID_MAP_SIZE if none is free.
void append_rebuild_values(array &destination, std::span< const rebuild_value > values, std::span< const dynamic_value > inserted, std::span< const std::size_t > inserted_children, const CHILDREN &old_children)
Appends the rebuild rows of one child to destination.
detail::union_rebuild_value rebuild_value
array make_filler_row(const array &old_child_view, std::size_t row)
Slices the row a filler rebuild value refers to, marked as null.
array_traits::value_type dynamic_value
array make_empty_child(const array_wrapper &child)
dynamic_value make_null_like(const dynamic_value &value)
Creates a null-like dynamic value for the given dynamic value.
constexpr std::size_t union_no_child
arrow_proxy create_union_proxy_impl(std::vector< array > &&children, std::vector< buffer< std::uint8_t > > &&buffers, std::size_t size, std::string &&format, std::optional< std::string_view > name, std::optional< METADATA_RANGE > metadata)
constexpr std::size_t size(typelist< T... >={})
Gets the count of types contained in a typelist.
constexpr bool excludes_copy_and_move_ctor_v
Convenience variable template for excludes_copy_and_move_ctor.
void unreachable()
Invokes undefined behavior for optimization purposes.
constexpr bool is_dense_union_array_v
Type trait to check if a type is a dense_union_array.
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.
constexpr void zero_null_values(R &range, const T &default_value=T{})
Sets null values in a range to a default value.
SPARROW_API bool operator==(const array &lhs, const array &rhs)
Compares the content of two arrays.
SPARROW_API std::size_t array_size(const array_wrapper &ar)
SPARROW_API array_traits::value_type array_default_value(const array_wrapper &ar)
constexpr InputIt next(InputIt it, Distance n)
SPARROW_API array array_make_from_element(const array_traits::value_type &value)
constexpr std::size_t range_size(R &&r)
SPARROW_API array array_empty_like(const array &source)
std::pair< ArrowArray, ArrowSchema > extract_arrow_structures(A &&a)
Extracts the internal ArrowArray and ArrowSchema structures from the given array or typed layout.
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.
std::ostream & operator<<(std::ostream &os, const nullval_t &)
SPARROW_API cloning_ptr< array_wrapper > array_factory(arrow_proxy proxy)
SPARROW_API array_traits::const_reference array_element(const array_wrapper &ar, std::size_t index)
constexpr bool is_sparse_union_array_v
Type trait to check if a type is a sparse_union_array.
data_type
Runtime identifier of arrow data types, usually associated with raw bytes with the associated value.
std::unordered_set< ArrowFlag > to_set_of_ArrowFlags(int64_t flag_values)
Converts a bitfield of ArrowFlag values to a set of ArrowFlag values.
Extensions to the C++ standard library.
mpl::rename< mpl::unique< mpl::transform< detail::array_const_reference_t, all_base_types_t > >, nullable_variant > const_reference
mpl::rename< mpl::transform< detail::array_value_type_t, all_base_types_t >, nullable_variant > value_type
mpl::rename< all_base_types_t, std::variant > inner_value_type
static constexpr sparrow::data_type get()
static constexpr sparrow::data_type get()
Metafunction for retrieving the data_type of a typed array.
Rebuilt data of a union array: the row plan of each child, plus the new type-ID and (dense-only) offs...
u8_buffer< std::uint32_t > offsets
Dense offsets (empty for sparse).
u8_buffer< std::uint8_t > type_ids
Type ID per output row.
std::vector< std::vector< union_rebuild_value > > child_values
Row plan of each child.
One row of a rebuild plan.
std::size_t child
Source child, or union_no_child when inserted.
bool inserted
True when the entry is an inserted value.
std::size_t row
Row of the source child, or inserted-value index.
bool force_null
Copy the row as null (sparse union filler row).
Schema of one child of a rebuilt union array.
bool operator==(const union_child_schema &other) const =default