Skip to content

Commit 7933a27

Browse files
author
shuxu.li
committed
static table metadata access support
1 parent 08da3a9 commit 7933a27

File tree

8 files changed

+476
-33
lines changed

8 files changed

+476
-33
lines changed

src/iceberg/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ set(ICEBERG_SOURCES
3737
sort_field.cc
3838
sort_order.cc
3939
statistics_file.cc
40+
table.cc
4041
table_metadata.cc
4142
transform.cc
4243
transform_function.cc

src/iceberg/table.cc

Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
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+
#include "iceberg/table.h"
21+
22+
#include <iostream>
23+
24+
#include "iceberg/exception.h"
25+
#include "iceberg/partition_spec.h"
26+
#include "iceberg/result.h"
27+
#include "iceberg/schema.h"
28+
#include "iceberg/snapshot.h"
29+
#include "iceberg/sort_order.h"
30+
#include "iceberg/table_metadata.h"
31+
32+
namespace iceberg {
33+
34+
BaseTable::BaseTable(std::string name, std::shared_ptr<TableMetadata> metadata)
35+
: name_(std::move(name)), metadata_(std::move(metadata)) {
36+
if (!metadata_) {
37+
throw std::invalid_argument("Table metadata cannot be null");
38+
}
39+
}
40+
41+
void BaseTable::InitSchema() const {
42+
for (const auto& schema : metadata_->schemas) {
43+
if (schema->schema_id() != std::nullopt) {
44+
schemas_map_.emplace(schema->schema_id().value(), schema);
45+
if (schema->schema_id().value() == metadata_->current_schema_id) {
46+
schema_ = schema;
47+
}
48+
}
49+
}
50+
// compatible with V1 table schema
51+
if (!schema_ && metadata_->schemas.size() == 1UL) {
52+
schema_ = metadata_->schemas.front();
53+
}
54+
}
55+
56+
void BaseTable::InitPartitionSpec() const {
57+
for (const auto& spec : metadata_->partition_specs) {
58+
partition_spec_map_[spec->spec_id()] = spec;
59+
if (spec->spec_id() == metadata_->default_spec_id) {
60+
partition_spec_ = spec;
61+
}
62+
}
63+
}
64+
65+
void BaseTable::InitSortOrder() const {
66+
for (const auto& order : metadata_->sort_orders) {
67+
sort_orders_map_[order->order_id()] = order;
68+
if (order->order_id() == metadata_->default_sort_order_id) {
69+
sort_order_ = order;
70+
}
71+
}
72+
}
73+
74+
void BaseTable::InitSnapshot() const {
75+
auto snapshots = metadata_->snapshots;
76+
for (const auto& snapshot : snapshots) {
77+
if (snapshot->snapshot_id == metadata_->current_snapshot_id) {
78+
current_snapshot_ = snapshot;
79+
}
80+
snapshots_map_[snapshot->snapshot_id] = snapshot;
81+
}
82+
}
83+
84+
const std::string& BaseTable::uuid() const { return metadata_->table_uuid; }
85+
86+
const std::shared_ptr<Schema>& BaseTable::schema() const {
87+
std::call_once(init_schema_once_, [this]() { InitSchema(); });
88+
if (!schema_) {
89+
throw IcebergError("Current schema is not defined for this table");
90+
}
91+
return schema_;
92+
}
93+
94+
const std::unordered_map<int32_t, std::shared_ptr<Schema>>& BaseTable::schemas() const {
95+
std::call_once(init_schema_once_, [this]() { InitSchema(); });
96+
return schemas_map_;
97+
}
98+
99+
const std::shared_ptr<PartitionSpec>& BaseTable::spec() const {
100+
std::call_once(init_partition_spec_once_, [this]() { InitPartitionSpec(); });
101+
return partition_spec_;
102+
}
103+
104+
const std::unordered_map<int32_t, std::shared_ptr<PartitionSpec>>& BaseTable::specs()
105+
const {
106+
std::call_once(init_partition_spec_once_, [this]() { InitPartitionSpec(); });
107+
return partition_spec_map_;
108+
}
109+
110+
const std::shared_ptr<SortOrder>& BaseTable::sort_order() const {
111+
std::call_once(init_sort_order_once_, [this]() { InitSortOrder(); });
112+
return sort_order_;
113+
}
114+
115+
const std::unordered_map<int32_t, std::shared_ptr<SortOrder>>& BaseTable::sort_orders()
116+
const {
117+
std::call_once(init_sort_order_once_, [this]() { InitSortOrder(); });
118+
return sort_orders_map_;
119+
}
120+
121+
const std::unordered_map<std::string, std::string>& BaseTable::properties() const {
122+
return metadata_->properties;
123+
}
124+
125+
const std::string& BaseTable::location() const { return metadata_->location; }
126+
127+
const std::shared_ptr<Snapshot>& BaseTable::current_snapshot() const {
128+
std::call_once(init_snapshot_once_, [this]() { InitSnapshot(); });
129+
if (!current_snapshot_) {
130+
throw IcebergError("Current snapshot is not defined for this table");
131+
}
132+
return current_snapshot_;
133+
}
134+
135+
Result<std::shared_ptr<Snapshot>> BaseTable::snapshot(int64_t snapshot_id) const {
136+
std::call_once(init_snapshot_once_, [this]() { InitSnapshot(); });
137+
auto iter = snapshots_map_.find(snapshot_id);
138+
if (iter == snapshots_map_.end()) {
139+
return NotFound("Snapshot with ID {} not found", snapshot_id);
140+
}
141+
return iter->second;
142+
}
143+
144+
const std::vector<std::shared_ptr<Snapshot>>& BaseTable::snapshots() const {
145+
return metadata_->snapshots;
146+
}
147+
148+
const std::vector<std::shared_ptr<HistoryEntry>>& BaseTable::history() const {
149+
// TODO: Implement history retrieval
150+
throw IcebergError("history is not supported for BaseTable now");
151+
}
152+
153+
Status StaticTable::Refresh() {
154+
throw IcebergError("Refresh is not supported for StaticTable");
155+
}
156+
157+
std::unique_ptr<TableScan> StaticTable::NewScan() const {
158+
throw IcebergError("NewScan is not supported for StaticTable");
159+
}
160+
161+
std::shared_ptr<AppendFiles> StaticTable::NewAppend() {
162+
throw IcebergError("NewAppend is not supported for StaticTable");
163+
}
164+
165+
std::unique_ptr<Transaction> StaticTable::NewTransaction() {
166+
throw IcebergError("NewTransaction is not supported for StaticTable");
167+
}
168+
169+
std::unique_ptr<LocationProvider> StaticTable::location_provider() const {
170+
throw IcebergError("location_provider is not supported for StaticTable");
171+
}
172+
173+
} // namespace iceberg

src/iceberg/table.h

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,4 +108,85 @@ class ICEBERG_EXPORT Table {
108108
virtual std::unique_ptr<LocationProvider> location_provider() const = 0;
109109
};
110110

111+
class ICEBERG_EXPORT BaseTable : public Table {
112+
public:
113+
virtual ~BaseTable() override = default;
114+
BaseTable(std::string name, std::shared_ptr<TableMetadata> metadata);
115+
116+
const std::string& name() const override { return name_; }
117+
118+
const std::string& uuid() const override;
119+
120+
const std::shared_ptr<Schema>& schema() const override;
121+
122+
const std::unordered_map<int32_t, std::shared_ptr<Schema>>& schemas() const override;
123+
124+
const std::shared_ptr<PartitionSpec>& spec() const override;
125+
126+
const std::unordered_map<int32_t, std::shared_ptr<PartitionSpec>>& specs()
127+
const override;
128+
129+
const std::shared_ptr<SortOrder>& sort_order() const override;
130+
131+
const std::unordered_map<int32_t, std::shared_ptr<SortOrder>>& sort_orders()
132+
const override;
133+
134+
const std::unordered_map<std::string, std::string>& properties() const override;
135+
136+
const std::string& location() const override;
137+
138+
const std::shared_ptr<Snapshot>& current_snapshot() const override;
139+
140+
Result<std::shared_ptr<Snapshot>> snapshot(int64_t snapshot_id) const override;
141+
142+
const std::vector<std::shared_ptr<Snapshot>>& snapshots() const override;
143+
144+
const std::vector<std::shared_ptr<HistoryEntry>>& history() const override;
145+
146+
private:
147+
void InitSchema() const;
148+
void InitPartitionSpec() const;
149+
void InitSortOrder() const;
150+
void InitSnapshot() const;
151+
152+
const std::string name_;
153+
154+
mutable std::shared_ptr<Schema> schema_;
155+
mutable std::unordered_map<int32_t, std::shared_ptr<Schema>> schemas_map_;
156+
157+
mutable std::shared_ptr<PartitionSpec> partition_spec_;
158+
mutable std::unordered_map<int32_t, std::shared_ptr<PartitionSpec>> partition_spec_map_;
159+
160+
mutable std::shared_ptr<SortOrder> sort_order_;
161+
mutable std::unordered_map<int32_t, std::shared_ptr<SortOrder>> sort_orders_map_;
162+
163+
mutable std::shared_ptr<Snapshot> current_snapshot_;
164+
mutable std::unordered_map<int64_t, std::shared_ptr<Snapshot>> snapshots_map_;
165+
166+
std::shared_ptr<TableMetadata> metadata_;
167+
168+
// once_flags
169+
mutable std::once_flag init_schema_once_;
170+
mutable std::once_flag init_partition_spec_once_;
171+
mutable std::once_flag init_sort_order_once_;
172+
mutable std::once_flag init_snapshot_once_;
173+
};
174+
175+
class ICEBERG_EXPORT StaticTable : public BaseTable {
176+
public:
177+
virtual ~StaticTable() override = default;
178+
StaticTable(std::string name, std::shared_ptr<TableMetadata> metadata)
179+
: BaseTable(std::move(name), std::move(metadata)) {}
180+
181+
Status Refresh() override;
182+
183+
std::unique_ptr<TableScan> NewScan() const override;
184+
185+
std::shared_ptr<AppendFiles> NewAppend() override;
186+
187+
std::unique_ptr<Transaction> NewTransaction() override;
188+
189+
std::unique_ptr<LocationProvider> location_provider() const override;
190+
};
191+
111192
} // namespace iceberg

