1919
2020#include " iceberg/catalog/rest/validator.h"
2121
22+ #include < algorithm>
2223#include < format>
2324#include < ranges>
24- #include < unordered_set>
25- #include < utility>
2625
2726#include " iceberg/catalog/rest/types.h"
2827#include " iceberg/result.h"
28+ #include " iceberg/util/macros.h"
2929
3030namespace iceberg ::rest {
3131
@@ -40,18 +40,20 @@ Status Validator::Validate(const CatalogConfig& config) {
4040}
4141
4242Status Validator::Validate (const ErrorModel& error) {
43- if (error.message .empty () || error.type .empty ()) [[unlikely]] {
43+ if (error.message .empty () || error.type .empty ()) {
4444 return Invalid (" Invalid error model: missing required fields" );
4545 }
4646
47- if (error.code < 400 || error.code > 600 ) [[unlikely]] {
48- return Invalid (" Invalid error model: code must be between 400 and 600" );
47+ if (error.code < 400 || error.code > 600 ) {
48+ return Invalid (" Invalid error model: code {} is out of range [400, 600] " , error. code );
4949 }
5050
5151 // stack is optional, no validation needed
5252 return {};
5353}
5454
55+ // We don't validate the error field because ErrorModel::Validate has been called in the
56+ // FromJson.
5557Status Validator::Validate (const ErrorResponse& response) { return {}; }
5658
5759// Namespace operations
@@ -66,30 +68,35 @@ Status Validator::Validate(const GetNamespaceResponse& response) { return {}; }
6668
6769Status Validator::Validate (const UpdateNamespacePropertiesRequest& request) {
6870 // keys in updates and removals must not overlap
69- if (request.removals .empty () || request.updates .empty ()) [[unlikely]] {
71+ if (request.removals .empty () || request.updates .empty ()) {
7072 return {};
7173 }
7274
73- std::unordered_set<std::string> remove_set (request.removals .begin (),
74- request.removals .end ());
75- std::vector<std::string> common;
75+ auto sorted_removals =
76+ request.removals |
77+ std::views::transform ([](const std::string& s) { return std::string_view{s}; }) |
78+ std::ranges::to<std::vector>();
79+ std::ranges::sort (sorted_removals);
7680
77- for (const std::string& k : request.updates | std::views::keys) {
78- if (remove_set.contains (k)) {
79- common.push_back (k);
80- }
81- }
81+ auto sorted_update_keys =
82+ request.updates | std::views::keys |
83+ std::views::transform ([](const std::string& s) { return std::string_view{s}; }) |
84+ std::ranges::to<std::vector>();
85+ std::ranges::sort (sorted_update_keys);
86+
87+ std::vector<std::string_view> common;
88+ std::ranges::set_intersection (sorted_update_keys, sorted_removals,
89+ std::back_inserter (common));
8290
8391 if (!common.empty ()) {
8492 std::string keys;
85- bool first = true ;
86- for (const std::string& s : common) {
87- if (!std::exchange (first, false )) keys += " , " ;
88- keys += s;
93+ for (size_t i = 0 ; i < common.size (); ++i) {
94+ if (i) keys += " , " ;
95+ keys += common[i];
8996 }
9097
9198 return Invalid (
92- " Invalid namespace properties update: cannot simultaneously set and remove keys: "
99+ " Invalid namespace update: cannot simultaneously set and remove keys: "
93100 " [{}]" ,
94101 keys);
95102 }
@@ -105,34 +112,34 @@ Status Validator::Validate(const UpdateNamespacePropertiesResponse& response) {
105112Status Validator::Validate (const ListTablesResponse& response) { return {}; }
106113
107114Status Validator::Validate (const LoadTableResult& result) {
108- if (!result.metadata ) [[unlikely]] {
115+ if (!result.metadata ) {
109116 return Invalid (" Invalid metadata: null" );
110117 }
111118 return {};
112119}
113120
114121Status Validator::Validate (const RegisterTableRequest& request) {
115- if (request.name .empty ()) [[unlikely]] {
116- return Invalid (" Invalid table name: empty " );
122+ if (request.name .empty ()) {
123+ return Invalid (" Missing table name" );
117124 }
118125
119- if (request.metadata_location .empty ()) [[unlikely]] {
120- return Invalid (" Invalid metadata location: empty " );
126+ if (request.metadata_location .empty ()) {
127+ return Invalid (" Empty metadata location" );
121128 }
122129
123130 return {};
124131}
125132
126133Status Validator::Validate (const RenameTableRequest& request) {
127- if (request.source .ns .levels .empty () || request.source .name .empty ()) [[unlikely]] {
128- return Invalid (" Invalid source identifier" );
129- }
134+ ICEBERG_RETURN_UNEXPECTED (Validate (request.source ));
135+ ICEBERG_RETURN_UNEXPECTED (Validate (request.destination ));
136+ return {};
137+ }
130138
131- if (request. destination . ns . levels . empty () || request. destination . name . empty ())
132- [[unlikely]] {
133- return Invalid (" Invalid destination identifier" );
139+ Status Validator::Validate ( const TableIdentifier& identifier) {
140+ if (identifier. name . empty ()) {
141+ return Invalid (" Invalid table identifier: missing table name " );
134142 }
135-
136143 return {};
137144}
138145
0 commit comments