diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 23f29e649..7b383b229 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -85,7 +85,7 @@ jobs: - name: Install dependencies shell: cmd run: | - vcpkg install zlib:x64-windows nlohmann-json:x64-windows nanoarrow:x64-windows + vcpkg install zlib:x64-windows nlohmann-json:x64-windows nanoarrow:x64-windows roaring:x64-windows - name: Build Iceberg shell: cmd run: | diff --git a/cmake_modules/IcebergThirdpartyToolchain.cmake b/cmake_modules/IcebergThirdpartyToolchain.cmake index 2e915c0d3..df3b9897a 100644 --- a/cmake_modules/IcebergThirdpartyToolchain.cmake +++ b/cmake_modules/IcebergThirdpartyToolchain.cmake @@ -261,6 +261,54 @@ function(resolve_nanoarrow_dependency) PARENT_SCOPE) endfunction() +# ---------------------------------------------------------------------- +# CRoaring + +function(resolve_croaring_dependency) + prepare_fetchcontent() + + set(BUILD_TESTING + OFF + CACHE BOOL "Disable CRoaring tests" FORCE) + + fetchcontent_declare(croaring + ${FC_DECLARE_COMMON_OPTIONS} + URL "https://github.com/RoaringBitmap/CRoaring/archive/refs/tags/v4.3.11.tar.gz" + FIND_PACKAGE_ARGS + NAMES + roaring + CONFIG) + fetchcontent_makeavailable(croaring) + + if(croaring_SOURCE_DIR) + if(NOT TARGET roaring::roaring) + add_library(roaring::roaring INTERFACE IMPORTED) + target_link_libraries(roaring::roaring INTERFACE roaring) + target_include_directories(roaring::roaring INTERFACE ${croaring_BINARY_DIR} + ${croaring_SOURCE_DIR}/cpp) + endif() + + set(CROARING_VENDORED TRUE) + set_target_properties(roaring PROPERTIES OUTPUT_NAME "iceberg_vendored_croaring" + POSITION_INDEPENDENT_CODE ON) + install(TARGETS roaring + EXPORT iceberg_targets + RUNTIME DESTINATION "${ICEBERG_INSTALL_BINDIR}" + ARCHIVE DESTINATION "${ICEBERG_INSTALL_LIBDIR}" + LIBRARY DESTINATION "${ICEBERG_INSTALL_LIBDIR}") + else() + set(CROARING_VENDORED FALSE) + list(APPEND ICEBERG_SYSTEM_DEPENDENCIES roaring) + endif() + + set(ICEBERG_SYSTEM_DEPENDENCIES + ${ICEBERG_SYSTEM_DEPENDENCIES} + PARENT_SCOPE) + set(CROARING_VENDORED + ${CROARING_VENDORED} + PARENT_SCOPE) +endfunction() + # ---------------------------------------------------------------------- # nlohmann-json @@ -398,6 +446,7 @@ endfunction() resolve_zlib_dependency() resolve_nanoarrow_dependency() +resolve_croaring_dependency() resolve_nlohmann_json_dependency() resolve_spdlog_dependency() diff --git a/src/iceberg/CMakeLists.txt b/src/iceberg/CMakeLists.txt index b3ce7fa25..ee618b839 100644 --- a/src/iceberg/CMakeLists.txt +++ b/src/iceberg/CMakeLists.txt @@ -62,23 +62,27 @@ list(APPEND ICEBERG_STATIC_BUILD_INTERFACE_LIBS nanoarrow::nanoarrow_static nlohmann_json::nlohmann_json + roaring::roaring spdlog::spdlog ZLIB::ZLIB) list(APPEND ICEBERG_SHARED_BUILD_INTERFACE_LIBS nanoarrow::nanoarrow_shared nlohmann_json::nlohmann_json + roaring::roaring spdlog::spdlog ZLIB::ZLIB) list(APPEND ICEBERG_STATIC_INSTALL_INTERFACE_LIBS "$,Iceberg::nanoarrow_static,$,nanoarrow::nanoarrow_static,nanoarrow::nanoarrow_shared>>" "$,Iceberg::nlohmann_json,$,nlohmann_json::nlohmann_json,nlohmann_json::nlohmann_json>>" + "$,Iceberg::roaring,roaring::roaring>" "$,Iceberg::spdlog,spdlog::spdlog>") list(APPEND ICEBERG_SHARED_INSTALL_INTERFACE_LIBS "$,Iceberg::nanoarrow_shared,$,nanoarrow::nanoarrow_shared,nanoarrow::nanoarrow_static>>" "$,Iceberg::nlohmann_json,$,nlohmann_json::nlohmann_json,nlohmann_json::nlohmann_json>>" + "$,Iceberg::roaring,roaring::roaring>" "$,Iceberg::spdlog,spdlog::spdlog>") add_iceberg_lib(iceberg diff --git a/src/iceberg/IcebergConfig.cmake.in b/src/iceberg/IcebergConfig.cmake.in index 8a9b9f3f3..c22682d36 100644 --- a/src/iceberg/IcebergConfig.cmake.in +++ b/src/iceberg/IcebergConfig.cmake.in @@ -70,6 +70,15 @@ endmacro() # Find system dependencies iceberg_find_dependencies("${ICEBERG_SYSTEM_DEPENDENCIES}") +# Create missing CRoaring targets if they don't exist +if(NOT TARGET roaring::roaring-headers) + add_library(roaring::roaring-headers INTERFACE IMPORTED) +endif() + +if(NOT TARGET roaring::roaring-headers-cpp) + add_library(roaring::roaring-headers-cpp INTERFACE IMPORTED) +endif() + include("${CMAKE_CURRENT_LIST_DIR}/IcebergTargets.cmake") if(TARGET Iceberg::arrow_static) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index f8926eb70..0f6003757 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -92,6 +92,8 @@ add_iceberg_test(util_test string_util_test.cc visit_type_test.cc) +add_iceberg_test(roaring_test SOURCES roaring_test.cc) + if(ICEBERG_BUILD_BUNDLE) add_iceberg_test(avro_test USE_BUNDLE diff --git a/test/roaring_test.cc b/test/roaring_test.cc new file mode 100644 index 000000000..3c9e4d7a5 --- /dev/null +++ b/test/roaring_test.cc @@ -0,0 +1,60 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#include "roaring/roaring.hh" + +#include + +#include "roaring/roaring64map.hh" + +namespace iceberg { + +TEST(CRoaringTest, Basic32Bit) { + roaring::Roaring r1; + for (uint32_t i = 100; i < 1000; i++) { + r1.add(i); + } + ASSERT_EQ(r1.cardinality(), 900); + ASSERT_TRUE(r1.contains(500)); + ASSERT_FALSE(r1.contains(50)); + ASSERT_FALSE(r1.isEmpty()); +} + +TEST(CRoaringTest, Basic64Bit) { + roaring::Roaring64Map r2; + for (uint64_t i = 18000000000000000100ull; i < 18000000000000001000ull; i++) { + r2.add(i); + } + ASSERT_EQ(r2.cardinality(), 900); + ASSERT_TRUE(r2.contains(static_cast(18000000000000000500ull))); + ASSERT_FALSE(r2.contains(static_cast(18000000000000000050ull))); + ASSERT_FALSE(r2.isEmpty()); +} + +TEST(CRoaringTest, ConstructorWithInitializerList) { + roaring::Roaring r1 = roaring::Roaring::bitmapOf(5, 1, 2, 3, 5, 6); + ASSERT_EQ(r1.cardinality(), 5); + ASSERT_TRUE(r1.contains(1)); + ASSERT_TRUE(r1.contains(2)); + ASSERT_TRUE(r1.contains(3)); + ASSERT_TRUE(r1.contains(5)); + ASSERT_TRUE(r1.contains(6)); + ASSERT_FALSE(r1.contains(4)); +} + +} // namespace iceberg