blob: 1837ab009cf3651dd860f1cfff43ebf3efbbc985 [file]
/*
* 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/update/update_properties.h"
#include <cstdint>
#include <memory>
#include "iceberg/metrics_config.h"
#include "iceberg/result.h"
#include "iceberg/table_metadata.h"
#include "iceberg/table_properties.h"
#include "iceberg/transaction.h"
#include "iceberg/util/error_collector.h"
#include "iceberg/util/macros.h"
#include "iceberg/util/string_util.h"
namespace iceberg {
Result<std::shared_ptr<UpdateProperties>> UpdateProperties::Make(
std::shared_ptr<TransactionContext> ctx) {
ICEBERG_PRECHECK(ctx != nullptr, "Cannot create UpdateProperties without a context");
return std::shared_ptr<UpdateProperties>(new UpdateProperties(std::move(ctx)));
}
UpdateProperties::UpdateProperties(std::shared_ptr<TransactionContext> ctx)
: PendingUpdate(std::move(ctx)) {}
UpdateProperties::~UpdateProperties() = default;
UpdateProperties& UpdateProperties::Set(const std::string& key,
const std::string& value) {
ICEBERG_BUILDER_CHECK(!removals_.contains(key),
"Cannot set property '{}' that is already marked for removal",
key);
if (!TableProperties::reserved_properties().contains(key) ||
key == TableProperties::kFormatVersion.key()) {
updates_.insert_or_assign(key, value);
}
return *this;
}
UpdateProperties& UpdateProperties::Remove(const std::string& key) {
ICEBERG_BUILDER_CHECK(!updates_.contains(key),
"Cannot remove property '{}' that is already marked for update",
key);
removals_.insert(key);
return *this;
}
Result<UpdateProperties::ApplyResult> UpdateProperties::Apply() {
ICEBERG_RETURN_UNEXPECTED(CheckErrors());
const auto& current_props = base().properties.configs();
std::unordered_map<std::string, std::string> new_properties;
std::vector<std::string> removals;
for (const auto& [key, value] : current_props) {
if (!removals_.contains(key)) {
new_properties[key] = value;
}
}
for (const auto& [key, value] : updates_) {
new_properties[key] = value;
}
auto iter = new_properties.find(TableProperties::kFormatVersion.key());
if (iter != new_properties.end()) {
ICEBERG_ASSIGN_OR_RAISE(auto parsed_version,
StringUtils::ParseNumber<int32_t>(iter->second));
if (parsed_version > TableMetadata::kSupportedTableFormatVersion) {
return InvalidArgument(
"Cannot upgrade table to unsupported format version: v{} (supported: v{})",
parsed_version, TableMetadata::kSupportedTableFormatVersion);
}
format_version_ = static_cast<int8_t>(parsed_version);
updates_.erase(TableProperties::kFormatVersion.key());
}
if (auto schema = base().Schema(); schema.has_value()) {
ICEBERG_RETURN_UNEXPECTED(
MetricsConfig::VerifyReferencedColumns(new_properties, *schema.value()));
}
return ApplyResult{
.updates = updates_, .removals = removals_, .format_version = format_version_};
}
} // namespace iceberg