Skip to content

Commit 7f7f85b

Browse files
authored
refactor: remove Validator and add Validate methods directly to rest models (#304)
1 parent e77263e commit 7f7f85b

File tree

7 files changed

+110
-250
lines changed

7 files changed

+110
-250
lines changed

src/iceberg/catalog/rest/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
# specific language governing permissions and limitations
1616
# under the License.
1717

18-
set(ICEBERG_REST_SOURCES rest_catalog.cc json_internal.cc validator.cc)
18+
set(ICEBERG_REST_SOURCES rest_catalog.cc json_internal.cc)
1919

2020
set(ICEBERG_REST_STATIC_BUILD_INTERFACE_LIBS)
2121
set(ICEBERG_REST_SHARED_BUILD_INTERFACE_LIBS)

src/iceberg/catalog/rest/json_internal.cc

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626
#include <nlohmann/json.hpp>
2727

2828
#include "iceberg/catalog/rest/types.h"
29-
#include "iceberg/catalog/rest/validator.h"
3029
#include "iceberg/json_internal.h"
3130
#include "iceberg/table_identifier.h"
3231
#include "iceberg/util/json_util_internal.h"
@@ -88,7 +87,7 @@ Result<CatalogConfig> CatalogConfigFromJson(const nlohmann::json& json) {
8887
ICEBERG_ASSIGN_OR_RAISE(
8988
config.endpoints,
9089
GetJsonValueOrDefault<std::vector<std::string>>(json, kEndpoints));
91-
ICEBERG_RETURN_UNEXPECTED(Validator::Validate(config));
90+
ICEBERG_RETURN_UNEXPECTED(config.Validate());
9291
return config;
9392
}
9493

@@ -111,7 +110,7 @@ Result<ErrorModel> ErrorModelFromJson(const nlohmann::json& json) {
111110
ICEBERG_ASSIGN_OR_RAISE(error.code, GetJsonValue<uint32_t>(json, kCode));
112111
ICEBERG_ASSIGN_OR_RAISE(error.stack,
113112
GetJsonValueOrDefault<std::vector<std::string>>(json, kStack));
114-
ICEBERG_RETURN_UNEXPECTED(Validator::Validate(error));
113+
ICEBERG_RETURN_UNEXPECTED(error.Validate());
115114
return error;
116115
}
117116

@@ -125,7 +124,7 @@ Result<ErrorResponse> ErrorResponseFromJson(const nlohmann::json& json) {
125124
ErrorResponse response;
126125
ICEBERG_ASSIGN_OR_RAISE(auto error_json, GetJsonValue<nlohmann::json>(json, kError));
127126
ICEBERG_ASSIGN_OR_RAISE(response.error, ErrorModelFromJson(error_json));
128-
ICEBERG_RETURN_UNEXPECTED(Validator::Validate(response));
127+
ICEBERG_RETURN_UNEXPECTED(response.Validate());
129128
return response;
130129
}
131130

@@ -144,7 +143,7 @@ Result<CreateNamespaceRequest> CreateNamespaceRequestFromJson(
144143
ICEBERG_ASSIGN_OR_RAISE(
145144
request.properties,
146145
GetJsonValueOrDefault<decltype(request.properties)>(json, kProperties));
147-
ICEBERG_RETURN_UNEXPECTED(Validator::Validate(request));
146+
ICEBERG_RETURN_UNEXPECTED(request.Validate());
148147
return request;
149148
}
150149

@@ -162,7 +161,7 @@ Result<UpdateNamespacePropertiesRequest> UpdateNamespacePropertiesRequestFromJso
162161
request.removals, GetJsonValueOrDefault<std::vector<std::string>>(json, kRemovals));
163162
ICEBERG_ASSIGN_OR_RAISE(
164163
request.updates, GetJsonValueOrDefault<decltype(request.updates)>(json, kUpdates));
165-
ICEBERG_RETURN_UNEXPECTED(Validator::Validate(request));
164+
ICEBERG_RETURN_UNEXPECTED(request.Validate());
166165
return request;
167166
}
168167

@@ -183,7 +182,7 @@ Result<RegisterTableRequest> RegisterTableRequestFromJson(const nlohmann::json&
183182
GetJsonValue<std::string>(json, kMetadataLocation));
184183
ICEBERG_ASSIGN_OR_RAISE(request.overwrite,
185184
GetJsonValueOrDefault<bool>(json, kOverwrite, false));
186-
ICEBERG_RETURN_UNEXPECTED(Validator::Validate(request));
185+
ICEBERG_RETURN_UNEXPECTED(request.Validate());
187186
return request;
188187
}
189188

@@ -201,7 +200,7 @@ Result<RenameTableRequest> RenameTableRequestFromJson(const nlohmann::json& json
201200
ICEBERG_ASSIGN_OR_RAISE(auto dest_json,
202201
GetJsonValue<nlohmann::json>(json, kDestination));
203202
ICEBERG_ASSIGN_OR_RAISE(request.destination, TableIdentifierFromJson(dest_json));
204-
ICEBERG_RETURN_UNEXPECTED(Validator::Validate(request));
203+
ICEBERG_RETURN_UNEXPECTED(request.Validate());
205204
return request;
206205
}
207206

