This is an automated email from the ASF dual-hosted git repository.

Mryange pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/doris.git


The following commit(s) were added to refs/heads/master by this push:
     new 61179b65580 [feature](function) Add H3 cell and coordinate functions 
(#69018)
61179b65580 is described below

commit 61179b655805b6ec150cbf7ef50144f8eb6f3ad6
Author: Mryange <[email protected]>
AuthorDate: Mon Oct 19 19:32:54 2026 +0800

    [feature](function) Add H3 cell and coordinate functions (#69018)
    
    ### What problem does this PR solve?
    
    Issue Number: N/A
    
    Problem Summary: Add `h3_lat_lng_to_cell`, `h3_cell_to_lat_lng`, and
    `h3_cell_to_boundary` using official H3 4.5.0. Coordinates use degrees
    in latitude/longitude order. Invalid inputs return NULL; centers contain
    two coordinates and boundaries preserve H3 vertex order without closing
    the ring. Input NULL propagation uses the default execution framework.
    FE has no separate Java H3 evaluator; constant folding through BE
    remains supported.
    
    Build H3 as a static C library from its 18 upstream core sources.
    Generate its versioned API header in the build directory, export include
    paths through the target, enable PIC, and inherit Doris sanitizer flags.
    Only the H3 target relaxes third-party warning errors. The wrapper
    avoids upstream standalone tools and global build options. Include the
    upstream license attribution and NOTICE.
    
    ### Release note
    
    Add three H3 SQL functions for mapping coordinates to cells and
    retrieving cell centers and boundaries.
    
    ### Check List (For Author)
    
    - Test
        - [x] Regression test
        - [x] Unit Test
        - [x] Manual test (add detailed scripts or steps below)
        - [ ] No need to test or manual test. Explain why:
    - Behavior changed:
        - [ ] No.
        - [x] Yes. Add three SQL functions.
    - Does this need documentation?
        - [ ] No.
    - [x] Yes. SQL function documentation is needed; no documentation PR
    yet.
    
    Validation on Linux x86_64:
    - ASAN BE build and clean FE build passed; H3 objects carry ASAN/UBSAN
    flags.
    - `run-be-ut.sh --run --filter=FunctionH3Test.* -j48`: all three tests
    passed.
    - `run-regression-test.sh --run -d
    query_p0/sql_functions/spatial_functions -s test_h3`: generated results
    with `-forceGenOut`, inspected them, and reran successfully. Includes
    constant-folding modes, nullable/non-nullable table columns, all 16
    resolutions, stored nested arrays, array expansion, filtering/grouping,
    and 35,000 mixed rows.
    - Compared 10,000 inputs per function against official C/Python H3
    4.5.0: exact agreement. ClickHouse 26.3.9.8 (H3 3.7.1) matched cell IDs
    and coordinates within tolerance (maximum coordinate error 8.29e-8
    degrees).
    - Clang-format 16 and targeted clang-tidy checks passed; no sanitizer
    diagnostics during these tests. ARM/macOS builds were not run.
    
    ### Check List (For Reviewer who merge this PR)
    
    - [ ] Confirm the release note
    - [ ] Confirm test cases
    - [ ] Confirm document
    - [ ] Add branch pick label
---
 .gitmodules                                        |   3 +
 LICENSE.txt                                        |   1 +
 NOTICE.txt                                         |  19 ++
 be/CMakeLists.txt                                  |   3 +
 be/src/exprs/CMakeLists.txt                        |   4 +-
 be/src/exprs/function/geo/functions_geo.cpp        |   3 +
 be/src/exprs/function/geo/functions_h3.cpp         | 145 +++++++++
 be/test/exprs/function/function_h3_test.cpp        | 164 ++++++++++
 build.sh                                           |   1 +
 contrib/h3                                         |   1 +
 contrib/h3-cmake/CMakeLists.txt                    |  67 ++++
 .../doris/catalog/BuiltinScalarFunctions.java      |   6 +
 .../functions/scalar/H3CellToBoundary.java         |  68 ++++
 .../functions/scalar/H3CellToLatLng.java           |  68 ++++
 .../functions/scalar/H3LatLngToCell.java           |  68 ++++
 .../expressions/visitor/ScalarFunctionVisitor.java |  15 +
 .../sql_functions/spatial_functions/test_h3.out    | 342 +++++++++++++++++++++
 .../sql_functions/spatial_functions/test_h3.groovy | 188 +++++++++++
 run-be-ut.sh                                       |   4 +-
 19 files changed, 1167 insertions(+), 3 deletions(-)

diff --git a/.gitmodules b/.gitmodules
index d4e96b80914..8969d2dba3f 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -32,6 +32,9 @@
 [submodule "contrib/datasketches-cpp"]
        path = contrib/datasketches-cpp
        url = https://github.com/apache/datasketches-cpp.git
+[submodule "contrib/h3"]
+       path = contrib/h3
+       url = https://github.com/uber/h3.git
 [submodule "doris-skills"]
        path = doris-skills
        url = https://github.com/apache/doris-skills
diff --git a/LICENSE.txt b/LICENSE.txt
index df1f548b6ae..b54c0b65503 100644
--- a/LICENSE.txt
+++ b/LICENSE.txt
@@ -207,6 +207,7 @@ The text of each license is the standard Apache 2.0 license.
 
 software.amazon.awssdk.core.client.builder.SdkDefaultClientBuilder from AWS 
SDK v2 (sdk-core 2.29.52)
 org.apache.hadoop.fs.FileSystem from Apache Hadoop (hadoop-common 3.4.2)
+H3 4.5.0 (contrib/h3) from https://github.com/uber/h3
 
 
--------------------------------------------------------------------------------
 
diff --git a/NOTICE.txt b/NOTICE.txt
index c1ad754dc72..1cf02043409 100644
--- a/NOTICE.txt
+++ b/NOTICE.txt
@@ -85,3 +85,22 @@ The licenses for these third party components are included 
in LICENSE.txt
   
   This product includes software developed at
   The Apache Software Foundation (https://www.apache.org/).    
+
+--------------------------------------------------------------------------------
+
+This product includes H3 (https://github.com/uber/h3), which includes the
+following in its NOTICE file:
+
+Copyright 2017-2021 Uber Technologies, Inc.
+
+Licensed 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.
diff --git a/be/CMakeLists.txt b/be/CMakeLists.txt
index 8a36b1f8ac0..13f6ebe986c 100644
--- a/be/CMakeLists.txt
+++ b/be/CMakeLists.txt
@@ -605,6 +605,8 @@ set(CMAKE_CXX_FLAGS "${CXX_COMMON_FLAGS} ${CMAKE_CXX_FLAGS} 
${EXTRA_CXX_FLAGS}")
 
 set(CMAKE_C_FLAGS ${CMAKE_CXX_FLAGS})
 
+add_subdirectory(${CONTRIB_PATH}/h3-cmake ${PROJECT_BINARY_DIR}/h3)
+
 # Set include dirs
 include_directories(
     ${CONTRIB_PATH}/apache-orc/c++/include
@@ -768,6 +770,7 @@ set(DORIS_DEPENDENCIES ${DORIS_DEPENDENCIES} ic)
 set(DORIS_DEPENDENCIES ${DORIS_DEPENDENCIES} clucene-core-static)
 set(DORIS_DEPENDENCIES ${DORIS_DEPENDENCIES} clucene-shared-static)
 set(DORIS_DEPENDENCIES ${DORIS_DEPENDENCIES} clucene-contribs-lib)
+set(DORIS_DEPENDENCIES ${DORIS_DEPENDENCIES} h3)
 
 set(DORIS_DEPENDENCIES ${DORIS_DEPENDENCIES} ${WL_END_GROUP})
 
diff --git a/be/src/exprs/CMakeLists.txt b/be/src/exprs/CMakeLists.txt
index 1940ba6d8e4..3965155e4a6 100644
--- a/be/src/exprs/CMakeLists.txt
+++ b/be/src/exprs/CMakeLists.txt
@@ -33,7 +33,7 @@ add_library(Exprs STATIC ${SRC_FILES})
 # function_array_distance uses faiss headers (platform_macros.h, distances.h),
 # which are exported by ann_index via PUBLIC linkage with faiss.
 target_link_libraries(Exprs
-    PRIVATE ann_index
+    PRIVATE ann_index h3
     PUBLIC DataSketches::HLL)
 
 pch_reuse(Exprs)
@@ -122,4 +122,4 @@ set(WARNING_OPTION "-Wno-unused-but-set-variable")
 check_cxx_compiler_flag(${WARNING_OPTION} HAS_WARNING_OPTION)
 if (HAS_WARNING_OPTION)
     target_compile_options(Exprs PRIVATE ${WARNING_OPTION} 
"-Wno-unused-macros")
-endif()
\ No newline at end of file
+endif()
diff --git a/be/src/exprs/function/geo/functions_geo.cpp 
b/be/src/exprs/function/geo/functions_geo.cpp
index 8f53b884eb9..05e59749b1e 100644
--- a/be/src/exprs/function/geo/functions_geo.cpp
+++ b/be/src/exprs/function/geo/functions_geo.cpp
@@ -1124,7 +1124,10 @@ struct StNumPoints {
     }
 };
 
+void register_function_h3(SimpleFunctionFactory& factory);
+
 void register_function_geo(SimpleFunctionFactory& factory) {
+    register_function_h3(factory);
     factory.register_function<GeoFunction<StPoint>>();
     factory.register_function<GeoFunction<StAsText<StAsWktName>>>();
     factory.register_function<GeoFunction<StAsText<StAsTextName>>>();
diff --git a/be/src/exprs/function/geo/functions_h3.cpp 
b/be/src/exprs/function/geo/functions_h3.cpp
new file mode 100644
index 00000000000..1a381f5c642
--- /dev/null
+++ b/be/src/exprs/function/geo/functions_h3.cpp
@@ -0,0 +1,145 @@
+// 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 <h3api.h>
+
+#include <cmath>
+
+#include "core/block/block.h"
+#include "core/column/column_array.h"
+#include "core/column/column_execute_util.h"
+#include "core/column/column_nullable.h"
+#include "core/data_type/data_type_array.h"
+#include "core/data_type/data_type_nullable.h"
+#include "core/data_type/data_type_number.h"
+#include "exprs/function/simple_function_factory.h"
+
+namespace doris {
+
+class FunctionH3LatLngToCell : public IFunction {
+public:
+    static constexpr auto name = "h3_lat_lng_to_cell";
+    static FunctionPtr create() { return 
std::make_shared<FunctionH3LatLngToCell>(); }
+    String get_name() const override { return name; }
+    size_t get_number_of_arguments() const override { return 3; }
+
+    DataTypePtr get_return_type_impl(const DataTypes&) const override {
+        return make_nullable(std::make_shared<DataTypeInt64>());
+    }
+
+    Status execute_impl(FunctionContext*, Block& block, const ColumnNumbers& 
arguments,
+                        uint32_t result, size_t rows) const override {
+        auto lat = 
ColumnView<TYPE_DOUBLE>::create(block.get_by_position(arguments[0]).column);
+        auto lng = 
ColumnView<TYPE_DOUBLE>::create(block.get_by_position(arguments[1]).column);
+        auto resolution = 
ColumnView<TYPE_INT>::create(block.get_by_position(arguments[2]).column);
+        auto values = ColumnInt64::create(rows, 0);
+        auto nulls = ColumnUInt8::create(rows, 0);
+        for (size_t row = 0; row < rows; ++row) {
+            const double latitude = lat.value_at(row);
+            const double longitude = lng.value_at(row);
+            const int res = resolution.value_at(row);
+            if (!std::isfinite(latitude) || !std::isfinite(longitude) || 
latitude < -90 ||
+                latitude > 90 || longitude < -180 || longitude > 180 || res < 
0 || res > 15) {
+                nulls->get_data()[row] = 1;
+                continue;
+            }
+            const LatLng coord {degsToRads(latitude), degsToRads(longitude)};
+            H3Index cell = 0;
+            if (latLngToCell(&coord, res, &cell) != E_SUCCESS) {
+                nulls->get_data()[row] = 1;
+                continue;
+            }
+            values->get_data()[row] = static_cast<Int64>(cell);
+        }
+        block.replace_by_position(result,
+                                  ColumnNullable::create(std::move(values), 
std::move(nulls)));
+        return Status::OK();
+    }
+};
+
+template <bool boundary>
+class FunctionH3CellToCoordinates : public IFunction {
+public:
+    static constexpr auto name = boundary ? "h3_cell_to_boundary" : 
"h3_cell_to_lat_lng";
+    static FunctionPtr create() { return 
std::make_shared<FunctionH3CellToCoordinates>(); }
+    String get_name() const override { return name; }
+    size_t get_number_of_arguments() const override { return 1; }
+
+    DataTypePtr get_return_type_impl(const DataTypes&) const override {
+        DataTypePtr type =
+                
std::make_shared<DataTypeArray>(make_nullable(std::make_shared<DataTypeFloat64>()));
+        if constexpr (boundary) {
+            type = std::make_shared<DataTypeArray>(make_nullable(type));
+        }
+        return make_nullable(type);
+    }
+
+    Status execute_impl(FunctionContext*, Block& block, const ColumnNumbers& 
arguments,
+                        uint32_t result, size_t rows) const override {
+        auto cells = 
ColumnView<TYPE_BIGINT>::create(block.get_by_position(arguments[0]).column);
+        auto values = ColumnFloat64::create();
+        auto point_offsets = ColumnArray::ColumnOffsets::create();
+        auto row_offsets = ColumnArray::ColumnOffsets::create();
+        auto nulls = ColumnUInt8::create(rows, 0);
+        row_offsets->reserve(rows);
+        if constexpr (!boundary) {
+            values->reserve(2 * rows);
+        }
+        for (size_t row = 0; row < rows; ++row) {
+            CellBoundary coords {};
+            const auto cell = cells.value_at(row);
+            bool valid = cell > 0 && isValidCell(static_cast<H3Index>(cell));
+            if (valid) {
+                if constexpr (boundary) {
+                    valid = cellToBoundary(cell, &coords) == E_SUCCESS;
+                } else {
+                    valid = cellToLatLng(cell, &coords.verts[0]) == E_SUCCESS;
+                    coords.numVerts = 1;
+                }
+            }
+            if (!valid) {
+                nulls->get_data()[row] = 1;
+            } else {
+                for (int vertex = 0; vertex < coords.numVerts; ++vertex) {
+                    
values->get_data().push_back(radsToDegs(coords.verts[vertex].lat));
+                    
values->get_data().push_back(radsToDegs(coords.verts[vertex].lng));
+                    if constexpr (boundary) {
+                        point_offsets->get_data().push_back(values->size());
+                    }
+                }
+            }
+            row_offsets->get_data().push_back(boundary ? point_offsets->size() 
: values->size());
+        }
+        auto element_nulls = ColumnUInt8::create(values->size(), 0);
+        ColumnPtr data = ColumnNullable::create(std::move(values), 
std::move(element_nulls));
+        if constexpr (boundary) {
+            data = ColumnArray::create(data, std::move(point_offsets));
+            data = ColumnNullable::create(data, 
ColumnUInt8::create(data->size(), 0));
+        }
+        data = ColumnArray::create(data, std::move(row_offsets));
+        block.replace_by_position(result, ColumnNullable::create(data, 
std::move(nulls)));
+        return Status::OK();
+    }
+};
+
+void register_function_h3(SimpleFunctionFactory& factory) {
+    factory.register_function<FunctionH3LatLngToCell>();
+    factory.register_function<FunctionH3CellToCoordinates<false>>();
+    factory.register_function<FunctionH3CellToCoordinates<true>>();
+}
+
+} // namespace doris
diff --git a/be/test/exprs/function/function_h3_test.cpp 
b/be/test/exprs/function/function_h3_test.cpp
new file mode 100644
index 00000000000..3c3ed851df0
--- /dev/null
+++ b/be/test/exprs/function/function_h3_test.cpp
@@ -0,0 +1,164 @@
+// 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 <limits>
+
+#include "core/column/column_const.h"
+#include "core/data_type/data_type_array.h"
+#include "core/data_type/data_type_nothing.h"
+#include "core/data_type/data_type_number.h"
+#include "exprs/function/function_test_util.h"
+
+namespace doris {
+using namespace ut_type;
+
+TEST(FunctionH3Test, LatLngToCell) {
+    const InputTypeSet types = {TYPE_DOUBLE, TYPE_DOUBLE, TYPE_INT};
+    const DataSet cases = {{{55.71290588, 37.79506683, int32_t(15)}, 
int64_t(644325524701193974)},
+                           {{91.0, 0.0, int32_t(9)}, Null()},
+                           {{-91.0, 0.0, int32_t(9)}, Null()},
+                           {{0.0, 181.0, int32_t(9)}, Null()},
+                           {{0.0, -181.0, int32_t(9)}, Null()},
+                           {{0.0, 0.0, int32_t(-1)}, Null()},
+                           {{0.0, 0.0, int32_t(16)}, Null()},
+                           {{std::numeric_limits<double>::quiet_NaN(), 0.0, 
int32_t(9)}, Null()},
+                           {{0.0, std::numeric_limits<double>::quiet_NaN(), 
int32_t(9)}, Null()},
+                           {{0.0, std::numeric_limits<double>::infinity(), 
int32_t(9)}, Null()},
+                           {{-std::numeric_limits<double>::infinity(), 0.0, 
int32_t(9)}, Null()},
+                           {{Null(), 0.0, int32_t(9)}, Null()},
+                           {{0.0, Null(), int32_t(9)}, Null()},
+                           {{0.0, 0.0, Null()}, Null()}};
+    check_function_all_arg_comb<DataTypeInt64, true>("h3_lat_lng_to_cell", 
types, cases);
+}
+
+// GTest assertion macros dominate the reported complexity of these checks.
+// NOLINTBEGIN(readability-function-cognitive-complexity)
+TEST(FunctionH3Test, OnlyNullLatLngToCell) {
+    const size_t rows = 7;
+    for (size_t null_argument = 0; null_argument < 3; ++null_argument) {
+        DataTypes types = {std::make_shared<DataTypeFloat64>(), 
std::make_shared<DataTypeFloat64>(),
+                           std::make_shared<DataTypeInt32>()};
+        types[null_argument] = 
make_nullable(std::make_shared<DataTypeNothing>());
+        Block block;
+        for (const auto& type : types) {
+            block.insert({type->create_column_const_with_default_value(rows), 
type, "argument"});
+        }
+        auto result_type = make_nullable(std::make_shared<DataTypeInt64>());
+        auto function = SimpleFunctionFactory::instance().get_function(
+                "h3_lat_lng_to_cell", block.get_columns_with_type_and_name(), 
result_type);
+        ASSERT_NE(function, nullptr);
+        FunctionUtils utils(result_type, types, false);
+        auto* context = utils.get_fn_ctx();
+        ASSERT_TRUE(function->open(context, 
FunctionContext::FRAGMENT_LOCAL).ok());
+        ASSERT_TRUE(function->open(context, 
FunctionContext::THREAD_LOCAL).ok());
+        block.insert({nullptr, result_type, "result"});
+        ASSERT_TRUE(function->execute(context, block, {0, 1, 2}, 3, 
rows).ok());
+        EXPECT_EQ(block.get_by_position(3).column->size(), rows);
+        EXPECT_TRUE(block.get_by_position(3).column->only_null());
+        EXPECT_TRUE(function->close(context, 
FunctionContext::THREAD_LOCAL).ok());
+        EXPECT_TRUE(function->close(context, 
FunctionContext::FRAGMENT_LOCAL).ok());
+    }
+}
+
+static void check_coordinates(bool boundary, bool constant, bool only_null, 
size_t rows) {
+    DataTypePtr input_type =
+            make_nullable(only_null ? 
DataTypePtr(std::make_shared<DataTypeNothing>())
+                                    : 
DataTypePtr(std::make_shared<DataTypeInt64>()));
+    DataTypePtr output_type =
+            
std::make_shared<DataTypeArray>(make_nullable(std::make_shared<DataTypeFloat64>()));
+    if (boundary) {
+        output_type = 
std::make_shared<DataTypeArray>(make_nullable(output_type));
+    }
+    output_type = make_nullable(output_type);
+    auto input = input_type->create_column();
+    const Int64 cells[] = {644325524701193974, 0, 581109487465660415, -1, 
576636674163867647};
+    for (size_t i = 0; i < (constant ? 1 : rows); ++i) {
+        if (only_null || i % 6 == 5) {
+            input->insert(Field());
+        } else {
+            input->insert(Field::create_field<TYPE_BIGINT>(cells[i % 6]));
+        }
+    }
+    if (constant) {
+        input = ColumnConst::create(std::move(input), rows);
+    }
+    Block block;
+    block.insert({std::move(input), input_type, "cell"});
+    auto function = SimpleFunctionFactory::instance().get_function(
+            boundary ? "h3_cell_to_boundary" : "h3_cell_to_lat_lng",
+            block.get_columns_with_type_and_name(), output_type);
+    ASSERT_NE(function, nullptr);
+    FunctionUtils utils(output_type, {input_type}, false);
+    auto* context = utils.get_fn_ctx();
+    std::vector<std::shared_ptr<ColumnPtrWrapper>> constants(1);
+    if (constant) {
+        constants[0] = 
std::make_shared<ColumnPtrWrapper>(block.get_by_position(0).column);
+    }
+    context->set_constant_cols(constants);
+    ASSERT_TRUE(function->open(context, FunctionContext::FRAGMENT_LOCAL).ok());
+    ASSERT_TRUE(function->open(context, FunctionContext::THREAD_LOCAL).ok());
+    block.insert({nullptr, output_type, "result"});
+    ASSERT_TRUE(function->execute(context, block, {0}, 1, rows).ok());
+    auto result = 
block.get_by_position(1).column->convert_to_full_column_if_const();
+    ASSERT_EQ(result->size(), rows);
+    for (size_t i = 0; i < rows; ++i) {
+        Field value;
+        result->get(i, value);
+        const auto index = constant ? 0 : i % 6;
+        if (only_null || index == 1 || index == 3 || index == 5) {
+            EXPECT_TRUE(value.is_null());
+            continue;
+        }
+        ASSERT_FALSE(value.is_null());
+        const auto& array = value.get<TYPE_ARRAY>();
+        ASSERT_EQ(array.size(), boundary ? (index == 2 ? 10 : index == 4 ? 5 : 
6) : 2);
+        if (index == 0) {
+            if (boundary) {
+                const double expected[][2] = {{55.712900225355526, 
37.79505811173474},
+                                              {55.71289713485416, 
37.79506506997184},
+                                              {55.712899340954856, 
37.79507312653982},
+                                              {55.71290463755745, 
37.79507422487167},
+                                              {55.71290772805917, 
37.79506726663346},
+                                              {55.712905521957914, 
37.795059210064515}};
+                for (size_t vertex = 0; vertex < array.size(); ++vertex) {
+                    const auto& point = array[vertex].get<TYPE_ARRAY>();
+                    ASSERT_EQ(point.size(), 2);
+                    EXPECT_NEAR(point[0].get<TYPE_DOUBLE>(), 
expected[vertex][0], 1e-10);
+                    EXPECT_NEAR(point[1].get<TYPE_DOUBLE>(), 
expected[vertex][1], 1e-10);
+                }
+            } else {
+                EXPECT_NEAR(array[0].get<TYPE_DOUBLE>(), 55.71290243145668, 
1e-10);
+                EXPECT_NEAR(array[1].get<TYPE_DOUBLE>(), 37.795066168302505, 
1e-10);
+            }
+        }
+    }
+    EXPECT_TRUE(function->close(context, FunctionContext::THREAD_LOCAL).ok());
+    EXPECT_TRUE(function->close(context, 
FunctionContext::FRAGMENT_LOCAL).ok());
+}
+// NOLINTEND(readability-function-cognitive-complexity)
+
+TEST(FunctionH3Test, ReverseCoordinates) {
+    for (bool boundary : {false, true}) {
+        check_coordinates(boundary, false, false, 8193);
+        check_coordinates(boundary, true, false, 7);
+        check_coordinates(boundary, true, true, 7);
+        check_coordinates(boundary, false, true, 7);
+        check_coordinates(boundary, false, false, 0);
+    }
+}
+
+} // namespace doris
diff --git a/build.sh b/build.sh
index a33f55c294e..6a5044fdf62 100755
--- a/build.sh
+++ b/build.sh
@@ -958,6 +958,7 @@ if [[ "${BUILD_BE}" -eq 1 ]]; then
     update_submodule "contrib/clucene" "clucene" 
"https://github.com/apache/doris-thirdparty/archive/refs/heads/clucene.tar.gz";
     update_submodule "contrib/openblas" "openblas" 
"https://github.com/apache/doris-thirdparty/archive/refs/heads/openblas.tar.gz";
     update_submodule "contrib/faiss" "faiss" 
"https://github.com/apache/doris-thirdparty/archive/refs/heads/faiss.tar.gz";
+    update_submodule "contrib/h3" "h3" 
"https://github.com/uber/h3/archive/refs/tags/v4.5.0.tar.gz";
     if [[ "${COMPILE_BENCH}" -eq 1 ]]; then
         compile_bench_phase_end
     fi
diff --git a/contrib/h3 b/contrib/h3
new file mode 160000
index 00000000000..1b536c34225
--- /dev/null
+++ b/contrib/h3
@@ -0,0 +1 @@
+Subproject commit 1b536c34225191ba24a75a840f634d4a48c3b206
diff --git a/contrib/h3-cmake/CMakeLists.txt b/contrib/h3-cmake/CMakeLists.txt
new file mode 100644
index 00000000000..41bb3efa4c0
--- /dev/null
+++ b/contrib/h3-cmake/CMakeLists.txt
@@ -0,0 +1,67 @@
+# 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.
+
+set(H3_SOURCE_DIR "${CONTRIB_PATH}/h3")
+set(H3_BINARY_DIR "${PROJECT_BINARY_DIR}/h3")
+
+file(STRINGS "${H3_SOURCE_DIR}/VERSION" H3_VERSION LIMIT_COUNT 1)
+string(REPLACE "." ";" H3_VERSION_PARTS "${H3_VERSION}")
+list(GET H3_VERSION_PARTS 0 H3_VERSION_MAJOR)
+list(GET H3_VERSION_PARTS 1 H3_VERSION_MINOR)
+list(GET H3_VERSION_PARTS 2 H3_VERSION_PATCH)
+
+set(H3_SOURCES
+    ${H3_SOURCE_DIR}/src/h3lib/lib/algos.c
+    ${H3_SOURCE_DIR}/src/h3lib/lib/area.c
+    ${H3_SOURCE_DIR}/src/h3lib/lib/baseCells.c
+    ${H3_SOURCE_DIR}/src/h3lib/lib/bbox.c
+    ${H3_SOURCE_DIR}/src/h3lib/lib/cellsToMultiPoly.c
+    ${H3_SOURCE_DIR}/src/h3lib/lib/directedEdge.c
+    ${H3_SOURCE_DIR}/src/h3lib/lib/faceijk.c
+    ${H3_SOURCE_DIR}/src/h3lib/lib/h3Assert.c
+    ${H3_SOURCE_DIR}/src/h3lib/lib/h3Index.c
+    ${H3_SOURCE_DIR}/src/h3lib/lib/iterators.c
+    ${H3_SOURCE_DIR}/src/h3lib/lib/latLng.c
+    ${H3_SOURCE_DIR}/src/h3lib/lib/linkedGeo.c
+    ${H3_SOURCE_DIR}/src/h3lib/lib/localij.c
+    ${H3_SOURCE_DIR}/src/h3lib/lib/mathExtensions.c
+    ${H3_SOURCE_DIR}/src/h3lib/lib/polygon.c
+    ${H3_SOURCE_DIR}/src/h3lib/lib/polyfill.c
+    ${H3_SOURCE_DIR}/src/h3lib/lib/vec2d.c
+    ${H3_SOURCE_DIR}/src/h3lib/lib/vertex.c)
+
+file(MAKE_DIRECTORY "${H3_BINARY_DIR}/include")
+configure_file(
+    ${H3_SOURCE_DIR}/src/h3lib/include/h3api.h.in
+    ${H3_BINARY_DIR}/include/h3api.h)
+
+add_library(h3 STATIC ${H3_SOURCES})
+set_target_properties(h3 PROPERTIES POSITION_INDEPENDENT_CODE ON)
+target_compile_features(h3 PUBLIC c_std_99)
+# Keep upstream warnings visible without imposing Doris warning policy.
+target_compile_options(h3 PRIVATE -Wno-error)
+# Upstream uses empty initializers as a C extension before C23.
+if(CMAKE_C_COMPILER_ID MATCHES "Clang")
+    target_compile_options(h3 PRIVATE -Wno-c23-extensions)
+endif()
+target_compile_definitions(h3 PRIVATE BUILDING_H3=1)
+target_include_directories(
+    h3
+    SYSTEM PUBLIC
+        $<BUILD_INTERFACE:${H3_SOURCE_DIR}/src/h3lib/include>
+        $<BUILD_INTERFACE:${H3_BINARY_DIR}/include>)
+target_link_libraries(h3 PUBLIC m)
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/catalog/BuiltinScalarFunctions.java 
b/fe/fe-core/src/main/java/org/apache/doris/catalog/BuiltinScalarFunctions.java
index be0802713db..7f0140e8303 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/catalog/BuiltinScalarFunctions.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/catalog/BuiltinScalarFunctions.java
@@ -239,6 +239,9 @@ import 
org.apache.doris.nereids.trees.expressions.functions.scalar.GetVariantTyp
 import org.apache.doris.nereids.trees.expressions.functions.scalar.Greatest;
 import org.apache.doris.nereids.trees.expressions.functions.scalar.Grouping;
 import org.apache.doris.nereids.trees.expressions.functions.scalar.GroupingId;
+import 
org.apache.doris.nereids.trees.expressions.functions.scalar.H3CellToBoundary;
+import 
org.apache.doris.nereids.trees.expressions.functions.scalar.H3CellToLatLng;
+import 
org.apache.doris.nereids.trees.expressions.functions.scalar.H3LatLngToCell;
 import 
org.apache.doris.nereids.trees.expressions.functions.scalar.HammingDistance;
 import org.apache.doris.nereids.trees.expressions.functions.scalar.Hex;
 import 
org.apache.doris.nereids.trees.expressions.functions.scalar.HllCardinality;
@@ -1130,6 +1133,9 @@ public class BuiltinScalarFunctions implements 
FunctionHelper {
             scalar(StLinefromtext.class, "st_linefromtext"),
             scalar(StLinestringfromtext.class, "st_linestringfromtext"),
             scalar(StPoint.class, "st_point"),
+            scalar(H3CellToBoundary.class, "h3_cell_to_boundary"),
+            scalar(H3CellToLatLng.class, "h3_cell_to_lat_lng"),
+            scalar(H3LatLngToCell.class, "h3_lat_lng_to_cell"),
             scalar(StPolyfromtext.class, "st_polyfromtext"),
             scalar(StPolygon.class, "st_polygon"),
             scalar(StPolygonfromtext.class, "st_polygonfromtext"),
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/H3CellToBoundary.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/H3CellToBoundary.java
new file mode 100644
index 00000000000..effc7619223
--- /dev/null
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/H3CellToBoundary.java
@@ -0,0 +1,68 @@
+// 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.
+
+package org.apache.doris.nereids.trees.expressions.functions.scalar;
+
+import org.apache.doris.catalog.FunctionSignature;
+import org.apache.doris.nereids.trees.expressions.Expression;
+import org.apache.doris.nereids.trees.expressions.functions.AlwaysNullable;
+import 
org.apache.doris.nereids.trees.expressions.functions.ExplicitlyCastableSignature;
+import 
org.apache.doris.nereids.trees.expressions.functions.PropagateNullLiteral;
+import org.apache.doris.nereids.trees.expressions.shape.UnaryExpression;
+import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor;
+import org.apache.doris.nereids.types.ArrayType;
+import org.apache.doris.nereids.types.BigIntType;
+import org.apache.doris.nereids.types.DoubleType;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
+
+import java.util.List;
+
+/** H3 scalar function 'h3_cell_to_boundary'. */
+public class H3CellToBoundary extends ScalarFunction
+        implements UnaryExpression, ExplicitlyCastableSignature, 
AlwaysNullable, PropagateNullLiteral {
+
+    public static final List<FunctionSignature> SIGNATURES = ImmutableList.of(
+            
FunctionSignature.ret(ArrayType.of(ArrayType.of(DoubleType.INSTANCE)))
+                    .args(BigIntType.INSTANCE)
+    );
+
+    public H3CellToBoundary(Expression arg0) {
+        super("h3_cell_to_boundary", arg0);
+    }
+
+    private H3CellToBoundary(ScalarFunctionParams functionParams) {
+        super(functionParams);
+    }
+
+    @Override
+    public H3CellToBoundary withChildren(List<Expression> children) {
+        Preconditions.checkArgument(children.size() == 1);
+        return new H3CellToBoundary(getFunctionParams(children));
+    }
+
+    @Override
+    public List<FunctionSignature> getSignatures() {
+        return SIGNATURES;
+    }
+
+    @Override
+    public <R, C> R accept(ExpressionVisitor<R, C> visitor, C context) {
+        return visitor.visitH3CellToBoundary(this, context);
+    }
+}
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/H3CellToLatLng.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/H3CellToLatLng.java
new file mode 100644
index 00000000000..bc55fa3153c
--- /dev/null
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/H3CellToLatLng.java
@@ -0,0 +1,68 @@
+// 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.
+
+package org.apache.doris.nereids.trees.expressions.functions.scalar;
+
+import org.apache.doris.catalog.FunctionSignature;
+import org.apache.doris.nereids.trees.expressions.Expression;
+import org.apache.doris.nereids.trees.expressions.functions.AlwaysNullable;
+import 
org.apache.doris.nereids.trees.expressions.functions.ExplicitlyCastableSignature;
+import 
org.apache.doris.nereids.trees.expressions.functions.PropagateNullLiteral;
+import org.apache.doris.nereids.trees.expressions.shape.UnaryExpression;
+import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor;
+import org.apache.doris.nereids.types.ArrayType;
+import org.apache.doris.nereids.types.BigIntType;
+import org.apache.doris.nereids.types.DoubleType;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
+
+import java.util.List;
+
+/** H3 scalar function 'h3_cell_to_lat_lng'. */
+public class H3CellToLatLng extends ScalarFunction
+        implements UnaryExpression, ExplicitlyCastableSignature, 
AlwaysNullable, PropagateNullLiteral {
+
+    public static final List<FunctionSignature> SIGNATURES = ImmutableList.of(
+            FunctionSignature.ret(ArrayType.of(DoubleType.INSTANCE))
+                    .args(BigIntType.INSTANCE)
+    );
+
+    public H3CellToLatLng(Expression arg0) {
+        super("h3_cell_to_lat_lng", arg0);
+    }
+
+    private H3CellToLatLng(ScalarFunctionParams functionParams) {
+        super(functionParams);
+    }
+
+    @Override
+    public H3CellToLatLng withChildren(List<Expression> children) {
+        Preconditions.checkArgument(children.size() == 1);
+        return new H3CellToLatLng(getFunctionParams(children));
+    }
+
+    @Override
+    public List<FunctionSignature> getSignatures() {
+        return SIGNATURES;
+    }
+
+    @Override
+    public <R, C> R accept(ExpressionVisitor<R, C> visitor, C context) {
+        return visitor.visitH3CellToLatLng(this, context);
+    }
+}
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/H3LatLngToCell.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/H3LatLngToCell.java
new file mode 100644
index 00000000000..4867faa6bae
--- /dev/null
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/H3LatLngToCell.java
@@ -0,0 +1,68 @@
+// 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.
+
+package org.apache.doris.nereids.trees.expressions.functions.scalar;
+
+import org.apache.doris.catalog.FunctionSignature;
+import org.apache.doris.nereids.trees.expressions.Expression;
+import org.apache.doris.nereids.trees.expressions.functions.AlwaysNullable;
+import 
org.apache.doris.nereids.trees.expressions.functions.ExplicitlyCastableSignature;
+import 
org.apache.doris.nereids.trees.expressions.functions.PropagateNullLiteral;
+import org.apache.doris.nereids.trees.expressions.shape.TernaryExpression;
+import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor;
+import org.apache.doris.nereids.types.BigIntType;
+import org.apache.doris.nereids.types.DoubleType;
+import org.apache.doris.nereids.types.IntegerType;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
+
+import java.util.List;
+
+/** H3 scalar function 'h3_lat_lng_to_cell'. */
+public class H3LatLngToCell extends ScalarFunction
+        implements TernaryExpression, ExplicitlyCastableSignature, 
AlwaysNullable, PropagateNullLiteral {
+
+    public static final List<FunctionSignature> SIGNATURES = ImmutableList.of(
+            FunctionSignature.ret(BigIntType.INSTANCE)
+                    .args(DoubleType.INSTANCE, DoubleType.INSTANCE, 
IntegerType.INSTANCE)
+    );
+
+    public H3LatLngToCell(Expression arg0, Expression arg1, Expression arg2) {
+        super("h3_lat_lng_to_cell", arg0, arg1, arg2);
+    }
+
+    private H3LatLngToCell(ScalarFunctionParams functionParams) {
+        super(functionParams);
+    }
+
+    @Override
+    public H3LatLngToCell withChildren(List<Expression> children) {
+        Preconditions.checkArgument(children.size() == 3);
+        return new H3LatLngToCell(getFunctionParams(children));
+    }
+
+    @Override
+    public List<FunctionSignature> getSignatures() {
+        return SIGNATURES;
+    }
+
+    @Override
+    public <R, C> R accept(ExpressionVisitor<R, C> visitor, C context) {
+        return visitor.visitH3LatLngToCell(this, context);
+    }
+}
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/visitor/ScalarFunctionVisitor.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/visitor/ScalarFunctionVisitor.java
index 9d5e1b7485e..865669a0632 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/visitor/ScalarFunctionVisitor.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/visitor/ScalarFunctionVisitor.java
@@ -252,6 +252,9 @@ import 
org.apache.doris.nereids.trees.expressions.functions.scalar.Gcd;
 import org.apache.doris.nereids.trees.expressions.functions.scalar.GetFormat;
 import 
org.apache.doris.nereids.trees.expressions.functions.scalar.GetVariantType;
 import org.apache.doris.nereids.trees.expressions.functions.scalar.Greatest;
+import 
org.apache.doris.nereids.trees.expressions.functions.scalar.H3CellToBoundary;
+import 
org.apache.doris.nereids.trees.expressions.functions.scalar.H3CellToLatLng;
+import 
org.apache.doris.nereids.trees.expressions.functions.scalar.H3LatLngToCell;
 import 
org.apache.doris.nereids.trees.expressions.functions.scalar.HammingDistance;
 import org.apache.doris.nereids.trees.expressions.functions.scalar.Hex;
 import 
org.apache.doris.nereids.trees.expressions.functions.scalar.HllCardinality;
@@ -2519,6 +2522,18 @@ public interface ScalarFunctionVisitor<R, C> {
         return visitScalarFunction(stPoint, context);
     }
 
+    default R visitH3CellToBoundary(H3CellToBoundary function, C context) {
+        return visitScalarFunction(function, context);
+    }
+
+    default R visitH3CellToLatLng(H3CellToLatLng function, C context) {
+        return visitScalarFunction(function, context);
+    }
+
+    default R visitH3LatLngToCell(H3LatLngToCell function, C context) {
+        return visitScalarFunction(function, context);
+    }
+
     default R visitStPolyfromtext(StPolyfromtext stPolyfromtext, C context) {
         return visitScalarFunction(stPolyfromtext, context);
     }
diff --git 
a/regression-test/data/query_p0/sql_functions/spatial_functions/test_h3.out 
b/regression-test/data/query_p0/sql_functions/spatial_functions/test_h3.out
new file mode 100644
index 00000000000..7e93c2f9a47
--- /dev/null
+++ b/regression-test/data/query_p0/sql_functions/spatial_functions/test_h3.out
@@ -0,0 +1,342 @@
+-- This file is automatically generated. You should know what you did if you 
want to edit this
+-- !fold_cell --
+644325524701193974     644325524701193974
+
+-- !fold_coordinates --
+[55.712902431, 37.795066168]   [[55.712900225, 37.795058112], [55.712897135, 
37.79506507], [55.712899341, 37.795073127], [55.712904638, 37.795074225], 
[55.712907728, 37.795067267], [55.712905522, 37.79505921]]
+
+-- !fold_nested --
+644325524701193974     2       6
+
+-- !fold_null --
+\N     \N      \N      \N      \N      \N
+
+-- !fold_invalid --
+\N     \N      \N      \N      \N      \N
+
+-- !fold_endpoints --
+576495936675512319     648282192095284420      646243831017778096      
646243831017778096
+
+-- !fold_cell --
+644325524701193974     644325524701193974
+
+-- !fold_coordinates --
+[55.712902431, 37.795066168]   [[55.712900225, 37.795058112], [55.712897135, 
37.79506507], [55.712899341, 37.795073127], [55.712904638, 37.795074225], 
[55.712907728, 37.795067267], [55.712905522, 37.79505921]]
+
+-- !fold_nested --
+644325524701193974     2       6
+
+-- !fold_null --
+\N     \N      \N      \N      \N      \N
+
+-- !fold_invalid --
+\N     \N      \N      \N      \N      \N
+
+-- !fold_endpoints --
+576495936675512319     648282192095284420      646243831017778096      
646243831017778096
+
+-- !cell --
+644325524701193974
+
+-- !center --
+[55.712902431, 37.795066168]
+
+-- !boundary --
+[[55.712900225, 37.795058112], [55.712897135, 37.79506507], [55.712899341, 
37.795073127], [55.712904638, 37.795074225], [55.712907728, 37.795067267], 
[55.712905522, 37.79505921]]
+
+-- !invalid --
+\N     \N      \N      \N      \N      \N      \N
+
+-- !null --
+\N     \N      \N      \N      \N
+
+-- !non_cell --
+\N     \N      \N      \N      \N
+
+-- !pentagons --
+5      10      [[63.327061328, 4.012620898], [61.890838475, 8.644221198], 
[61.5405146, 11.080660058], [62.889968358, 15.771773841], [63.800792653, 
17.535446308], [66.327261733, 16.433696997], [67.351768675, 14.813658726], 
[67.468427885, 8.130261032], [67.015632628, 5.23925888], [64.525608422, 
3.69993326]]
+
+-- !rows --
+1      644325524701193974      [55.712902431, 37.795066168]    [[55.712900225, 
37.795058112], [55.712897135, 37.79506507], [55.712899341, 37.795073127], 
[55.712904638, 37.795074225], [55.712907728, 37.795067267], [55.712905522, 
37.79505921]]
+2      \N      \N      \N
+3      \N      \N      \N
+4      \N      \N      \N
+5      \N      \N      \N
+6      576495936675512319      [48.758349724, 18.303044481]    [[55.706768465, 
5.523646549], [45.18424869, 2.026568965], [37.523712366, 13.244313476], 
[39.643310548, 28.846868847], [49.779342868, 36.116723632], [58.40154487, 
25.082722327]]
+7      648282192095284420      [79.24239851, 38.023407008]     [[68.929957882, 
31.831280499], [69.39359649, 62.345344957], [76.16304283, 94.143090102], 
[87.364695323, 145.558197691], [81.27137179, -34.75841798], [73.310223685, 
0.325610352]]
+
+-- !mixed --
+1      617440756014514175      646165426115021650
+2      \N      619056821840379903
+3      \N      619056821840379903
+4      619056821840379903      \N
+5      619056821840379903      \N
+6      617048546304851967      578712552117108735
+7      621260594331254783      646243831017778096
+
+-- !array_access --
+1      2       55.712902431    37.795066168    \N      55.712900225    
37.795058112
+2      \N      \N      \N      \N      \N      \N
+3      \N      \N      \N      \N      \N      \N
+4      \N      \N      \N      \N      \N      \N
+5      \N      \N      \N      \N      \N      \N
+6      2       48.758349724    18.303044481    \N      55.706768465    
5.523646549
+7      2       79.24239851     38.023407008    \N      68.929957882    
31.831280499
+
+-- !null_columns --
+1      \N      \N      \N
+2      \N      \N      \N
+3      \N      \N      \N
+4      \N      \N      \N
+5      \N      \N      \N
+6      \N      \N      \N
+7      \N      \N      \N
+
+-- !empty --
+
+-- !roundtrip --
+644325524701193974
+
+-- !many_rows --
+10000  0       30000   10000
+
+-- !all_resolutions --
+0      0       578536630256664575      2       5       true
+1      0       576777411652222975      2       6       true
+10     1       581021526535438335      2       6       true
+100    12      632733032135666687      2       6       true
+101    12      632733032135666687      2       6       true
+102    12      631210968839402495      2       6       true
+103    12      633847439693631999      2       6       true
+104    13      637071220349785855      2       6       true
+105    13      635318325446452991      2       6       true
+106    13      635062944814269375      2       6       true
+107    13      639274992840543487      2       6       true
+108    13      637236631763037119      2       6       true
+109    13      637236631763037119      2       6       true
+11     1       585234855093075967      2       6       true
+110    13      635714568466772927      2       6       true
+111    13      638351039321002175      2       6       true
+112    14      641574819977156319      2       6       true
+113    14      639821925073823479      2       6       true
+114    14      639566544441639839      2       6       true
+115    14      643778592467913927      2       6       true
+116    14      641740231390407607      2       6       true
+117    14      641740231390407607      2       6       true
+118    14      640218168094143383      2       6       true
+119    14      642854638948372655      2       6       true
+12     1       583194161511923711      2       7       true
+120    15      646078419604526808      2       6       true
+121    15      644325524701193974      2       6       true
+122    15      644070144069010329      2       6       true
+123    15      648282192095284420      2       6       true
+124    15      646243831017778096      2       6       true
+125    15      646243831017778096      2       6       true
+126    15      644721767721513872      2       6       true
+127    15      647358238575743144      2       6       true
+13     1       583194161511923711      2       7       true
+14     1       581672437419081727      2       6       true
+15     1       584311265325744127      2       6       true
+16     2       587531734883500031      2       6       true
+17     2       585779113348825087      2       6       true
+18     2       585523476895367167      2       6       true
+19     2       589735705941377023      2       6       true
+2      0       576495936675512319      2       6       true
+20     2       587697211383480319      2       6       true
+21     2       587697211383480319      2       6       true
+22     2       586175487290638335      2       6       true
+23     2       588811566418231295      2       6       true
+24     3       592035265791393791      2       6       true
+25     3       590282369378811903      2       6       true
+26     3       590027007803260927      2       6       true
+27     3       594239030690840575      2       6       true
+28     3       592200673571897343      2       6       true
+29     3       592200673571897343      2       6       true
+3      0       580753245698260991      2       6       true
+30     3       590678605881671679      2       6       true
+31     3       593315097326125055      2       6       true
+32     4       596538564771053567      2       6       true
+33     4       594785934646444031      2       6       true
+34     4       594530555891023871      2       6       true
+35     4       598742604548407295      2       6       true
+36     4       596704238839529471      2       6       true
+37     4       596704238839529471      2       6       true
+38     4       595182179739238399      2       6       true
+39     4       597818645413887999      2       6       true
+4      0       578712552117108735      2       5       true
+40     5       601042424243945471      2       6       true
+41     5       599289528905105407      2       6       true
+42     5       599034148002201599      2       6       true
+43     5       603246196659585023      2       6       true
+44     5       601207835245674495      2       6       true
+45     5       601207835245674495      2       6       true
+46     5       599685771850416127      2       6       true
+47     5       602322242893774847      2       6       true
+48     6       605546023066009599      2       6       true
+49     6       603793128129822719      2       6       true
+5      0       578712552117108735      2       5       true
+50     6       603537747495354367      2       6       true
+51     6       607749795481649151      2       6       true
+52     6       605711434470391807      2       6       true
+53     6       605711434470391807      2       6       true
+54     6       604189371209351167      2       6       true
+55     6       606825841984274431      2       6       true
+56     7       610049622659825663      2       6       true
+57     7       608296727690084351      2       6       true
+58     7       608041347055615999      2       6       true
+59     7       612253395092242431      2       6       true
+6      0       577199624117288959      2       6       true
+60     7       610215034013876223      2       6       true
+61     7       610215034013876223      2       6       true
+62     7       608692970719281151      2       6       true
+63     7       611329441561313279      2       6       true
+64     8       614553222213795839      2       6       true
+65     8       612800327311163391      2       6       true
+66     8       612544946678792191      2       6       true
+67     8       616756994704932863      2       6       true
+68     8       614718633626566655      2       6       true
+69     8       614718633626566655      2       6       true
+7      0       579838452023951359      2       6       true
+70     8       613196570331971583      2       6       true
+71     8       615833041184489471      2       6       true
+72     9       619056821840379903      2       6       true
+73     9       617303926937223167      2       6       true
+74     9       617048546304851967      2       6       true
+75     9       621260594331254783      2       6       true
+76     9       619222233253675007      2       6       true
+77     9       619222233253675007      2       6       true
+78     9       617700169957507071      2       6       true
+79     9       620336640811597823      2       6       true
+8      1       583031433791012863      2       7       true
+80     10      623560421467684863      2       6       true
+81     10      621807526564364287      2       6       true
+82     10      621552145932189695      2       6       true
+83     10      625764193958461439      2       6       true
+84     10      623725832880947199      2       6       true
+85     10      623725832880947199      2       6       true
+86     10      622203769584680959      2       6       true
+87     10      624840240438902783      2       6       true
+88     11      628064021095030783      2       6       true
+89     11      626311126191714303      2       6       true
+9      1       581276613233082367      2       7       true
+90     11      626055745559531519      2       6       true
+91     11      630267793585803263      2       6       true
+92     11      628229432508297215      2       6       true
+93     11      628229432508297215      2       6       true
+94     11      626707369212035071      2       6       true
+95     11      629343840066265087      2       6       true
+96     12      632567620722400767      2       6       true
+97     12      630814725819082751      2       6       true
+98     12      630559345186898943      2       6       true
+99     12      634771393213173247      2       6       true
+
+-- !location_filter --
+0      8
+1      8
+10     8
+11     8
+12     8
+13     8
+14     8
+15     8
+2      8
+3      8
+4      8
+5      8
+6      8
+7      8
+8      8
+9      8
+
+-- !cell_grouping --
+0      578712552117108735      2
+1      583194161511923711      2
+10     623725832880947199      2
+11     628229432508297215      2
+12     632733032135666687      2
+13     637236631763037119      2
+14     641740231390407607      2
+15     646243831017778096      2
+2      587697211383480319      2
+3      592200673571897343      2
+4      596704238839529471      2
+5      601207835245674495      2
+6      605711434470391807      2
+7      610215034013876223      2
+8      614718633626566655      2
+9      619222233253675007      2
+
+-- !constant_with_columns --
+0      619056821840379903      619056821840379903      578536630256664575
+1      617440756014514175      619143828350959615      578536630256664575
+120    619056821840379903      619056821840379903      646078419604526808
+121    617440756014514175      619143828350959615      646078419604526808
+122    617048546304851967      619222233253675007      646078419604526808
+123    621260594331254783      619222233253675007      646078419604526808
+124    619056821840379903      619222233253675007      646078419604526808
+125    619056821840379903      619222233253675007      646078419604526808
+126    618001544260616191      618952619549786111      646078419604526808
+127    620377570945269759      619095778567389183      646078419604526808
+2      617048546304851967      619222233253675007      578536630256664575
+3      621260594331254783      619222233253675007      578536630256664575
+4      619056821840379903      619222233253675007      578536630256664575
+5      619056821840379903      619222233253675007      578536630256664575
+6      618001544260616191      618952619549786111      578536630256664575
+7      620377570945269759      619095778567389183      578536630256664575
+
+-- !stored_arrays --
+1      2       6       [55.712902431, 37.795066168]    [[55.712900225, 
37.795058112], [55.712897135, 37.79506507], [55.712899341, 37.795073127], 
[55.712904638, 37.795074225], [55.712907728, 37.795067267], [55.712905522, 
37.79505921]]
+2      \N      \N      \N      \N
+3      \N      \N      \N      \N
+4      \N      \N      \N      \N
+5      \N      \N      \N      \N
+6      2       6       [48.758349724, 18.303044481]    [[55.706768465, 
5.523646549], [45.18424869, 2.026568965], [37.523712366, 13.244313476], 
[39.643310548, 28.846868847], [49.779342868, 36.116723632], [58.40154487, 
25.082722327]]
+7      2       6       [79.24239851, 38.023407008]     [[68.929957882, 
31.831280499], [69.39359649, 62.345344957], [76.16304283, 94.143090102], 
[87.364695323, 145.558197691], [81.27137179, -34.75841798], [73.310223685, 
0.325610352]]
+
+-- !exploded_boundary --
+1      55.712897135    37.79506507
+1      55.712899341    37.795073127
+1      55.712900225    37.795058112
+1      55.712904638    37.795074225
+1      55.712905522    37.79505921
+1      55.712907728    37.795067267
+6      37.523712366    13.244313476
+6      39.643310548    28.846868847
+6      45.18424869     2.026568965
+6      49.779342868    36.116723632
+6      55.706768465    5.523646549
+6      58.40154487     25.082722327
+7      68.929957882    31.831280499
+7      69.39359649     62.345344957
+7      73.310223685    0.325610352
+7      76.16304283     94.143090102
+7      81.27137179     -34.75841798
+7      87.364695323    145.558197691
+
+-- !array_composition --
+1      6       [2, 2, 2, 2, 2, 2]      644325524701193974
+2      \N      \N      \N
+3      \N      \N      \N
+4      \N      \N      \N
+5      \N      \N      \N
+6      6       [2, 2, 2, 2, 2, 2]      644542512295313408
+7      6       [2, 2, 2, 2, 2, 2]      644014746713980928
+
+-- !batch_nulls --
+0      5000    5000    5000    5000    10000   30000
+1      5000    5000    5000    5000    10000   30000
+2      5000    0       0       0       \N      \N
+3      5000    0       0       0       \N      \N
+4      5000    0       0       0       \N      \N
+5      5000    0       0       0       \N      \N
+6      5000    5000    5000    5000    10000   30000
+
+-- !batch_filter --
+15000
+
+-- !batch_cell_grouping --
+\N     20000
+576495936675512319     5000
+644325524701193974     5000
+648282192095284420     5000
+
diff --git 
a/regression-test/suites/query_p0/sql_functions/spatial_functions/test_h3.groovy
 
b/regression-test/suites/query_p0/sql_functions/spatial_functions/test_h3.groovy
new file mode 100644
index 00000000000..e2cd487bb8b
--- /dev/null
+++ 
b/regression-test/suites/query_p0/sql_functions/spatial_functions/test_h3.groovy
@@ -0,0 +1,188 @@
+// 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.
+
+
+suite("test_h3") {
+    for (def foldOnBe in [false, true]) {
+        sql "set enable_fold_constant_by_be = ${foldOnBe}"
+        qt_fold_cell """select h3_lat_lng_to_cell(55.71290588,37.79506683,15),
+            h3_lat_lng_to_cell(cast('55.71290588' as double),
+                cast('37.79506683' as double),abs(-15))"""
+        qt_fold_coordinates """select
+            array_map(x -> round(x,9),h3_cell_to_lat_lng(644325524701193974)),
+            array_map(p -> array_map(x -> round(x,9),p),
+                h3_cell_to_boundary(644325524701193974))"""
+        qt_fold_nested """select h3_lat_lng_to_cell(
+            h3_cell_to_lat_lng(644325524701193974)[1],
+            h3_cell_to_lat_lng(644325524701193974)[2],15),
+            size(h3_cell_to_lat_lng(h3_lat_lng_to_cell(0,0,0))),
+            size(h3_cell_to_boundary(h3_lat_lng_to_cell(0,0,15)))"""
+        qt_fold_null """select h3_lat_lng_to_cell(cast(null as double),0,9),
+            h3_lat_lng_to_cell(0,cast(null as double),9),
+            h3_lat_lng_to_cell(0,0,cast(null as int)),
+            h3_cell_to_lat_lng(cast(null as bigint)),
+            h3_cell_to_boundary(cast(null as bigint)),
+            h3_cell_to_lat_lng(h3_lat_lng_to_cell(91,0,9))"""
+        qt_fold_invalid """select h3_lat_lng_to_cell(-91,0,9),
+            h3_lat_lng_to_cell(0,-181,9),h3_lat_lng_to_cell(0,0,16),
+            h3_cell_to_lat_lng(12345),h3_cell_to_boundary(-1),
+            h3_cell_to_boundary(1509016653156329206)"""
+        qt_fold_endpoints """select h3_lat_lng_to_cell(90,180,0),
+            h3_lat_lng_to_cell(-90,-180,15),h3_lat_lng_to_cell(0,180,15),
+            h3_lat_lng_to_cell(0,-180,15)"""
+    }
+    sql "set enable_fold_constant_by_be = false"
+    explain {
+        sql """select h3_lat_lng_to_cell(55.71290588,37.79506683,15),
+            h3_cell_to_lat_lng(644325524701193974),
+            h3_cell_to_boundary(644325524701193974)"""
+        contains "h3_lat_lng_to_cell(55.71290588, 37.79506683, 15)"
+        contains "h3_cell_to_lat_lng(644325524701193974)"
+        contains "h3_cell_to_boundary(644325524701193974)"
+    }
+    sql "set enable_fold_constant_by_be = true"
+    explain {
+        sql "select h3_lat_lng_to_cell(55.71290588,37.79506683,15)"
+        contains "644325524701193974"
+        notContains "h3_lat_lng_to_cell(55.71290588, 37.79506683, 15)"
+    }
+    sql "set enable_fold_constant_by_be = false"
+    qt_cell "select h3_lat_lng_to_cell(55.71290588, 37.79506683, 15)"
+    qt_center """select array_map(x -> round(x, 9),
+        h3_cell_to_lat_lng(644325524701193974))"""
+    qt_boundary """select array_map(p -> array_map(x -> round(x, 9), p),
+        h3_cell_to_boundary(644325524701193974))"""
+    qt_invalid """select h3_lat_lng_to_cell(91, 0, 9),
+        h3_lat_lng_to_cell(0, 181, 9), h3_lat_lng_to_cell(0, 0, -1),
+        h3_lat_lng_to_cell(0, 0, 16), h3_cell_to_lat_lng(0),
+        h3_cell_to_lat_lng(-1), h3_cell_to_boundary(12345)"""
+    qt_null """select h3_lat_lng_to_cell(null, 0, 9),
+        h3_lat_lng_to_cell(0, null, 9), h3_lat_lng_to_cell(0, 0, null),
+        h3_cell_to_lat_lng(null), h3_cell_to_boundary(null)"""
+    qt_non_cell """select h3_cell_to_lat_lng(1509016653156329206),
+        h3_cell_to_boundary(1509016653156329206),
+        h3_cell_to_lat_lng(2517822969687320233),
+        h3_cell_to_boundary(2517822969687320233),
+        h3_cell_to_lat_lng(9223372036854775807)"""
+    qt_pentagons """select size(h3_cell_to_boundary(576636674163867647)),
+        size(h3_cell_to_boundary(581109487465660415)),
+        array_map(p -> array_map(x -> round(x,9),p),
+            h3_cell_to_boundary(581109487465660415))"""
+    sql "drop table if exists test_h3_inputs"
+    sql """create table test_h3_inputs (
+        id int, lat double, lng double, res int, cell bigint
+    ) distributed by hash(id) buckets 1 properties("replication_num"="1")"""
+    sql """insert into test_h3_inputs values
+        (1,55.71290588,37.79506683,15,644325524701193974),
+        (2,91,0,9,0), (3,null,0,9,null), (4,0,null,9,-1),
+        (5,0,0,null,12345), (6,90,180,0,577023702256844799),
+        (7,-90,-180,15,576495936675512319)"""
+    order_qt_rows """select id, h3_lat_lng_to_cell(lat,lng,res),
+        array_map(x -> round(x, 9), h3_cell_to_lat_lng(cell)),
+        array_map(p -> array_map(x -> round(x, 9),p),h3_cell_to_boundary(cell))
+        from test_h3_inputs"""
+    order_qt_mixed """select id, h3_lat_lng_to_cell(lat,0,9),
+        h3_lat_lng_to_cell(0,lng,res) from test_h3_inputs"""
+    order_qt_array_access """select id,size(h3_cell_to_lat_lng(cell)),
+        
round(h3_cell_to_lat_lng(cell)[1],9),round(h3_cell_to_lat_lng(cell)[2],9),
+        h3_cell_to_lat_lng(cell)[3],
+        round(h3_cell_to_boundary(cell)[1][1],9),
+        round(h3_cell_to_boundary(cell)[1][2],9)
+        from test_h3_inputs"""
+    order_qt_null_columns """select id,
+        h3_lat_lng_to_cell(if(id>0,null,lat),lng,res),
+        h3_cell_to_lat_lng(if(id>0,null,cell)),
+        h3_cell_to_boundary(if(id>0,null,cell)) from test_h3_inputs"""
+    order_qt_empty """select h3_lat_lng_to_cell(lat,lng,res),
+        h3_cell_to_lat_lng(cell),h3_cell_to_boundary(cell)
+        from test_h3_inputs where id < 0"""
+    qt_roundtrip """select h3_lat_lng_to_cell(
+        h3_cell_to_lat_lng(644325524701193974)[1],
+        h3_cell_to_lat_lng(644325524701193974)[2],15)"""
+    qt_many_rows """select count(*), sum(h3_lat_lng_to_cell(0,0,cast(number % 
16 as int)) is null),
+        sum(size(h3_cell_to_boundary(if(number % 2=0,644325524701193974,0)))),
+        sum(size(h3_cell_to_lat_lng(if(number % 2=0,644325524701193974,null))))
+        from numbers('number'='10000')"""
+
+    sql "drop table if exists test_h3_locations"
+    sql """create table test_h3_locations (
+        id int not null, lat double not null, lng double not null, res int not 
null,
+        cell bigint not null
+    ) distributed by hash(id) buckets 3 properties("replication_num"="1")"""
+    sql """insert into test_h3_locations
+        select cast(number as int),
+            case number % 8 when 0 then 0 when 1 then 55.71290588
+                when 2 then 90 when 3 then -90 when 4 then 0
+                when 5 then 0 when 6 then 37.7749 else -33.8688 end,
+            case number % 8 when 0 then 0 when 1 then 37.79506683
+                when 2 then 180 when 3 then -180 when 4 then 180
+                when 5 then -180 when 6 then -122.4194 else 151.2093 end,
+            cast(floor(number / 8) as int), 0
+        from numbers('number'='128')"""
+    sql """insert overwrite table test_h3_locations
+        select id,lat,lng,res,h3_lat_lng_to_cell(lat,lng,res) from 
test_h3_locations"""
+    order_qt_all_resolutions """select id,res,cell,
+        size(h3_cell_to_lat_lng(cell)),size(h3_cell_to_boundary(cell)),
+        h3_lat_lng_to_cell(h3_cell_to_lat_lng(cell)[1],
+            h3_cell_to_lat_lng(cell)[2],res)=cell as center_roundtrip
+        from test_h3_locations"""
+    order_qt_location_filter """select res,count(*)
+        from test_h3_locations where h3_cell_to_lat_lng(cell) is not null
+            and size(h3_cell_to_boundary(cell)) between 5 and 10 group by 
res"""
+    order_qt_cell_grouping """select 
res,h3_lat_lng_to_cell(lat,lng,res),count(*)
+        from test_h3_locations where id % 8 in (4,5)
+        group by res,h3_lat_lng_to_cell(lat,lng,res)"""
+    order_qt_constant_with_columns """select id,
+        h3_lat_lng_to_cell(lat,0,9),h3_lat_lng_to_cell(0,lng,9),
+        h3_lat_lng_to_cell(0,0,res) from test_h3_locations where res in 
(0,15)"""
+
+    sql "drop table if exists test_h3_arrays"
+    sql """create table test_h3_arrays (
+        id int, center array<double>, boundary array<array<double>>
+    ) distributed by hash(id) buckets 1 properties("replication_num"="1")"""
+    sql """insert into test_h3_arrays select id,h3_cell_to_lat_lng(cell),
+        h3_cell_to_boundary(cell) from test_h3_inputs"""
+    order_qt_stored_arrays """select id,size(center),size(boundary),
+        array_map(x -> round(x,9),center),
+        array_map(p -> array_map(x -> round(x,9),p),boundary)
+        from test_h3_arrays"""
+    order_qt_exploded_boundary """select 
id,round(vertex[1],9),round(vertex[2],9)
+        from test_h3_arrays lateral view explode(boundary) points as vertex"""
+    order_qt_array_composition """select id,
+        size(array_filter(p -> p[1] >= 0,h3_cell_to_boundary(cell))),
+        array_map(p -> size(p),h3_cell_to_boundary(cell)),
+        h3_lat_lng_to_cell(center[1],center[2],15)
+        from test_h3_inputs join test_h3_arrays using(id)"""
+
+    sql "drop table if exists test_h3_batches"
+    sql """create table test_h3_batches (
+        id int, lat double, lng double, res int, cell bigint
+    ) distributed by hash(id) buckets 3 properties("replication_num"="1")"""
+    sql """insert into test_h3_batches
+        select cast(n.number*7+i.id as int),i.lat,i.lng,i.res,i.cell
+        from test_h3_inputs i cross join numbers('number'='5000') n"""
+    order_qt_batch_nulls """select id % 7,count(*),
+        count(h3_lat_lng_to_cell(lat,lng,res)),
+        count(h3_cell_to_lat_lng(cell)),count(h3_cell_to_boundary(cell)),
+        
sum(size(h3_cell_to_lat_lng(cell))),sum(size(h3_cell_to_boundary(cell)))
+        from test_h3_batches group by id % 7"""
+    qt_batch_filter """select count(*) from test_h3_batches
+        where h3_lat_lng_to_cell(lat,lng,res) is not null
+            and h3_cell_to_boundary(cell) is not null"""
+    order_qt_batch_cell_grouping """select 
h3_lat_lng_to_cell(lat,lng,res),count(*)
+        from test_h3_batches group by h3_lat_lng_to_cell(lat,lng,res)"""
+}
diff --git a/run-be-ut.sh b/run-be-ut.sh
index 201dfcc68c9..2485582ca6e 100755
--- a/run-be-ut.sh
+++ b/run-be-ut.sh
@@ -256,12 +256,14 @@ update_submodule() {
 
 # Keep this list in sync with build.sh: be/CMakeLists.txt adds 
storage/index/ann
 # unconditionally, and its cmake-protect target add_subdirectory()s both faiss 
and openblas,
-# so the configure step fails outright when either is missing.
+# so the configure step fails outright when either is missing. The H3 wrapper 
also
+# requires its submodule to be initialized before configuring BE.
 update_submodule "contrib/datasketches-cpp" "datasketches-cpp" 
"https://github.com/apache/datasketches-cpp/archive/refs/heads/master.tar.gz";
 update_submodule "contrib/apache-orc" "apache-orc" 
"https://github.com/apache/doris-thirdparty/archive/refs/heads/orc.tar.gz";
 update_submodule "contrib/clucene" "clucene" 
"https://github.com/apache/doris-thirdparty/archive/refs/heads/clucene.tar.gz";
 update_submodule "contrib/openblas" "openblas" 
"https://github.com/apache/doris-thirdparty/archive/refs/heads/openblas.tar.gz";
 update_submodule "contrib/faiss" "faiss" 
"https://github.com/apache/doris-thirdparty/archive/refs/heads/faiss.tar.gz";
+update_submodule "contrib/h3" "h3" 
"https://github.com/uber/h3/archive/refs/tags/v4.5.0.tar.gz";
 
 if [[ "_${DENABLE_CLANG_COVERAGE}" == "_ON" ]]; then
     echo "export DORIS_TOOLCHAIN=clang" >>custom_env.sh


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to