blob: 5af23cf668a49ac795a6c79ab0953794b82a8851 [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 "paimon/table/source/table_read.h"
#include <cassert>
#include <map>
#include <optional>
#include <string>
#include <utility>
#include "fmt/format.h"
#include "paimon/common/reader/concat_batch_reader.h"
#include "paimon/common/types/data_field.h"
#include "paimon/common/utils/string_utils.h"
#include "paimon/core/core_options.h"
#include "paimon/core/operation/internal_read_context.h"
#include "paimon/core/schema/schema_manager.h"
#include "paimon/core/schema/table_schema.h"
#include "paimon/core/table/source/append_only_table_read.h"
#include "paimon/core/table/source/fallback_table_read.h"
#include "paimon/core/table/source/key_value_table_read.h"
#include "paimon/core/table/system/system_table.h"
#include "paimon/core/utils/branch_manager.h"
#include "paimon/core/utils/file_store_path_factory.h"
#include "paimon/defs.h"
#include "paimon/format/file_format.h"
#include "paimon/read_context.h"
#include "paimon/status.h"
namespace paimon {
class DataSplit;
class Executor;
class MemoryPool;
namespace {
Result<std::unique_ptr<InternalReadContext>> CreateInternalReadContext(
const std::shared_ptr<ReadContext>& context, const std::string& branch) {
std::map<std::string, std::string> tmp_options = context->GetOptions();
std::shared_ptr<TableSchema> table_schema;
const auto& specific_table_schema = context->GetSpecificTableSchema();
if (branch == BranchManager::DEFAULT_MAIN_BRANCH && specific_table_schema) {
PAIMON_ASSIGN_OR_RAISE(table_schema,
TableSchema::CreateFromJson(specific_table_schema.value()));
} else {
PAIMON_ASSIGN_OR_RAISE(CoreOptions tmp_core_options,
CoreOptions::FromMap(tmp_options, context->GetSpecificFileSystem(),
context->GetFileSystemSchemeToIdentifierMap()));
SchemaManager schema_manager(tmp_core_options.GetFileSystem(), context->GetPath(), branch);
PAIMON_ASSIGN_OR_RAISE(std::optional<std::shared_ptr<TableSchema>> latest_schema,
schema_manager.Latest());
if (!latest_schema) {
return Status::Invalid(fmt::format("schema file not found in path {}, branch {}",
context->GetPath(), branch));
}
table_schema = latest_schema.value();
}
assert(table_schema);
// merge options
auto options = table_schema->Options();
for (const auto& [key, value] : tmp_options) {
options[key] = value;
}
if (branch != BranchManager::DEFAULT_MAIN_BRANCH) {
options[Options::BRANCH] = branch;
}
return InternalReadContext::Create(context, table_schema, options);
}
Result<std::unique_ptr<TableRead>> CreateTableRead(
const std::shared_ptr<InternalReadContext>& internal_context,
const std::shared_ptr<MemoryPool>& memory_pool, const std::shared_ptr<Executor>& executor) {
const auto& core_options = internal_context->GetCoreOptions();
const auto& table_schema = internal_context->GetTableSchema();
auto arrow_schema = DataField::ConvertDataFieldsToArrowSchema(table_schema->Fields());
PAIMON_ASSIGN_OR_RAISE(std::vector<std::string> external_paths,
core_options.CreateExternalPaths());
PAIMON_ASSIGN_OR_RAISE(std::optional<std::string> global_index_external_path,
core_options.CreateGlobalIndexExternalPath());
PAIMON_ASSIGN_OR_RAISE(
std::shared_ptr<FileStorePathFactory> path_factory,
FileStorePathFactory::Create(
internal_context->GetPath(), arrow_schema, table_schema->PartitionKeys(),
core_options.GetPartitionDefaultName(), core_options.GetFileFormat()->Identifier(),
core_options.DataFilePrefix(), core_options.LegacyPartitionNameEnabled(),
external_paths, global_index_external_path, core_options.IndexFileInDataFileDir(),
memory_pool));
if (internal_context->GetPrimaryKeys().empty()) {
return std::make_unique<AppendOnlyTableRead>(path_factory, internal_context, memory_pool,
executor);
}
return KeyValueTableRead::Create(path_factory, internal_context, memory_pool, executor);
}
Result<std::unique_ptr<TableRead>> NewDataTableRead(const std::shared_ptr<ReadContext>& context) {
PAIMON_ASSIGN_OR_RAISE(std::shared_ptr<InternalReadContext> internal_context,
CreateInternalReadContext(context, context->GetBranch()));
PAIMON_ASSIGN_OR_RAISE(
std::unique_ptr<TableRead> table_read,
CreateTableRead(internal_context, context->GetMemoryPool(), context->GetExecutor()));
std::optional<std::string> scan_fallback_branch =
internal_context->GetCoreOptions().GetScanFallbackBranch();
if (!scan_fallback_branch ||
StringUtils::IsNullOrWhitespaceOnly(scan_fallback_branch.value())) {
return std::move(table_read);
}
PAIMON_ASSIGN_OR_RAISE(
std::shared_ptr<InternalReadContext> fallback_context,
CreateInternalReadContext(context, /*branch=*/scan_fallback_branch.value()));
PAIMON_ASSIGN_OR_RAISE(
std::unique_ptr<TableRead> fallback_table_read,
CreateTableRead(fallback_context, context->GetMemoryPool(), context->GetExecutor()));
return std::make_unique<FallbackTableRead>(
std::move(table_read), std::move(fallback_table_read), context->GetMemoryPool());
}
} // namespace
TableRead::TableRead(const std::shared_ptr<MemoryPool>& memory_pool) : pool_(memory_pool) {}
Result<std::unique_ptr<TableRead>> TableRead::Create(std::unique_ptr<ReadContext> ctx) {
std::shared_ptr<ReadContext> context = std::move(ctx);
if (context == nullptr) {
return Status::Invalid("read context is null pointer");
}
if (context->GetMemoryPool() == nullptr) {
return Status::Invalid("memory pool is null pointer");
}
if (context->GetExecutor() == nullptr) {
return Status::Invalid("executor is null pointer");
}
PAIMON_ASSIGN_OR_RAISE(
CoreOptions tmp_core_options,
CoreOptions::FromMap(context->GetOptions(), context->GetSpecificFileSystem(),
context->GetFileSystemSchemeToIdentifierMap()));
PAIMON_ASSIGN_OR_RAISE(std::optional<SystemTablePath> system_table_path,
SystemTableLoader::TryParsePath(context->GetPath()));
if (system_table_path) {
PAIMON_ASSIGN_OR_RAISE(
std::shared_ptr<SystemTable> system_table,
SystemTableLoader::LoadFromPath(tmp_core_options.GetFileSystem(), context->GetPath(),
context->GetOptions()));
return system_table->NewRead(context);
}
return NewDataTableRead(context);
}
Result<std::unique_ptr<BatchReader>> TableRead::CreateReader(
const std::vector<std::shared_ptr<Split>>& splits) {
std::vector<std::unique_ptr<BatchReader>> batch_readers;
batch_readers.reserve(splits.size());
for (const auto& split : splits) {
PAIMON_ASSIGN_OR_RAISE(std::unique_ptr<BatchReader> reader, CreateReader(split));
batch_readers.emplace_back(std::move(reader));
}
return std::make_unique<ConcatBatchReader>(std::move(batch_readers), pool_);
}
} // namespace paimon