2626#include < unordered_map>
2727#include < unordered_set>
2828
29- #include " iceberg/iceberg_export.h"
3029#include " iceberg/row/partition_values.h"
3130
3231namespace iceberg {
@@ -35,6 +34,18 @@ constexpr size_t kHashPrime = 0x9e3779b9;
3534
3635using PartitionKey = std::pair<int32_t , PartitionValues>;
3736
37+ // / \brief Lightweight lookup key for heterogeneous lookup without copying
38+ // / PartitionValues.
39+ struct PartitionKeyRef {
40+ int32_t spec_id;
41+ const PartitionValues& values;
42+
43+ PartitionKeyRef (int32_t id, const PartitionValues& vals) : spec_id(id), values(vals) {}
44+
45+ explicit PartitionKeyRef (const PartitionKey& key)
46+ : spec_id(key.first), values(key.second) {}
47+ };
48+
3849// / \brief Hash functor for PartitionValues.
3950struct PartitionValuesHash {
4051 std::size_t operator ()(const PartitionValues& partition) const noexcept {
@@ -54,19 +65,46 @@ struct PartitionValuesEqual {
5465 }
5566};
5667
57- // / \brief Hash functor for std::pair<int32_t, PartitionValues> .
68+ // / \brief Transparent hash functor for PartitionKey with heterogeneous lookup support .
5869struct PartitionKeyHash {
70+ using is_transparent = void ;
71+
5972 std::size_t operator ()(const PartitionKey& key) const noexcept {
6073 std::size_t hash = std::hash<int32_t >{}(key.first );
6174 hash ^= PartitionValuesHash{}(key.second ) + kHashPrime + (hash << 6 ) + (hash >> 2 );
6275 return hash;
6376 }
77+
78+ std::size_t operator ()(const PartitionKeyRef& key) const noexcept {
79+ std::size_t hash = std::hash<int32_t >{}(key.spec_id );
80+ hash ^= PartitionValuesHash{}(key.values ) + kHashPrime + (hash << 6 ) + (hash >> 2 );
81+ return hash;
82+ }
6483};
6584
66- // / \brief Equality functor for std::pair<int32_t, PartitionValues>.
85+ // / \brief Transparent equality functor for PartitionKey with heterogeneous lookup
86+ // / support.
6787struct PartitionKeyEqual {
88+ using is_transparent = void ;
89+
90+ // Equality for PartitionKey vs PartitionKey
6891 bool operator ()(const PartitionKey& lhs, const PartitionKey& rhs) const {
69- return lhs == rhs;
92+ return lhs.first == rhs.first && lhs.second == rhs.second ;
93+ }
94+
95+ // Equality for PartitionKey vs PartitionKeyRef (heterogeneous lookup)
96+ bool operator ()(const PartitionKey& lhs, const PartitionKeyRef& rhs) const {
97+ return lhs.first == rhs.spec_id && lhs.second == rhs.values ;
98+ }
99+
100+ // Equality for PartitionKeyRef vs PartitionKey (heterogeneous lookup)
101+ bool operator ()(const PartitionKeyRef& lhs, const PartitionKey& rhs) const {
102+ return lhs.spec_id == rhs.first && lhs.values == rhs.second ;
103+ }
104+
105+ // Equality for PartitionKeyRef vs PartitionKeyRef (heterogeneous lookup)
106+ bool operator ()(const PartitionKeyRef& lhs, const PartitionKeyRef& rhs) const {
107+ return lhs.spec_id == rhs.spec_id && lhs.values == rhs.values ;
70108 }
71109};
72110
@@ -97,7 +135,7 @@ class PartitionMap {
97135 // / \param values The partition values.
98136 // / \return true if the key exists, false otherwise.
99137 bool contains (int32_t spec_id, const PartitionValues& values) const {
100- return map_.contains (PartitionKey {spec_id, values});
138+ return map_.contains (PartitionKeyRef {spec_id, values});
101139 }
102140
103141 // / \brief Get the value associated with a key.
@@ -106,7 +144,7 @@ class PartitionMap {
106144 // / \return Reference to the value if found, std::nullopt otherwise.
107145 std::optional<std::reference_wrapper<V>> get (int32_t spec_id,
108146 const PartitionValues& values) {
109- auto it = map_.find (PartitionKey {spec_id, values});
147+ auto it = map_.find (PartitionKeyRef {spec_id, values});
110148 return it != map_.end () ? std::make_optional (std::ref (it->second )) : std::nullopt ;
111149 }
112150
@@ -116,7 +154,7 @@ class PartitionMap {
116154 // / \return Reference to the value if found, std::nullopt otherwise.
117155 std::optional<std::reference_wrapper<const V>> get (
118156 int32_t spec_id, const PartitionValues& values) const {
119- auto it = map_.find (PartitionKey {spec_id, values});
157+ auto it = map_.find (PartitionKeyRef {spec_id, values});
120158 return it != map_.end () ? std::make_optional (std::cref (it->second )) : std::nullopt ;
121159 }
122160
@@ -126,13 +164,12 @@ class PartitionMap {
126164 // / \param value The value to insert.
127165 // / \return true if the entry was updated, false if it was inserted.
128166 bool put (int32_t spec_id, PartitionValues values, V value) {
129- auto key = PartitionKey{spec_id, std::move (values)};
130- auto it = map_.find (key);
167+ auto it = map_.find (PartitionKeyRef{spec_id, values});
131168 if (it != map_.end ()) {
132169 it->second = std::move (value);
133170 return true ;
134171 }
135- map_.emplace (std::move (key) , std::move (value));
172+ map_.emplace (PartitionKey{spec_id, std::move (values)} , std::move (value));
136173 return false ;
137174 }
138175
@@ -141,7 +178,12 @@ class PartitionMap {
141178 // / \param values The partition values.
142179 // / \return true if the entry was removed, false if it didn't exist.
143180 bool remove (int32_t spec_id, const PartitionValues& values) {
144- return map_.erase (PartitionKey{spec_id, values}) > 0 ;
181+ auto it = map_.find (PartitionKeyRef{spec_id, values});
182+ if (it != map_.end ()) {
183+ map_.erase (it);
184+ return true ;
185+ }
186+ return false ;
145187 }
146188
147189 // / \brief Get iterator to the beginning.
@@ -181,7 +223,7 @@ class PartitionSet {
181223 // / \param values The partition values.
182224 // / \return true if the element exists, false otherwise.
183225 bool contains (int32_t spec_id, const PartitionValues& values) const {
184- return set_.contains (PartitionKey {spec_id, values});
226+ return set_.contains (PartitionKeyRef {spec_id, values});
185227 }
186228
187229 // / \brief Add an element to the set.
@@ -198,7 +240,12 @@ class PartitionSet {
198240 // / \param values The partition values.
199241 // / \return true if the element was removed, false if it didn't exist.
200242 bool remove (int32_t spec_id, const PartitionValues& values) {
201- return set_.erase (PartitionKey{spec_id, values}) > 0 ;
243+ auto it = set_.find (PartitionKeyRef{spec_id, values});
244+ if (it != set_.end ()) {
245+ set_.erase (it);
246+ return true ;
247+ }
248+ return false ;
202249 }
203250
204251 // / \brief Get iterator to the beginning.
0 commit comments