@@ -248,7 +247,7 @@ Result<ListNamespacesResponse> ListNamespacesResponseFromJson(
248247
ICEBERG_ASSIGN_OR_RAISE(auto ns, NamespaceFromJson(ns_json));
249248
response.namespaces.push_back(std::move(ns));
250249
}
251-
ICEBERG_RETURN_UNEXPECTED(Validator::Validate(response));
250+
ICEBERG_RETURN_UNEXPECTED(response.Validate());
252251
return response;
253252
}
254253

@@ -304,7 +303,7 @@ Result<UpdateNamespacePropertiesResponse> UpdateNamespacePropertiesResponseFromJ
304303
response.removed, GetJsonValueOrDefault<std::vector<std::string>>(json, kRemoved));
305304
ICEBERG_ASSIGN_OR_RAISE(
306305
response.missing, GetJsonValueOrDefault<std::vector<std::string>>(json, kMissing));
307-
ICEBERG_RETURN_UNEXPECTED(Validator::Validate(response));
306+
ICEBERG_RETURN_UNEXPECTED(response.Validate());
308307
return response;
309308
}
310309

@@ -329,7 +328,7 @@ Result<ListTablesResponse> ListTablesResponseFromJson(const nlohmann::json& json
329328
ICEBERG_ASSIGN_OR_RAISE(auto identifier, TableIdentifierFromJson(id_json));
330329
response.identifiers.push_back(std::move(identifier));
331330
}
332-
ICEBERG_RETURN_UNEXPECTED(Validator::Validate(response));
331+
ICEBERG_RETURN_UNEXPECTED(response.Validate());
333332
return response;
334333
}
335334

src/iceberg/catalog/rest/meson.build

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,7 @@
1515
# specific language governing permissions and limitations
1616
# under the License.
1717

