Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 1 addition & 4 deletions cmake_modules/IcebergThirdpartyToolchain.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -906,10 +906,7 @@ function(resolve_thrift_dependency)
return()
endif()
if(ICEBERG_THRIFT_BUNDLED)
# Arrow's bundled build creates the Thrift C++ runtime as a `thrift` target
# scoped to its FetchContent directory, where iceberg_hive cannot see it.
# Promote it to a global `thrift::thrift` alias so iceberg_hive can link the
# generated Hive Metastore bindings against it.
# Expose bundled Thrift and its include paths to Hive.
if(TARGET thrift AND NOT TARGET thrift::thrift)
add_library(thrift::thrift INTERFACE IMPORTED GLOBAL)
target_link_libraries(thrift::thrift INTERFACE thrift)
Expand Down
18 changes: 12 additions & 6 deletions src/iceberg/catalog/hive/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,13 @@ if(NOT TARGET thrift::thrift)
"-DICEBERG_BUNDLE_THRIFT=OFF against a system Thrift install.")
endif()

set(ICEBERG_HIVE_SOURCES hive_catalog.cc hive_catalog_properties.cc hms_client.cc
${ICEBERG_HIVE_THRIFT_GEN_SOURCES})
set(ICEBERG_HIVE_SOURCES
hive_catalog.cc
hive_catalog_properties.cc
hive_schema.cc
hive_utils.cc
hms_client.cc
${ICEBERG_HIVE_THRIFT_GEN_SOURCES})

