Skip to content

Commit 2cb7351

Browse files
committed
refactor(inspect): refine metadata table scan APIs
1 parent 69cfbe9 commit 2cb7351

10 files changed

Lines changed: 303 additions & 206 deletions

src/iceberg/inspect/history_table.cc

Lines changed: 14 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -26,37 +26,32 @@
2626
#include "iceberg/schema.h"
2727
#include "iceberg/schema_field.h"
2828
#include "iceberg/table.h"
29-
#include "iceberg/table_identifier.h"
3029
#include "iceberg/type.h"
30+
#include "iceberg/util/macros.h"
3131

3232
namespace iceberg {
33-
namespace {
3433

35-
std::shared_ptr<Schema> MakeHistoryTableSchema() {
36-
return std::make_shared<Schema>(std::vector<SchemaField>{
34+
HistoryTable::HistoryTable(std::shared_ptr<Table> table)
35+
: MetadataTable(std::move(table)) {}
36+
37+
HistoryTable::~HistoryTable() = default;
38+
39+
const std::shared_ptr<Schema>& HistoryTable::schema() const {
40+
static const auto schema = std::make_shared<Schema>(std::vector<SchemaField>{
3741
SchemaField::MakeRequired(1, "made_current_at", timestamp_tz()),
3842
SchemaField::MakeRequired(2, "snapshot_id", int64()),
3943
SchemaField::MakeOptional(3, "parent_id", int64()),
4044
SchemaField::MakeRequired(4, "is_current_ancestor", boolean())});
45+
return schema;
4146
}
4247

43-
TableIdentifier MakeHistoryTableName(const TableIdentifier& source_name) {
44-
return TableIdentifier{.ns = source_name.ns, .name = source_name.name + ".history"};
45-
}
46-
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-
5548
Result<std::unique_ptr<HistoryTable>> HistoryTable::Make(std::shared_ptr<Table> table) {
56-
if (table == nullptr) [[unlikely]] {
57-
return InvalidArgument("Table cannot be null");
58-
}
49+
ICEBERG_PRECHECK(table != nullptr, "Table cannot be null");
5950
return std::unique_ptr<HistoryTable>(new HistoryTable(std::move(table)));
6051
}
6152

53+
Result<ArrowArrayStream> HistoryTable::Scan() {
54+
return NotSupported("Scan is not supported for the history table");
55+
}
56+
6257
} // namespace iceberg

src/iceberg/inspect/history_table.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,10 @@ class ICEBERG_EXPORT HistoryTable : public MetadataTable {
4040

4141
Kind kind() const noexcept override { return Kind::kHistory; }
4242

43+
const std::shared_ptr<Schema>& schema() const override;
44+
45+
Result<ArrowArrayStream> Scan() override;
46+
4347
private:
4448
explicit HistoryTable(std::shared_ptr<Table> table);
4549
};

src/iceberg/inspect/metadata_table.cc

Lines changed: 16 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -22,40 +22,33 @@
2222
#include <memory>
2323
#include <utility>
2424

25-
#include "iceberg/inspect/history_table.h"
26-
#include "iceberg/inspect/snapshots_table.h"
27-
2825
namespace iceberg {
2926

30-
MetadataTable::MetadataTable(std::shared_ptr<Table> source_table,
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)) {}
27+
MetadataTable::MetadataTable(std::shared_ptr<Table> source_table)
28+
: source_table_(std::move(source_table)) {}
3529

3630
MetadataTable::~MetadataTable() = default;
3731

3832
bool MetadataTable::supports_time_travel() const noexcept { return false; }
3933

40-
Result<ArrowArray> MetadataTable::Scan(
41-
const std::optional<SnapshotSelection>& /*snapshot_selection*/) {
42-
return NotSupported("Scan is not supported for this metadata table type");
34+
const std::shared_ptr<Table>& MetadataTable::source_table() const {
35+
return source_table_;
4336
}
4437

45-
Result<std::unique_ptr<MetadataTable>> MetadataTable::Make(std::shared_ptr<Table> table,
46-
Kind kind) {
47-
if (table == nullptr) [[unlikely]] {
48-
return InvalidArgument("Table cannot be null");
49-
}
38+
TimeTravelMetadataTable::TimeTravelMetadataTable(std::shared_ptr<Table> source_table)
39+
: MetadataTable(std::move(source_table)) {}
40+
41+
TimeTravelMetadataTable::~TimeTravelMetadataTable() = default;
5042

51-
switch (kind) {
52-
case Kind::kSnapshots:
53-
return SnapshotsTable::Make(table);
54-
case Kind::kHistory:
55-
return HistoryTable::Make(table);
56-
}
43+
bool TimeTravelMetadataTable::supports_time_travel() const noexcept { return true; }
44+
45+
Result<ArrowArrayStream> TimeTravelMetadataTable::Scan() {
46+
return ScanSnapshot(SnapshotSelection{});
47+
}
5748

58-
return NotSupported("Unsupported metadata table type");
49+
Result<ArrowArrayStream> TimeTravelMetadataTable::Scan(
50+
const SnapshotSelection& snapshot_selection) {
51+
return ScanSnapshot(snapshot_selection);
5952
}
6053

6154
} // namespace iceberg

src/iceberg/inspect/metadata_table.h

Lines changed: 68 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -20,81 +20,109 @@
2020
#pragma once
2121

2222
/// \file iceberg/inspect/metadata_table.h
23-
/// \brief Define base APIs for metadata tables.
23+
/// \brief Base APIs for inspecting Iceberg metadata tables.
2424

25+
#include <concepts>
2526
#include <memory>
26-
#include <optional>
2727
#include <string>
28+
#include <utility>
29+
#include <variant>
2830

2931
#include "iceberg/arrow_c_data.h"
3032
#include "iceberg/iceberg_export.h"
3133
#include "iceberg/result.h"
32-
#include "iceberg/table_identifier.h"
3334
#include "iceberg/type_fwd.h"
3435
#include "iceberg/util/timepoint.h"
3536

3637
namespace iceberg {
3738

38-
/// \brief Parameters for snapshot selection (time travel).
39-
struct SnapshotSelection {
40-
/// \brief The snapshot ID to read.
41-
std::optional<int64_t> snapshot_id;
42-
/// \brief Read the snapshot that was current at this timestamp.
43-
std::optional<TimePointMs> as_of_timestamp;
44-
/// \brief Read the snapshot referenced by this named ref (branch or tag).
45-
std::optional<std::string> ref_name;
46-
};
47-
48-
/// \brief Base class for Iceberg metadata tables.
39+
/// \brief Base interface for an Iceberg metadata table.
4940
class ICEBERG_EXPORT MetadataTable {
5041
public:
42+
/// \brief Supported metadata table kinds.
5143
enum class Kind {
5244
kSnapshots,
5345
kHistory,
5446
};
5547

56-
static Result<std::unique_ptr<MetadataTable>> Make(std::shared_ptr<Table> table,
57-
Kind kind);
48+
/// \brief Maximum number of rows emitted in each Arrow batch.
49+
static constexpr int64_t kBatchSize = 1024;
5850

51+
/// \brief Create a metadata table of the requested concrete type.
52+
///
53+
/// \tparam MetadataTableType Concrete class derived from MetadataTable.
54+
/// \param table Source table whose metadata will be exposed.
55+
/// \return The constructed metadata table, or an error.
56+
template <typename MetadataTableType>
57+
requires std::derived_from<MetadataTableType, MetadataTable>
58+
static Result<std::unique_ptr<MetadataTableType>> Make(std::shared_ptr<Table> table) {
59+
return MetadataTableType::Make(std::move(table));
60+
}
61+
62+
/// \brief Destroy this metadata table.
5963
virtual ~MetadataTable();
6064

65+
/// \brief Return this metadata table's kind.
6166
virtual Kind kind() const noexcept = 0;
6267

63-
/// \brief Whether this metadata table supports time-travel queries.
64-
///
65-
/// The currently supported snapshots and history metadata tables do not
66-
/// support time travel.
67-
bool supports_time_travel() const noexcept;
68+
/// \brief Return the schema of rows emitted by scans.
69+
virtual const std::shared_ptr<Schema>& schema() const = 0;
70+
71+
/// \brief Return the source table whose metadata is exposed.
72+
const std::shared_ptr<Table>& source_table() const;
6873

69-
/// \brief Scan the metadata table using the current snapshot.
74+
/// \brief Return whether this metadata table supports time travel.
75+
virtual bool supports_time_travel() const noexcept;
76+
77+
/// \brief Scan the metadata table without time travel.
7078
///
71-
/// Convenience overload — delegates to Scan(std::nullopt).
72-
Result<ArrowArray> Scan() { return Scan(std::nullopt); }
79+
/// The caller owns the returned stream and must release it with
80+
/// ArrowArrayStreamRelease.
81+
virtual Result<ArrowArrayStream> Scan() = 0;
82+
83+
protected:
84+
explicit MetadataTable(std::shared_ptr<Table> source_table);
7385

74-
/// \brief Scan the metadata table and return all rows as an Arrow struct array.
86+
private:
87+
std::shared_ptr<Table> source_table_;
88+
};
89+
90+
/// \brief Snapshot selection parameters for a time-travel scan.
91+
struct SnapshotSelection {
92+
/// \brief Select the current snapshot, a snapshot ID, or an as-of timestamp.
7593
///
76-
/// The returned ArrowArray is a struct array where each element is one row.
77-
/// The caller takes ownership and must call ArrowArrayRelease when done.
94+
/// std::monostate selects the current snapshot.
95+
std::variant<std::monostate, int64_t, TimePointMs> snapshot;
96+
97+
/// \brief Resolve the snapshot relative to this branch or tag.
7898
///
79-
/// The default implementation returns NotSupported. Subclasses override this
80-
/// to materialize their data.
81-
virtual Result<ArrowArray> Scan(
82-
const std::optional<SnapshotSelection>& snapshot_selection);
99+
/// An empty string uses the main branch.
100+
std::string ref_name;
101+
};
83102

84-
const TableIdentifier& name() const { return identifier_; }
103+
/// \brief Base interface for metadata tables that support time travel.
104+
class ICEBERG_EXPORT TimeTravelMetadataTable : public MetadataTable {
105+
public:
106+
~TimeTravelMetadataTable() override;
107+
108+
/// \brief Return true because this interface supports time travel.
109+
bool supports_time_travel() const noexcept final;
85110

86-
const std::shared_ptr<Schema>& schema() const { return schema_; }
111+
/// \brief Scan using the current snapshot on the main branch.
112+
Result<ArrowArrayStream> Scan() final;
87113

88-
const std::shared_ptr<Table>& source_table() const { return source_table_; }
114+
/// \brief Scan using the requested snapshot selection.
115+
///
116+
/// \param snapshot_selection Snapshot ID, timestamp, and optional ref selection.
117+
/// \return An Arrow stream containing the metadata table rows, or an error.
118+
Result<ArrowArrayStream> Scan(const SnapshotSelection& snapshot_selection);
89119

90120
protected:
91-
explicit MetadataTable(std::shared_ptr<Table> source_table, TableIdentifier identifier,
92-
std::shared_ptr<Schema> schema);
121+
explicit TimeTravelMetadataTable(std::shared_ptr<Table> source_table);
93122

94-
private:
95-
TableIdentifier identifier_;
96-
std::shared_ptr<Schema> schema_;
97-
std::shared_ptr<Table> source_table_;
123+
/// \brief Implement a scan for the requested snapshot selection.
124+
virtual Result<ArrowArrayStream> ScanSnapshot(
125+
const SnapshotSelection& snapshot_selection) = 0;
98126
};
99127

100128
} // namespace iceberg

0 commit comments

Comments
 (0)