Skip to content

Commit 89388f2

Browse files
author
shuxu.li
committed
static table metadata access support
1 parent f48c326 commit 89388f2

File tree

10 files changed

+138
-84
lines changed

10 files changed

+138
-84
lines changed

src/iceberg/table.cc

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ BaseTable::BaseTable(std::string name, std::shared_ptr<TableMetadata> metadata)
4040

4141
void BaseTable::InitSchema() const {
4242
for (const auto& schema : metadata_->schemas) {
43-
if (schema->schema_id() != std::nullopt) {
43+
if (schema->schema_id()) {
4444
schemas_map_.emplace(schema->schema_id().value(), schema);
4545
if (schema->schema_id().value() == metadata_->current_schema_id) {
4646
schema_ = schema;
@@ -83,10 +83,10 @@ void BaseTable::InitSnapshot() const {
8383

8484
const std::string& BaseTable::uuid() const { return metadata_->table_uuid; }
8585

86-
const std::shared_ptr<Schema>& BaseTable::schema() const {
86+
Result<std::shared_ptr<Schema>> BaseTable::schema() const {
8787
std::call_once(init_schema_once_, [this]() { InitSchema(); });
8888
if (!schema_) {
89-
throw IcebergError("Current schema is not defined for this table");
89+
return NotFound("Current schema is not defined for this table");
9090
}
9191
return schema_;
9292
}
@@ -96,8 +96,11 @@ const std::unordered_map<int32_t, std::shared_ptr<Schema>>& BaseTable::schemas()
9696
return schemas_map_;
9797
}
9898

99-
const std::shared_ptr<PartitionSpec>& BaseTable::spec() const {
99+
Result<std::shared_ptr<PartitionSpec>> BaseTable::spec() const {
100100
std::call_once(init_partition_spec_once_, [this]() { InitPartitionSpec(); });
101+
if (!partition_spec_) {
102+
return NotFound("Default partition spec is not defined for this table");
103+
}
101104
return partition_spec_;
102105
}
103106

@@ -107,8 +110,11 @@ const std::unordered_map<int32_t, std::shared_ptr<PartitionSpec>>& BaseTable::sp
107110
return partition_spec_map_;
108111
}
109112

110-
const std::shared_ptr<SortOrder>& BaseTable::sort_order() const {
113+
Result<std::shared_ptr<SortOrder>> BaseTable::sort_order() const {
111114
std::call_once(init_sort_order_once_, [this]() { InitSortOrder(); });
115+
if (!sort_order_) {
116+
return NotFound("Default sort order is not defined for this table");
117+
}
112118
return sort_order_;
113119
}
114120

@@ -124,10 +130,10 @@ const std::unordered_map<std::string, std::string>& BaseTable::properties() cons
124130

125131
const std::string& BaseTable::location() const { return metadata_->location; }
126132

127-
const std::shared_ptr<Snapshot>& BaseTable::current_snapshot() const {
133+
Result<std::shared_ptr<Snapshot>> BaseTable::current_snapshot() const {
128134
std::call_once(init_snapshot_once_, [this]() { InitSnapshot(); });
129135
if (!current_snapshot_) {
130-
throw IcebergError("Current snapshot is not defined for this table");
136+
return NotFound("Current snapshot is not defined for this table");
131137
}
132138
return current_snapshot_;
133139
}
@@ -147,27 +153,27 @@ const std::vector<std::shared_ptr<Snapshot>>& BaseTable::snapshots() const {
147153

148154
const std::vector<std::shared_ptr<HistoryEntry>>& BaseTable::history() const {
149155
// TODO(lishuxu): Implement history retrieval
150-
throw IcebergError("history is not supported for BaseTable now");
156+
return history_;
151157
}
152158

153159
Status StaticTable::Refresh() {
154-
throw IcebergError("Refresh is not supported for StaticTable");
160+
return NotSupported("Refresh is not supported for StaticTable");
155161
}
156162

157-
std::unique_ptr<TableScan> StaticTable::NewScan() const {
158-
throw IcebergError("NewScan is not supported for StaticTable");
163+
Result<std::unique_ptr<TableScan>> StaticTable::NewScan() const {
164+
return NotSupported("NewScan is not supported for StaticTable");
159165
}
160166

161-
std::shared_ptr<AppendFiles> StaticTable::NewAppend() {
162-
throw IcebergError("NewAppend is not supported for StaticTable");
167+
Result<std::shared_ptr<AppendFiles>> StaticTable::NewAppend() {
168+
return NotSupported("NewAppend is not supported for StaticTable");
163169
}
164170

165-
std::unique_ptr<Transaction> StaticTable::NewTransaction() {
166-
throw IcebergError("NewTransaction is not supported for StaticTable");
171+
Result<std::unique_ptr<Transaction>> StaticTable::NewTransaction() {
172+
return NotSupported("NewTransaction is not supported for StaticTable");
167173
}
168174

169-
std::unique_ptr<LocationProvider> StaticTable::location_provider() const {
170-
throw IcebergError("location_provider is not supported for StaticTable");
175+
Result<std::unique_ptr<LocationProvider>> StaticTable::location_provider() const {
176+
return NotSupported("location_provider is not supported for StaticTable");
171177
}
172178

173179
} // namespace iceberg

src/iceberg/table.h

Lines changed: 38 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,10 @@
2626
#include <vector>
2727

2828
#include "iceberg/iceberg_export.h"
29+
#include "iceberg/location_provider.h"
2930
#include "iceberg/result.h"
31+
#include "iceberg/table_scan.h"
32+
#include "iceberg/transaction.h"
3033
#include "iceberg/type_fwd.h"
3134

3235
namespace iceberg {
@@ -45,21 +48,21 @@ class ICEBERG_EXPORT Table {
4548
/// \brief Refresh the current table metadata
4649
virtual Status Refresh() = 0;
4750

48-
/// \brief Return the schema for this table
49-
virtual const std::shared_ptr<Schema>& schema() const = 0;
51+
/// \brief Return the schema for this table, return NotFoundError if not found
52+
virtual Result<std::shared_ptr<Schema>> schema() const = 0;
5053

5154
/// \brief Return a map of schema for this table
5255
virtual const std::unordered_map<int32_t, std::shared_ptr<Schema>>& schemas() const = 0;
5356

54-
/// \brief Return the partition spec for this table
55-
virtual const std::shared_ptr<PartitionSpec>& spec() const = 0;
57+
/// \brief Return the partition spec for this table, return NotFoundError if not found
58+
virtual Result<std::shared_ptr<PartitionSpec>> spec() const = 0;
5659

5760
/// \brief Return a map of partition specs for this table
5861
virtual const std::unordered_map<int32_t, std::shared_ptr<PartitionSpec>>& specs()
5962
const = 0;
6063

61-
/// \brief Return the sort order for this table
62-
virtual const std::shared_ptr<SortOrder>& sort_order() const = 0;
64+
/// \brief Return the sort order for this table, return NotFoundError if not found
65+
virtual Result<std::shared_ptr<SortOrder>> sort_order() const = 0;
6366

6467
/// \brief Return a map of sort order IDs to sort orders for this table
6568
virtual const std::unordered_map<int32_t, std::shared_ptr<SortOrder>>& sort_orders()
@@ -71,8 +74,8 @@ class ICEBERG_EXPORT Table {
7174
/// \brief Return the table's base location
7275
virtual const std::string& location() const = 0;
7376

74-
/// \brief Return the table's current snapshot
75-
virtual const std::shared_ptr<Snapshot>& current_snapshot() const = 0;
77+
/// \brief Return the table's current snapshot, or NotFoundError if not found
78+
virtual Result<std::shared_ptr<Snapshot>> current_snapshot() const = 0;
7679

7780
/// \brief Get the snapshot of this table with the given id, or null if there is no
7881
/// matching snapshot
@@ -92,42 +95,51 @@ class ICEBERG_EXPORT Table {
9295
/// \brief Create a new table scan for this table
9396
///
9497
/// Once a table scan is created, it can be refined to project columns and filter data.
95-
virtual std::unique_ptr<TableScan> NewScan() const = 0;
98+
virtual Result<std::unique_ptr<TableScan>> NewScan() const = 0;
9699

97100
/// \brief Create a new append API to add files to this table and commit
98-
virtual std::shared_ptr<AppendFiles> NewAppend() = 0;
101+
virtual Result<std::shared_ptr<AppendFiles>> NewAppend() = 0;
99102

100103
/// \brief Create a new transaction API to commit multiple table operations at once
101-
virtual std::unique_ptr<Transaction> NewTransaction() = 0;
104+
virtual Result<std::unique_ptr<Transaction>> NewTransaction() = 0;
102105

103106
/// TODO(wgtmac): design of FileIO is not finalized yet. We intend to use an
104107
/// IO-less design in the core library.
105108
// /// \brief Returns a FileIO to read and write table data and metadata files
106109
// virtual std::shared_ptr<FileIO> io() const = 0;
107110

108111
/// \brief Returns a LocationProvider to provide locations for new data files
109-
virtual std::unique_ptr<LocationProvider> location_provider() const = 0;
112+
virtual Result<std::unique_ptr<LocationProvider>> location_provider() const = 0;
110113
};
111114

115+
/// \brief An abstract base implementation of the Iceberg Table interface.
116+
///
117+
/// BaseTable provides common functionality for Iceberg table implementations,
118+
/// including lazy initialization of schema, partition specs, sort orders,
119+
/// and snapshot metadata.
120+
///
121+
/// This class is not intended to be used directly by users, but serves as a foundation
122+
/// for concrete implementations such as StaticTable or CatalogTable.
112123
class ICEBERG_EXPORT BaseTable : public Table {
113124
public:
114125
~BaseTable() override = default;
126+
115127
BaseTable(std::string name, std::shared_ptr<TableMetadata> metadata);
116128

117129
const std::string& name() const override { return name_; }
118130

119131
const std::string& uuid() const override;
120132

121-
const std::shared_ptr<Schema>& schema() const override;
133+
Result<std::shared_ptr<Schema>> schema() const override;
122134

123135
const std::unordered_map<int32_t, std::shared_ptr<Schema>>& schemas() const override;
124136

125-
const std::shared_ptr<PartitionSpec>& spec() const override;
137+
Result<std::shared_ptr<PartitionSpec>> spec() const override;
126138

127139
const std::unordered_map<int32_t, std::shared_ptr<PartitionSpec>>& specs()
128140
const override;
129141

130-
const std::shared_ptr<SortOrder>& sort_order() const override;
142+
Result<std::shared_ptr<SortOrder>> sort_order() const override;
131143

132144
const std::unordered_map<int32_t, std::shared_ptr<SortOrder>>& sort_orders()
133145
const override;
@@ -136,7 +148,7 @@ class ICEBERG_EXPORT BaseTable : public Table {
136148

137149
const std::string& location() const override;
138150

139-
const std::shared_ptr<Snapshot>& current_snapshot() const override;
151+
Result<std::shared_ptr<Snapshot>> current_snapshot() const override;
140152

141153
Result<std::shared_ptr<Snapshot>> snapshot(int64_t snapshot_id) const override;
142154

@@ -164,6 +176,8 @@ class ICEBERG_EXPORT BaseTable : public Table {
164176
mutable std::shared_ptr<Snapshot> current_snapshot_;
165177
mutable std::unordered_map<int64_t, std::shared_ptr<Snapshot>> snapshots_map_;
166178

179+
mutable std::vector<std::shared_ptr<HistoryEntry>> history_;
180+
167181
std::shared_ptr<TableMetadata> metadata_;
168182

169183
// once_flags
@@ -173,21 +187,25 @@ class ICEBERG_EXPORT BaseTable : public Table {
173187
mutable std::once_flag init_snapshot_once_;
174188
};
175189

190+
/// \brief A read-only implementation of an Iceberg table.
191+
///
192+
/// StaticTable represents a snapshot of a table that does not support mutation.
176193
class ICEBERG_EXPORT StaticTable : public BaseTable {
177194
public:
178195
~StaticTable() override = default;
196+
179197
StaticTable(std::string name, std::shared_ptr<TableMetadata> metadata)
180198
: BaseTable(std::move(name), std::move(metadata)) {}
181199

182200
Status Refresh() override;
183201

184-
std::unique_ptr<TableScan> NewScan() const override;
202+
Result<std::unique_ptr<TableScan>> NewScan() const override;
185203

186-
std::shared_ptr<AppendFiles> NewAppend() override;
204+
Result<std::shared_ptr<AppendFiles>> NewAppend() override;
187205

188-
std::unique_ptr<Transaction> NewTransaction() override;
206+
Result<std::unique_ptr<Transaction>> NewTransaction() override;
189207

190-
std::unique_ptr<LocationProvider> location_provider() const override;
208+
Result<std::unique_ptr<LocationProvider>> location_provider() const override;
191209
};
192210

193211
} // namespace iceberg

src/iceberg/table_metadata.cc

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,19 @@ Result<std::shared_ptr<SortOrder>> TableMetadata::SortOrder() const {
7676
return *iter;
7777
}
7878

79+
Result<std::shared_ptr<Snapshot>> TableMetadata::Snapshot() const {
80+
if (current_snapshot_id == Snapshot::kInvalidSnapshotId) {
81+
return NotFound("Current snapshot is not defined for this table");
82+
}
83+
auto iter = std::ranges::find_if(snapshots, [this](const auto& snapshot) {
84+
return snapshot->snapshot_id == current_snapshot_id;
85+
});
86+
if (iter == snapshots.end()) {
87+
return NotFound("Current snapshot with ID {} is not found", current_snapshot_id);
88+
}
89+
return *iter;
90+
}
91+
7992
namespace {
8093

8194
template <typename T>

src/iceberg/table_metadata.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,8 @@ struct ICEBERG_EXPORT TableMetadata {
133133
Result<std::shared_ptr<PartitionSpec>> PartitionSpec() const;
134134
/// \brief Get the current sort order, return NotFoundError if not found
135135
Result<std::shared_ptr<SortOrder>> SortOrder() const;
136+
/// \brief Get the current snapshot, return NotFoundError if not found
137+
Result<std::shared_ptr<Snapshot>> Snapshot() const;
136138

137139
friend bool operator==(const TableMetadata& lhs, const TableMetadata& rhs);
138140

src/iceberg/table_scan.h

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
#pragma once
21+
22+
namespace iceberg {
23+
24+
/// \brief Represents a table scan operation
25+
class ICEBERG_EXPORT TableScan{};
26+
27+
} // namespace iceberg

test/CMakeLists.txt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,8 @@ add_test(NAME schema_test COMMAND schema_test)
4646

4747
add_executable(table_test)
4848
target_include_directories(table_test PRIVATE "${CMAKE_BINARY_DIR}")
49-
target_sources(table_test PRIVATE table_test_helper.cc json_internal_test.cc
50-
table_test.cc schema_json_test.cc)
49+
target_sources(table_test PRIVATE test_common.cc json_internal_test.cc table_test.cc
50+
schema_json_test.cc)
5151
target_link_libraries(table_test PRIVATE iceberg_static GTest::gtest_main GTest::gmock)
5252
add_test(NAME table_test COMMAND table_test)
5353

@@ -59,7 +59,7 @@ add_test(NAME expression_test COMMAND expression_test)
5959

6060
add_executable(json_serde_test)
6161
target_include_directories(json_serde_test PRIVATE "${CMAKE_BINARY_DIR}")
62-
target_sources(json_serde_test PRIVATE table_test_helper.cc json_internal_test.cc
62+
target_sources(json_serde_test PRIVATE test_common.cc json_internal_test.cc
6363
metadata_serde_test.cc schema_json_test.cc)
6464
target_link_libraries(json_serde_test PRIVATE iceberg_static GTest::gtest_main
6565
GTest::gmock)

test/metadata_serde_test.cc

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
#include "iceberg/table_metadata.h"
3636
#include "iceberg/transform.h"
3737
#include "iceberg/type.h"
38-
#include "table_test_helper.h"
38+
#include "test_common.h"
3939

4040
namespace iceberg {
4141

@@ -51,7 +51,7 @@ class MetadataSerdeTest : public ::testing::Test {
5151
TEST_F(MetadataSerdeTest, DeserializeV1Valid) {
5252
std::unique_ptr<TableMetadata> metadata;
5353
ASSERT_NO_FATAL_FAILURE(
54-
TableTestHelper::ReadTableMetadata("TableMetadataV1Valid.json", &metadata));
54+
test::ReadTableMetadata("TableMetadataV1Valid.json", &metadata));
5555

5656
EXPECT_EQ(metadata->format_version, 1);
5757
EXPECT_EQ(metadata->table_uuid, "d20125c8-7284-442c-9aea-15fee620737c");
@@ -89,7 +89,7 @@ TEST_F(MetadataSerdeTest, DeserializeV1Valid) {
8989
TEST_F(MetadataSerdeTest, DeserializeV2Valid) {
9090
std::unique_ptr<TableMetadata> metadata;
9191
ASSERT_NO_FATAL_FAILURE(
92-
TableTestHelper::ReadTableMetadata("TableMetadataV2Valid.json", &metadata));
92+
test::ReadTableMetadata("TableMetadataV2Valid.json", &metadata));
9393

9494
EXPECT_EQ(metadata->format_version, 2);
9595
EXPECT_EQ(metadata->table_uuid, "9c12d441-03fe-4693-9a96-a0705ddf69c1");

0 commit comments

Comments
 (0)