Skip to content

Commit 92fe7fe

Browse files
committed
polish and simplify metadata table design
1 parent 18ebed7 commit 92fe7fe

12 files changed

Lines changed: 175 additions & 291 deletions

src/iceberg/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,7 @@ add_subdirectory(puffin)
239239
add_subdirectory(row)
240240
add_subdirectory(update)
241241
add_subdirectory(util)
242+
add_subdirectory(inspect)
242243
add_subdirectory(metrics)
243244

244245
if(ICEBERG_BUILD_BUNDLE)

src/iceberg/inspect/history_table.cc

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -21,36 +21,42 @@
2121

2222
#include <memory>
2323
#include <utility>
24+
#include <vector>
2425

25-
#include "iceberg/inspect/metadata_table.h"
2626
#include "iceberg/schema.h"
2727
#include "iceberg/schema_field.h"
28+
#include "iceberg/table.h"
2829
#include "iceberg/table_identifier.h"
2930
#include "iceberg/type.h"
3031

3132
namespace iceberg {
32-
33-
HistoryTable::HistoryTable(std::shared_ptr<Table> table)
34-
: MetadataTable(table, CreateName(table->name())) {}
35-
36-
HistoryTable::~HistoryTable() = default;
37-
38-
std::shared_ptr<Schema> HistoryTable::GetSchema() const {
39-
return std::make_shared<Schema>(
40-
std::vector<SchemaField>{
41-
SchemaField::MakeRequired(1, "made_current_at", timestamp_tz()),
42-
SchemaField::MakeRequired(2, "snapshot_id", int64()),
43-
SchemaField::MakeOptional(3, "parent_id", int64()),
44-
SchemaField::MakeRequired(4, "is_current_ancestor", boolean())},
45-
1);
33+
namespace {
34+
35+
std::shared_ptr<Schema> MakeHistoryTableSchema() {
36+
return std::make_shared<Schema>(std::vector<SchemaField>{
37+
SchemaField::MakeRequired(1, "made_current_at", timestamp_tz()),
38+
SchemaField::MakeRequired(2, "snapshot_id", int64()),
39+
SchemaField::MakeOptional(3, "parent_id", int64()),
40+
SchemaField::MakeRequired(4, "is_current_ancestor", boolean())});
4641
}
4742

48-
TableIdentifier HistoryTable::CreateName(const TableIdentifier& source_name) {
43+
TableIdentifier MakeHistoryTableName(const TableIdentifier& source_name) {
4944
return TableIdentifier{.ns = source_name.ns, .name = source_name.name + ".history"};
5045
}
5146

47+
} // namespace
48+
49+
HistoryTable::HistoryTable(std::shared_ptr<Table> table)
50+
: MetadataTable(table, MakeHistoryTableName(table->name()),
51+
MakeHistoryTableSchema()) {}
52+
53+
HistoryTable::~HistoryTable() = default;
54+
5255
Result<std::unique_ptr<HistoryTable>> HistoryTable::Make(std::shared_ptr<Table> table) {
53-
return std::unique_ptr<HistoryTable>(new HistoryTable(table));
56+
if (table == nullptr) [[unlikely]] {
57+
return InvalidArgument("Table cannot be null");
58+
}
59+
return std::unique_ptr<HistoryTable>(new HistoryTable(std::move(table)));
5460
}
5561

5662
} // namespace iceberg

src/iceberg/inspect/history_table.h

Lines changed: 3 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -24,36 +24,21 @@
2424
#include "iceberg/iceberg_export.h"
2525
#include "iceberg/inspect/metadata_table.h"
2626
#include "iceberg/result.h"
27-
#include "iceberg/table.h"
27+
#include "iceberg/type_fwd.h"
2828

2929
namespace iceberg {
3030

31-
/// \brief History metadata table
32-
///
33-
/// History is based on the table's snapshot log, which logs each update
34-
/// to the table's current snapshot. Each row has columns:
35-
/// - made_current_at (long, timestamp)
36-
/// - snapshot_id (long)
37-
/// - parent_id (long, optional)
38-
/// - is_current_ancestor (bool)
31+
/// \brief History metadata table.
3932
class ICEBERG_EXPORT HistoryTable : public MetadataTable {
4033
public:
41-
/// \brief Create a HistoryTable from table metadata
42-
///
43-
/// \param[in] table The source table
44-
/// \return A HistoryTable instance or error status
4534
static Result<std::unique_ptr<HistoryTable>> Make(std::shared_ptr<Table> table);
4635

4736
~HistoryTable() override;
4837

49-
MetadataTableType type() const noexcept override { return MetadataTableType::kHistory; }
50-
51-
std::shared_ptr<Schema> GetSchema() const override;
38+
Kind kind() const noexcept override { return Kind::kHistory; }
5239

5340
private:
5441
explicit HistoryTable(std::shared_ptr<Table> table);
55-
56-
TableIdentifier CreateName(const TableIdentifier& source_name);
5742
};
5843

5944
} // namespace iceberg

src/iceberg/inspect/metadata_table.cc

Lines changed: 13 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -20,76 +20,35 @@
2020
#include "iceberg/inspect/metadata_table.h"
2121

2222
#include <memory>
23-
#include <string>
2423
#include <utility>
2524

26-
#include "iceberg/file_io.h"
2725
#include "iceberg/inspect/history_table.h"
2826
#include "iceberg/inspect/snapshots_table.h"
29-
#include "iceberg/partition_spec.h"
30-
#include "iceberg/schema.h"
31-
#include "iceberg/schema_field.h"
32-
#include "iceberg/sort_order.h"
33-
#include "iceberg/table_identifier.h"
34-
#include "iceberg/table_metadata.h"
35-
#include "iceberg/table_properties.h"
36-
#include "iceberg/table_scan.h"
37-
#include "iceberg/type.h"
38-
#include "iceberg/type_fwd.h"
39-
#include "iceberg/util/uuid.h"
4027

4128
namespace iceberg {
4229

4330
MetadataTable::MetadataTable(std::shared_ptr<Table> source_table,
44-
TableIdentifier identifier)
45-
: StaticTable(identifier, source_table->metadata(),
46-
std::string(source_table->metadata_file_location()), source_table->io(),
47-
source_table->catalog()),
48-
source_table_(std::move(source_table)) {
49-
auto schema = GetSchema();
50-
if (!schema) {
51-
schema = std::make_shared<Schema>(std::vector<SchemaField>{}, 1);
52-
}
53-
54-
auto builder =
55-
TableMetadataBuilder::BuildFromEmpty(TableMetadata::kDefaultTableFormatVersion);
56-
auto result = builder->AssignUUID(Uuid::GenerateV4().ToString())
57-
.SetLocation(std::string(source_table_->location()))
58-
.SetCurrentSchema(schema, schema->schema_id())
59-
.SetDefaultSortOrder(SortOrder::Unsorted())
60-
.SetDefaultPartitionSpec(PartitionSpec::Unpartitioned())
61-
.SetProperties({})
62-
.Build();
63-
64-
if (!result.has_value()) {
65-
// If metadata building fails, keep the original metadata from source_table
66-
return;
67-
}
68-
69-
std::shared_ptr<TableMetadata> built_metadata = std::move(result.value());
70-
71-
metadata_ = built_metadata;
72-
metadata_cache_ = std::make_unique<TableMetadataCache>(metadata_.get());
73-
}
31+
TableIdentifier identifier, std::shared_ptr<Schema> schema)
32+
: identifier_(std::move(identifier)),
33+
schema_(std::move(schema)),
34+
source_table_(std::move(source_table)) {}
7435

7536
MetadataTable::~MetadataTable() = default;
7637

77-
Status MetadataTable::Refresh() { return source_table_->Refresh(); }
78-
79-
Result<std::unique_ptr<DataTableScanBuilder>> MetadataTable::NewScan() const {
80-
return NotSupported("TODO: Scanning metadata tables is not yet supported");
81-
};
38+
Result<std::unique_ptr<MetadataTable>> MetadataTable::Make(std::shared_ptr<Table> table,
39+
Kind kind) {
40+
if (table == nullptr) [[unlikely]] {
41+
return InvalidArgument("Table cannot be null");
42+
}
8243

83-
Result<std::unique_ptr<MetadataTable>> MetadataTableFactory::CreateMetadataTable(
84-
std::shared_ptr<Table> table, MetadataTableType type) {
85-
switch (type) {
86-
case MetadataTableType::kSnapshots:
44+
switch (kind) {
45+
case Kind::kSnapshots:
8746
return SnapshotsTable::Make(table);
88-
case MetadataTableType::kHistory:
47+
case Kind::kHistory:
8948
return HistoryTable::Make(table);
9049
}
9150

92-
return Invalid("Unsupported metadata table type");
51+
return NotSupported("Unsupported metadata table type");
9352
}
9453

9554
} // namespace iceberg

src/iceberg/inspect/metadata_table.h

Lines changed: 19 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -20,122 +20,43 @@
2020
#pragma once
2121

2222
#include <memory>
23-
#include <string>
2423

2524
#include "iceberg/iceberg_export.h"
26-
#include "iceberg/location_provider.h"
2725
#include "iceberg/result.h"
28-
#include "iceberg/sort_order.h"
29-
#include "iceberg/table.h"
30-
#include "iceberg/table_metadata.h"
31-
#include "iceberg/table_scan.h"
26+
#include "iceberg/table_identifier.h"
3227
#include "iceberg/type_fwd.h"
3328

3429
namespace iceberg {
3530

36-
/// \brief The type of metadata table
37-
enum class MetadataTableType {
38-
kSnapshots,
39-
kHistory,
40-
};
41-
42-
/// \brief Base class for Iceberg metadata tables
43-
///
44-
/// Metadata tables expose table metadata as queryable tables with schemas and scan
45-
/// support. They provide read-only access to metadata.
46-
class ICEBERG_EXPORT MetadataTable : public StaticTable {
31+
/// \brief Base class for Iceberg metadata tables.
32+
class ICEBERG_EXPORT MetadataTable {
4733
public:
48-
virtual MetadataTableType type() const noexcept = 0;
49-
50-
/// \brief Returns the table's metadata file location
51-
std::string_view metadata_file_location() const {
52-
return source_table_->metadata_file_location();
53-
}
54-
55-
/// \brief Returns the table's base location
56-
std::string_view location() const { return source_table_->location(); }
57-
58-
/// \brief Returns the time when this table was last updated
59-
TimePointMs last_updated_ms() const { return source_table_->last_updated_ms(); }
60-
61-
/// \brief Returns the table's current snapshot, return NotFoundError if not found
62-
Result<std::shared_ptr<Snapshot>> current_snapshot() const {
63-
return source_table_->current_snapshot();
64-
}
34+
enum class Kind {
35+
kSnapshots,
36+
kHistory,
37+
};
6538

66-
/// \brief Get the snapshot of this table with the given id
67-
///
68-
/// \param snapshot_id the ID of the snapshot to get
69-
/// \return the Snapshot with the given id, return NotFoundError if not found
70-
Result<std::shared_ptr<Snapshot>> SnapshotById(int64_t snapshot_id) const {
71-
return source_table_->SnapshotById(snapshot_id);
72-
}
39+
static Result<std::unique_ptr<MetadataTable>> Make(std::shared_ptr<Table> table,
40+
Kind kind);
7341

74-
/// \brief Get the snapshots of this table
75-
const std::vector<std::shared_ptr<Snapshot>>& snapshots() const {
76-
return source_table_->snapshots();
77-
}
42+
virtual ~MetadataTable();
7843

79-
/// \brief Get the snapshot history of this table
80-
const std::vector<SnapshotLogEntry>& history() const {
81-
return source_table_->history();
82-
}
44+
virtual Kind kind() const noexcept = 0;
8345

84-
/// \brief Returns the catalog that this table belongs to
85-
const std::shared_ptr<Catalog>& catalog() const { return source_table_->catalog(); }
46+
const TableIdentifier& name() const { return identifier_; }
8647

87-
/// \brief Returns a LocationProvider for this table
88-
Result<std::unique_ptr<LocationProvider>> location_provider() const {
89-
return source_table_->location_provider();
90-
}
48+
const std::shared_ptr<Schema>& schema() const { return schema_; }
9149

92-
/// \brief Refreshing is not supported in metadata tables.
93-
Status Refresh() override;
94-
95-
/// \brief Create a new table scan builder for this table
96-
///
97-
/// Once a table scan builder is created, it can be refined to project columns and
98-
/// filter data.
99-
Result<std::unique_ptr<DataTableScanBuilder>> NewScan() const override;
100-
101-
~MetadataTable();
50+
const std::shared_ptr<Table>& source_table() const { return source_table_; }
10251

10352
protected:
104-
explicit MetadataTable(std::shared_ptr<Table> source_table, TableIdentifier identifier);
105-
106-
/// \brief Returns the schema for this metadata table
107-
///
108-
/// Subclasses override this method to provide their custom schema during
109-
/// MetadataTable construction. The returned schema is used to initialize
110-
/// the underlying TableMetadata.
111-
///
112-
/// \return The schema for this metadata table, or nullptr for default schema
113-
virtual std::shared_ptr<Schema> GetSchema() const { return nullptr; }
53+
explicit MetadataTable(std::shared_ptr<Table> source_table, TableIdentifier identifier,
54+
std::shared_ptr<Schema> schema);
11455

56+
private:
57+
TableIdentifier identifier_;
58+
std::shared_ptr<Schema> schema_;
11559
std::shared_ptr<Table> source_table_;
11660
};
11761

118-
/// \brief Metadata table factory and inspector
119-
///
120-
/// MetadataTable provides factory methods to create specific metadata tables for
121-
/// inspecting table metadata. Each metadata table exposes a different aspect of the
122-
/// table's metadata as a scannable Iceberg table.
123-
///
124-
/// Usage:
125-
/// auto metadata_table = ICEBERG_TRY(
126-
/// MetadataTableFactory::CreateMetadataTable(
127-
/// table, MetadataTableType::kSnapshots));
128-
/// auto scan = ICEBERG_TRY(metadata_table->NewScan());
129-
/// // ... scan and read metadata table data
130-
class ICEBERG_EXPORT MetadataTableFactory {
131-
public:
132-
/// \brief Create a metadata table from a table
133-
///
134-
/// \param table The source table
135-
/// \param type The metadata table type to create
136-
/// \return A MetadataTable instance or error status
137-
static Result<std::unique_ptr<MetadataTable>> CreateMetadataTable(
138-
std::shared_ptr<Table> table, MetadataTableType type);
139-
};
140-
14162
} // namespace iceberg

0 commit comments

Comments
 (0)