set(ICEBERG_HIVE_STATIC_BUILD_INTERFACE_LIBS)
set(ICEBERG_HIVE_SHARED_BUILD_INTERFACE_LIBS)
Expand All @@ -72,10 +77,11 @@ set(ICEBERG_HIVE_SHARED_INSTALL_INTERFACE_LIBS)
# * System: downstream find_package(Iceberg) re-creates `thrift::thrift` via
# find_dependency(ThriftAlt) (FindThriftAlt.cmake is shipped next to the
# config), so it must be propagated.
list(APPEND ICEBERG_HIVE_STATIC_BUILD_INTERFACE_LIBS
"$<IF:$<TARGET_EXISTS:iceberg_static>,iceberg_static,iceberg_shared>" thrift::thrift)
list(APPEND ICEBERG_HIVE_SHARED_BUILD_INTERFACE_LIBS
"$<IF:$<TARGET_EXISTS:iceberg_shared>,iceberg_shared,iceberg_static>" thrift::thrift)
# Prefer Thrift headers over any system Thrift found through core.
list(APPEND ICEBERG_HIVE_STATIC_BUILD_INTERFACE_LIBS thrift::thrift
"$<IF:$<TARGET_EXISTS:iceberg_static>,iceberg_static,iceberg_shared>")
list(APPEND ICEBERG_HIVE_SHARED_BUILD_INTERFACE_LIBS thrift::thrift
"$<IF:$<TARGET_EXISTS:iceberg_shared>,iceberg_shared,iceberg_static>")
list(APPEND
ICEBERG_HIVE_STATIC_INSTALL_INTERFACE_LIBS
"$<IF:$<TARGET_EXISTS:iceberg::iceberg_static>,iceberg::iceberg_static,iceberg::iceberg_shared>"
Expand Down
128 changes: 128 additions & 0 deletions src/iceberg/catalog/hive/hive_schema.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
/*
* 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 "iceberg/catalog/hive/hive_schema.h"

#include <format>
#include <string>
#include <vector>

#include "iceberg/schema.h"
#include "iceberg/schema_field.h"
#include "iceberg/type.h"
#include "iceberg/util/checked_cast.h"
#include "iceberg/util/macros.h"

namespace iceberg::hive {

namespace {

Result<std::string> PrimitiveToHive(const Type& type) {
switch (type.type_id()) {
case TypeId::kBoolean:
return std::string("boolean");
case TypeId::kInt:
return std::string("int");
case TypeId::kLong:
return std::string("bigint");
case TypeId::kFloat:
return std::string("float");
case TypeId::kDouble:
return std::string("double");
case TypeId::kDate:
return std::string("date");
case TypeId::kTimestamp:
return std::string("timestamp");
case TypeId::kTimestampTz:
return std::string("timestamp with local time zone");
case TypeId::kTime:
case TypeId::kString:
case TypeId::kUuid:
return std::string("string");
case TypeId::kBinary:
case TypeId::kFixed:
return std::string("binary");
case TypeId::kVariant:
return std::string("unknown");
case TypeId::kDecimal: {
const auto& decimal = internal::checked_cast<const DecimalType&>(type);
return std::format("decimal({},{})", decimal.precision(), decimal.scale());
}
default:
return NotImplemented("Unhandled primitive Iceberg type id: {}",
static_cast<int>(type.type_id()));
}
}

Result<std::string> StructToHive(const StructType& type) {
std::string out = "struct<";
bool first = true;
for (const auto& field : type.fields()) {
if (!first) {
out += ",";
}
ICEBERG_ASSIGN_OR_RAISE(auto field_type, TypeToHiveString(*field.type()));
out += std::string(field.name());
out += ":";
out += field_type;
first = false;
}
out += ">";
return out;
}

Result<std::string> ListToHive(const ListType& type) {
ICEBERG_ASSIGN_OR_RAISE(auto inner, TypeToHiveString(*type.element().type()));
return std::format("array<{}>", inner);
}

Result<std::string> MapToHive(const MapType& type) {
ICEBERG_ASSIGN_OR_RAISE(auto key_type, TypeToHiveString(*type.key().type()));
ICEBERG_ASSIGN_OR_RAISE(auto value_type, TypeToHiveString(*type.value().type()));
return std::format("map<{},{}>", key_type, value_type);
}

} // namespace

Result<std::string> TypeToHiveString(const Type& type) {
switch (type.type_id()) {
case TypeId::kStruct:
return StructToHive(internal::checked_cast<const StructType&>(type));
case TypeId::kList:
return ListToHive(internal::checked_cast<const ListType&>(type));
case TypeId::kMap:
return MapToHive(internal::checked_cast<const MapType&>(type));
default:
return PrimitiveToHive(type);
}
}

Result<std::vector<HiveColumn>> SchemaToHiveColumns(const Schema& schema) {
std::vector<HiveColumn> columns;
columns.reserve(schema.fields().size());
for (const auto& field : schema.fields()) {
ICEBERG_ASSIGN_OR_RAISE(auto type_string, TypeToHiveString(*field.type()));
columns.push_back(HiveColumn{.name = std::string(field.name()),
.type_string = std::move(type_string),
.comment = std::string(field.doc())});
}
return columns;
}

} // namespace iceberg::hive
51 changes: 51 additions & 0 deletions src/iceberg/catalog/hive/hive_schema.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* 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.
*/

#pragma once

#include <string>
#include <vector>

#include "iceberg/catalog/hive/iceberg_hive_export.h"
#include "iceberg/result.h"
#include "iceberg/type_fwd.h"

/// \file iceberg/catalog/hive/hive_schema.h
/// \brief Render Iceberg schemas as Hive type strings.

namespace iceberg::hive {

/// \brief Column metadata passed to HMS.
struct ICEBERG_HIVE_EXPORT HiveColumn {
std::string name;
std::string type_string;
std::string comment;
};

/// \brief Render a Hive type string, including nested types.
/// Follow Java: variant -> unknown, time/uuid -> string, fixed -> binary.
/// Unsupported types return kNotImplemented. Zoned timestamps require Hive 3+.
ICEBERG_HIVE_EXPORT Result<std::string> TypeToHiveString(const Type& type);

/// \brief Convert top-level fields to HMS columns. Docs become comments.
/// Field IDs and requiredness are not represented in HMS.
ICEBERG_HIVE_EXPORT Result<std::vector<HiveColumn>> SchemaToHiveColumns(
const Schema& schema);

} // namespace iceberg::hive
Loading
Loading