test/CMakeLists.txt

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,14 @@ target_sources(schema_test
4444
target_link_libraries(schema_test PRIVATE iceberg_static GTest::gtest_main GTest::gmock)
4545
add_test(NAME schema_test COMMAND schema_test)
4646

47+
add_executable(table_test)
48+
target_include_directories(table_test PRIVATE "${CMAKE_BINARY_DIR}")
49+
target_sources(table_test PRIVATE table_test_helper.cc json_internal_test.cc table_test.cc
50+
schema_json_test.cc)
51+
target_link_libraries(table_test PRIVATE iceberg_static GTest::gtest_main
52+
GTest::gmock)
53+
add_test(NAME table_test COMMAND table_test)
54+
4755
add_executable(expression_test)
4856
target_sources(expression_test PRIVATE expression_test.cc)
4957
target_link_libraries(expression_test PRIVATE iceberg_static GTest::gtest_main
@@ -52,7 +60,7 @@ add_test(NAME expression_test COMMAND expression_test)
5260

5361
add_executable(json_serde_test)
5462
target_include_directories(json_serde_test PRIVATE "${CMAKE_BINARY_DIR}")
55-
target_sources(json_serde_test PRIVATE json_internal_test.cc metadata_serde_test.cc
63+
target_sources(json_serde_test PRIVATE table_test_helper.cc json_internal_test.cc metadata_serde_test.cc
5664
schema_json_test.cc)
5765
target_link_libraries(json_serde_test PRIVATE iceberg_static GTest::gtest_main
5866
GTest::gmock)

test/metadata_serde_test.cc

Lines changed: 5 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,11 @@
2020
#include <filesystem>
2121
#include <fstream>
2222
#include <optional>
23-
#include <sstream>
2423
#include <string>
2524

2625
#include <gtest/gtest.h>
2726
#include <nlohmann/json.hpp>
2827

29-
#include "iceberg/json_internal.h"
3028
#include "iceberg/partition_field.h"
3129
#include "iceberg/partition_spec.h"
3230
#include "iceberg/schema.h"
@@ -35,9 +33,9 @@
3533
#include "iceberg/sort_field.h"
3634
#include "iceberg/sort_order.h"
3735
#include "iceberg/table_metadata.h"
38-
#include "iceberg/test/test_config.h"
3936
#include "iceberg/transform.h"
4037
#include "iceberg/type.h"
38+
#include "table_test_helper.h"
4139

4240
namespace iceberg {
4341

@@ -46,40 +44,14 @@ namespace {
4644
class MetadataSerdeTest : public ::testing::Test {
4745
protected:
4846
void SetUp() override {}
49-
50-
static std::string GetResourcePath(const std::string& file_name) {
51-
return std::string(ICEBERG_TEST_RESOURCES) + "/" + file_name;
52-
}
53-
54-
static void ReadJsonFile(const std::string& file_name, std::string* content) {
55-
std::filesystem::path path{GetResourcePath(file_name)};
56-
ASSERT_TRUE(std::filesystem::exists(path))
57-
<< "File does not exist: " << path.string();
58-
59-
std::ifstream file(path);
60-
std::stringstream buffer;
61-
buffer << file.rdbuf();
62-
*content = buffer.str();
63-
}
64-
65-
static void ReadTableMetadata(const std::string& file_name,
66-
std::unique_ptr<TableMetadata>* metadata) {
67-
std::string json_content;
68-
ReadJsonFile(file_name, &json_content);
69-
70-
nlohmann::json json = nlohmann::json::parse(json_content);
71-
auto result = TableMetadataFromJson(json);
72-
ASSERT_TRUE(result.has_value()) << "Failed to parse table metadata from " << file_name
73-
<< ": " << result.error().message;
74-
*metadata = std::move(result.value());
75-
}
7647
};
7748

7849
} // namespace
7950

8051
TEST_F(MetadataSerdeTest, DeserializeV1Valid) {
8152
std::unique_ptr<TableMetadata> metadata;
82-
ASSERT_NO_FATAL_FAILURE(ReadTableMetadata("TableMetadataV1Valid.json", &metadata));
53+
ASSERT_NO_FATAL_FAILURE(
54+
TableTestHelper::ReadTableMetadata("TableMetadataV1Valid.json", &metadata));
8355

8456
EXPECT_EQ(metadata->format_version, 1);
8557
EXPECT_EQ(metadata->table_uuid, "d20125c8-7284-442c-9aea-15fee620737c");
@@ -116,7 +88,8 @@ TEST_F(MetadataSerdeTest, DeserializeV1Valid) {
11688

11789
TEST_F(MetadataSerdeTest, DeserializeV2Valid) {
11890
std::unique_ptr<TableMetadata> metadata;
119-
ASSERT_NO_FATAL_FAILURE(ReadTableMetadata("TableMetadataV2Valid.json", &metadata));
91+
ASSERT_NO_FATAL_FAILURE(
92+
TableTestHelper::ReadTableMetadata("TableMetadataV2Valid.json", &metadata));
12093

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

0 commit comments

Comments
 (0)