18-
iceberg_rest_sources = files(
19-
'json_internal.cc',
20-
'rest_catalog.cc',
21-
'validator.cc',
22-
)
18+
iceberg_rest_sources = files('json_internal.cc', 'rest_catalog.cc')
2319
# cpr does not export symbols, so on Windows it must
2420
# be used as a static lib
2521
cpr_needs_static = (
@@ -50,7 +46,4 @@ iceberg_rest_dep = declare_dependency(
5046
meson.override_dependency('iceberg-rest', iceberg_rest_dep)
5147
pkg.generate(iceberg_rest_lib)
5248

53-
install_headers(
54-
['rest_catalog.h', 'types.h', 'json_internal.h', 'validator.h'],
55-
subdir: 'iceberg/catalog/rest',
56-
)
49+
install_headers(['rest_catalog.h', 'types.h'], subdir: 'iceberg/catalog/rest')

src/iceberg/catalog/rest/types.h

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,18 @@
1919

2020
#pragma once
2121

22+
#include <algorithm>
23+
#include <format>
2224
#include <memory>
2325
#include <string>
2426
#include <unordered_map>
2527
#include <vector>
2628

2729
#include "iceberg/catalog/rest/iceberg_rest_export.h"
30+
#include "iceberg/result.h"
2831
#include "iceberg/table_identifier.h"
2932
#include "iceberg/type_fwd.h"
33+
#include "iceberg/util/macros.h"
3034

3135
/// \file iceberg/catalog/rest/types.h
3236
/// Request and response types for Iceberg REST Catalog API.
@@ -38,6 +42,15 @@ struct ICEBERG_REST_EXPORT CatalogConfig {
3842
std::unordered_map<std::string, std::string> defaults; // required
3943
std::unordered_map<std::string, std::string> overrides; // required
4044
std::vector<std::string> endpoints;
45+
46+
/// \brief Validates the CatalogConfig.
47+
Status Validate() const {
48+
// TODO(Li Feiyang): Add an invalidEndpoint test that validates endpoint format.
49+
// See:
50+
// https://github.com/apache/iceberg/blob/main/core/src/test/java/org/apache/iceberg/rest/responses/TestConfigResponseParser.java#L164
51+
// for reference.
52+
return {};
53+
}
4154
};
4255

4356
/// \brief JSON error payload returned in a response with further details on the error.
@@ -46,36 +59,88 @@ struct ICEBERG_REST_EXPORT ErrorModel {
4659
std::string type; // required
4760
uint32_t code; // required
4861
std::vector<std::string> stack;
62+
63+
/// \brief Validates the ErrorModel.
64+
Status Validate() const {
65+
if (message.empty() || type.empty()) {
66+
return Invalid("Invalid error model: missing required fields");
67+
}
68+
69+
if (code < 400 || code > 600) {
70+
return Invalid("Invalid error model: code {} is out of range [400, 600]", code);
71+
}
72+
73+
// stack is optional, no validation needed
74+
return {};
75+
}
4976
};
5077

5178
/// \brief Error response body returned in a response.
5279
struct ICEBERG_REST_EXPORT ErrorResponse {
5380
ErrorModel error; // required
81+
82+
/// \brief Validates the ErrorResponse.
83+
// We don't validate the error field because ErrorModel::Validate has been called in the
84+
// FromJson.
85+
Status Validate() const { return {}; }
5486
};
5587

5688
/// \brief Request to create a namespace.
5789
struct ICEBERG_REST_EXPORT CreateNamespaceRequest {
5890
Namespace namespace_; // required
5991
std::unordered_map<std::string, std::string> properties;
92+
93+
/// \brief Validates the CreateNamespaceRequest.
94+
Status Validate() const { return {}; }
6095
};
6196

6297
/// \brief Update or delete namespace properties request.
6398
struct ICEBERG_REST_EXPORT UpdateNamespacePropertiesRequest {
6499
std::vector<std::string> removals;
65100
std::unordered_map<std::string, std::string> updates;
101+
102+
/// \brief Validates the UpdateNamespacePropertiesRequest.
103+
Status Validate() const {
104+
for (const auto& key : removals) {
105+
if (updates.contains(key)) {
106+
return Invalid("Duplicate key to update and remove: {}", key);
107+
}
108+
}
109+
return {};
110+
}
66111
};
67112

68113
/// \brief Request to register a table.
69114
struct ICEBERG_REST_EXPORT RegisterTableRequest {
70115
std::string name; // required
71116
std::string metadata_location; // required
72117
bool overwrite = false;
118+
119+
/// \brief Validates the RegisterTableRequest.
120+
Status Validate() const {
121+
if (name.empty()) {
122+
return Invalid("Missing table name");
123+
}
124+
125+
if (metadata_location.empty()) {
126+
return Invalid("Empty metadata location");
127+
}
128+
129+
return {};
130+
}
73131
};
74132

75133
/// \brief Request to rename a table.
76134
struct ICEBERG_REST_EXPORT RenameTableRequest {
77135
TableIdentifier source; // required
78136
TableIdentifier destination; // required
137+
138+
/// \brief Validates the RenameTableRequest.
139+
Status Validate() const {
140+
ICEBERG_RETURN_UNEXPECTED(source.Validate());
141+
ICEBERG_RETURN_UNEXPECTED(destination.Validate());
142+
return {};
143+
}
79144
};
80145

81146
/// \brief An opaque token that allows clients to make use of pagination for list APIs.
@@ -87,6 +152,14 @@ struct ICEBERG_REST_EXPORT LoadTableResult {
87152
std::shared_ptr<TableMetadata> metadata; // required
88153
std::unordered_map<std::string, std::string> config;
89154
// TODO(Li Feiyang): Add std::shared_ptr<StorageCredential> storage_credential;
155+
156+
/// \brief Validates the LoadTableResult.
157+
Status Validate() const {
158+
if (!metadata) {
159+
return Invalid("Invalid metadata: null");
160+
}
161+
return {};
162+
}
90163
};
91164

92165
/// \brief Alias of LoadTableResult used as the body of CreateTableResponse
@@ -99,31 +172,46 @@ using LoadTableResponse = LoadTableResult;
99172
struct ICEBERG_REST_EXPORT ListNamespacesResponse {
100173
PageToken next_page_token;
101174
std::vector<Namespace> namespaces;
175+
176+
/// \brief Validates the ListNamespacesResponse.
177+
Status Validate() const { return {}; }
102178
};
103179

104180
/// \brief Response body after creating a namespace.
105181
struct ICEBERG_REST_EXPORT CreateNamespaceResponse {
106182
Namespace namespace_; // required
107183
std::unordered_map<std::string, std::string> properties;
184+
185+
/// \brief Validates the CreateNamespaceResponse.
186+
Status Validate() const { return {}; }
108187
};
109188

110189
/// \brief Response body for loading namespace properties.
111190
struct ICEBERG_REST_EXPORT GetNamespaceResponse {
112191
Namespace namespace_; // required
113192
std::unordered_map<std::string, std::string> properties;
193+
194+
/// \brief Validates the GetNamespaceResponse.
195+
Status Validate() const { return {}; }
114196
};
115197

116198
/// \brief Response body after updating namespace properties.
117199
struct ICEBERG_REST_EXPORT UpdateNamespacePropertiesResponse {
118200
std::vector<std::string> updated; // required
119201
std::vector<std::string> removed; // required
120202
std::vector<std::string> missing;
203+
204+
/// \brief Validates the UpdateNamespacePropertiesResponse.
205+
Status Validate() const { return {}; }
121206
};
122207

123208
/// \brief Response body for listing tables in a namespace.
124209
struct ICEBERG_REST_EXPORT ListTablesResponse {
125210
PageToken next_page_token;
126211
std::vector<TableIdentifier> identifiers;
212+
213+
/// \brief Validates the ListTablesResponse.
214+
Status Validate() const { return {}; }
127215
};
128216

129217
} // namespace iceberg::rest

0 commit comments

Comments
 (0)