blob: a4c310254b5bcc1d21d21a9c4e8effa9d0191b67 [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.
*/
#pragma once
#include <map>
#include <memory>
#include <string>
#include <vector>
#include "paimon/catalog/identifier.h"
#include "paimon/result.h"
#include "paimon/schema/schema.h"
#include "paimon/status.h"
#include "paimon/type_fwd.h"
#include "paimon/visibility.h"
struct ArrowSchema;
namespace paimon {
class FileSystem;
/// A table that is a directory of data files of one format, laid out like a standard Hive table.
///
/// It carries no snapshots and no manifests: the files under its location are the table, and a
/// partitioned table's partitions are the `key=value` directories below that location, or the
/// bare-value ones under `format-table.partition-path-only-value`. A table is a format table when
/// its `type` option is `format-table`; `file.format` then names the format of every file in it,
/// defaulting to `parquet`.
///
/// Writes only insert - there is nowhere to record an update or a delete - so a read fills
/// `_VALUE_KIND` with inserts throughout.
///
/// Reading and writing go through the entry points every other table uses: `TableScan`,
/// `TableRead`, `FileStoreWrite` and `FileStoreCommit`. Each recognises a format table from the
/// schema under the table path, or takes one already loaded through the `FormatTable` constructor
/// every context builder has, which is how a table whose schema lives in a metastore is reached.
///
/// See `docs/source/user_guide/format_table.rst` for what is not supported yet.
class PAIMON_EXPORT FormatTable {
public:
/// Formats a format table's files can be in.
enum class Format {
PARQUET,
ORC,
};
/// Parses the `file.format` option, case-insensitively. A format this library has no reader
/// for is rejected by name, instead of failing later with a missing-format-factory error.
static Result<Format> ParseFormat(const std::string& file_format);
/// The identifier of a format, as it appears in `file.format` and as a file extension.
static std::string FormatToString(Format format);
/// Loads a format table from its directory, reading the schema stored under it.
///
/// This needs a schema file under the table directory, which a table created through
/// `SchemaManager` or a file system catalog has. A table whose schema lives in a metastore has
/// none, and is loaded through `Catalog::GetFormatTable()` instead.
///
/// @param file_system File system holding the table directory.
/// @param table_path Root path of the table, which is also its data location.
/// @param identifier Logical table identifier, used for naming and error messages.
/// @param dynamic_options Options given at the call, which win over the ones stored in the
/// schema. Empty when the caller has none.
/// @return A result containing the format table, or an error status.
static Result<std::shared_ptr<FormatTable>> Create(
const std::shared_ptr<FileSystem>& file_system, const std::string& table_path,
const Identifier& identifier, const std::map<std::string, std::string>& dynamic_options);
/// Builds a format table from a schema that is already loaded, for a caller that has one in
/// hand, such as a catalog that just created the table.
///
/// @param location Directory the data files live in. It may not be empty: every path this
/// table reads or writes is checked against it, and an empty one is a prefix of
/// nothing. A trailing separator names the same directory as none.
/// @param location_carries_paimon_metadata See `LocationCarriesPaimonMetadata()`. Only the
/// caller knows: a file system catalog puts metadata there, a REST or Hive catalog
/// keeps it in the metastore.
/// @param dynamic_options Options given at the call, which win over the ones stored in the
/// schema. Empty when the caller has none.
/// @return A result containing the format table, or an error status.
static Result<std::shared_ptr<FormatTable>> Create(
const std::shared_ptr<FileSystem>& file_system, const std::string& location,
const Identifier& identifier, const std::shared_ptr<DataSchema>& schema,
bool location_carries_paimon_metadata,
const std::map<std::string, std::string>& dynamic_options);
/// Copies `table` with `dynamic_options` on top of the options it already carries, which is
/// the precedence every context builder promises for a table it was handed rather than loaded
/// itself. `table` comes back as it is when there is nothing to add.
///
/// `type` is not overridable: it is structural and is read from the schema alone.
///
/// @param table The table to copy.
/// @param dynamic_options Options given at the call.
/// @return A result containing the copied table, or an error status.
static Result<std::shared_ptr<FormatTable>> Copy(
const std::shared_ptr<FormatTable>& table,
const std::map<std::string, std::string>& dynamic_options);
~FormatTable();
/// Directory the data files live in.
const std::string& Location() const {
return location_;
}
/// Format of every data file in the directory.
Format GetFormat() const {
return format_;
}
/// Fields the table is partitioned by, in the order their directories nest.
const std::vector<std::string>& PartitionKeys() const;
/// Compression new data files are written with. It is resolved from `file.compression`, then
/// `format-table.file.compression`, then the bare `compression` key an engine's own writer
/// reads, then what the table's format writes by default.
const std::string& FileCompression() const {
return file_compression_;
}
/// Directory name standing for a null partition value, from `partition.default-name`.
const std::string& PartitionDefaultName() const {
return partition_default_name_;
}
/// Whether a partition directory is named by its value alone (`2025/01/`) instead of
/// `key=value` (`year=2025/month=01/`), from `format-table.partition-path-only-value`. The
/// value-only layout carries no field names, so the nesting order of the table's partition
/// keys alone says which key a directory belongs to.
bool PartitionOnlyValueInPath() const {
return partition_only_value_in_path_;
}
/// Table options: the ones stored in the schema, with any given at the call on top.
const std::map<std::string, std::string>& Options() const {
return options_;
}
/// A name to identify this table.
std::string Name() const {
return identifier_.GetObjectName();
}
/// Full name of the table, database.tableName.
std::string FullName() const;
/// Schema of the table, including its partition fields.
std::shared_ptr<DataSchema> LatestSchema() const {
return schema_;
}
/// Schema of the table as an arrow schema, including its partition fields.
Result<std::unique_ptr<::ArrowSchema>> GetArrowSchema() const;
/// File system holding the table directory.
std::shared_ptr<FileSystem> GetFileSystem() const {
return file_system_;
}
/// Whether this table's own metadata lives under its location, as told by whoever loaded it.
///
/// Only then are the `schema` and `branch` directories below the location table metadata
/// rather than table content. For a table whose schema lives in a metastore they are data,
/// and are read and written like any other directory.
bool LocationCarriesPaimonMetadata() const {
return location_carries_paimon_metadata_;
}
private:
FormatTable(const std::shared_ptr<FileSystem>& file_system, const std::string& location,
const Identifier& identifier, const std::shared_ptr<DataSchema>& schema,
const std::map<std::string, std::string>& options, Format format,
const std::string& file_compression, const std::string& partition_default_name,
bool partition_only_value_in_path, bool location_carries_paimon_metadata);
std::shared_ptr<FileSystem> file_system_;
std::string location_;
Identifier identifier_;
std::shared_ptr<DataSchema> schema_;
std::map<std::string, std::string> options_;
Format format_;
std::string file_compression_;
std::string partition_default_name_;
bool partition_only_value_in_path_ = false;
bool location_carries_paimon_metadata_ = false;
};
} // namespace paimon