MySQL 8.0.37
Source Code Documentation
map_helpers.h
Go to the documentation of this file.
1/* Copyright (c) 2017, 2024, Oracle and/or its affiliates.
2
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License, version 2.0,
5 as published by the Free Software Foundation.
6
7 This program is designed to work with certain software (including
8 but not limited to OpenSSL) that is licensed under separate terms,
9 as designated in a particular file or component or in included license
10 documentation. The authors of MySQL hereby grant you an additional
11 permission to link the program and your derivative works with the
12 separately licensed software that they have either included with
13 the program or referenced in the documentation.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License, version 2.0, for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
23
24#ifndef MAP_HELPERS_INCLUDED
25#define MAP_HELPERS_INCLUDED
26
27#include <map>
28#include <memory>
29#include <string>
30#include <type_traits>
31#include <unordered_map>
32#include <unordered_set>
33#include <utility>
34
35#include "m_ctype.h"
36#include "my_inttypes.h"
39#include "template_utils.h"
40
41/**
42 Some useful helpers for associative arrays with MySQL-specific semantics.
43*/
44
45/**
46 For unordered_map<Key, T*> or unordered_map<Key, unique_ptr<T>>, does
47 find() and returns nullptr if the element was not found.
48
49 It is not possible to distinguish between "not found" and "found, but
50 contained nullptr" in this case. Thus, you should normally prefer checking
51 against container.end() yourself.
52*/
53template <class Container, class Key>
54static inline auto find_or_nullptr(const Container &container, const Key &key) {
55 const auto it = container.find(key);
56 if constexpr (std::is_pointer_v<typename Container::mapped_type>) {
57 return it == container.end() ? nullptr : it->second;
58 } else {
59 return it == container.end() ? nullptr : it->second.get();
60 }
61}
62
63/**
64 For unordered_multimap<Key, Value>, erase the first specific element that
65 matches _both_ the given key and value.
66*/
67template <class Container, class Value>
68typename Container::iterator erase_specific_element(
69 Container *container, const typename Container::key_type &key,
70 const Value &value) {
71 auto it_range = container->equal_range(key);
72 for (auto it = it_range.first; it != it_range.second; ++it) {
73 if constexpr (std::is_pointer_v<typename Container::mapped_type>) {
74 if (it->second == value) return container->erase(it);
75 } else {
76 // For when the container holds unique_ptr elements.
77 if (it->second.get() == value) return container->erase(it);
78 }
79 }
80 return container->end();
81}
82/**
83 std::unique_ptr, but with a custom delete function.
84 Normally, it is more efficient to have a deleter class instead,
85 but this allows you to have a unique_ptr to a forward-declared class,
86 so it keeps include dependencies down somewhat.
87*/
88template <class T>
89using unique_ptr_with_deleter = std::unique_ptr<T, void (*)(T *)>;
90
92 void operator()(void *ptr) const { my_free(ptr); }
93};
94
95/** std::unique_ptr, but with my_free as deleter. */
96template <class T>
97using unique_ptr_my_free = std::unique_ptr<T, My_free_deleter>;
98
100 void operator()(void *ptr) const { free(ptr); }
101};
102
103/** std::unique_ptr, but with free as deleter. */
104template <class T>
105using unique_ptr_free = std::unique_ptr<T, Free_deleter>;
106
107/** A Hasher that hashes std::strings according to a MySQL collation. */
109 public:
110 explicit Collation_hasher(const CHARSET_INFO *cs_arg)
111 : cs(cs_arg), hash_sort(cs->coll->hash_sort) {}
112
113 size_t operator()(const std::string &s) const {
114 uint64 nr1 = 1, nr2 = 4;
115 hash_sort(cs, pointer_cast<const uchar *>(s.data()), s.size(), &nr1, &nr2);
116 return nr1;
117 }
118
119 private:
121 decltype(cs->coll->hash_sort) hash_sort;
122};
123
124/** A KeyEqual that compares std::strings according to a MySQL collation. */
126 public:
127 explicit Collation_key_equal(const CHARSET_INFO *cs_arg)
128 : cs(cs_arg), strnncollsp(cs->coll->strnncollsp) {}
129
130 size_t operator()(const std::string &a, const std::string &b) const {
131 return strnncollsp(cs, pointer_cast<const uchar *>(a.data()), a.size(),
132 pointer_cast<const uchar *>(b.data()), b.size()) == 0;
133 }
134
135 private:
137 decltype(cs->coll->strnncollsp) strnncollsp;
138};
139
140/**
141 std::unordered_map, but with my_malloc, so that you can track the memory
142 used using PSI memory keys.
143*/
144template <class Key, class Value, class Hash = std::hash<Key>,
145 class KeyEqual = std::equal_to<Key>>
147 : public std::unordered_map<Key, Value, Hash, KeyEqual,
148 Malloc_allocator<std::pair<const Key, Value>>> {
149 public:
150 /*
151 In theory, we should be allowed to send in the allocator only, but GCC 4.8
152 is missing several unordered_map constructors, so let's give in everything.
153 */
155 : std::unordered_map<Key, Value, Hash, KeyEqual,
156 Malloc_allocator<std::pair<const Key, Value>>>(
157 /*bucket_count=*/10, Hash(), KeyEqual(),
158 Malloc_allocator<>(psi_key)) {}
159};
160
161/**
162 std::unordered_set, but with my_malloc, so that you can track the memory
163 used using PSI memory keys.
164*/
165template <class Key, class Hash = std::hash<Key>,
166 class KeyEqual = std::equal_to<Key>>
168 : public std::unordered_set<Key, Hash, KeyEqual, Malloc_allocator<Key>> {
169 public:
170 /*
171 In theory, we should be allowed to send in the allocator only, but GCC 4.8
172 is missing several unordered_set constructors, so let's give in everything.
173 */
175 : std::unordered_set<Key, Hash, KeyEqual, Malloc_allocator<Key>>(
176 /*bucket_count=*/10, Hash(), KeyEqual(),
177 Malloc_allocator<>(psi_key)) {}
178};
179
180/**
181 std::unordered_multimap, but with my_malloc, so that you can track the memory
182 used using PSI memory keys.
183*/
184template <class Key, class Value, class Hash = std::hash<Key>,
185 class KeyEqual = std::equal_to<Key>>
187 : public std::unordered_multimap<
188 Key, Value, Hash, KeyEqual,
189 Malloc_allocator<std::pair<const Key, Value>>> {
190 public:
191 /*
192 In theory, we should be allowed to send in the allocator only, but GCC 4.8
193 is missing several unordered_multimap constructors, so let's give in
194 everything.
195 */
197 : std::unordered_multimap<Key, Value, Hash, KeyEqual,
198 Malloc_allocator<std::pair<const Key, Value>>>(
199 /*bucket_count=*/10, Hash(), KeyEqual(),
200 Malloc_allocator<>(psi_key)) {}
201};
202
203/**
204 std::unordered_map, but with my_malloc and collation-aware comparison.
205*/
206template <class Key, class Value>
208 : public std::unordered_map<Key, Value, Collation_hasher,
209 Collation_key_equal,
210 Malloc_allocator<std::pair<const Key, Value>>> {
211 public:
214 Malloc_allocator<std::pair<const Key, Value>>>(
215 /*bucket_count=*/10, Collation_hasher(cs), Collation_key_equal(cs),
216 Malloc_allocator<>(psi_key)) {}
217};
218
219/**
220 std::unordered_multimap, but with my_malloc and collation-aware comparison.
221*/
222template <class Key, class Value>
224 : public std::unordered_multimap<
225 Key, Value, Collation_hasher, Collation_key_equal,
226 Malloc_allocator<std::pair<const Key, Value>>> {
227 public:
229 : std::unordered_multimap<Key, Value, Collation_hasher,
231 Malloc_allocator<std::pair<const Key, Value>>>(
232 /*bucket_count=*/10, Collation_hasher(cs), Collation_key_equal(cs),
233 Malloc_allocator<>(psi_key)) {}
234};
235
236/**
237 std::unordered_set, but with my_malloc and collation-aware comparison.
238*/
239template <class Key>
241 : public std::unordered_set<Key, Collation_hasher, Collation_key_equal,
242 Malloc_allocator<Key>> {
243 public:
247 /*bucket_count=*/10, Collation_hasher(cs), Collation_key_equal(cs),
248 Malloc_allocator<>(psi_key)) {}
249 collation_unordered_set(std::initializer_list<Key> il, CHARSET_INFO *cs,
250 PSI_memory_key psi_key)
253 il, /*bucket_count=*/10, Collation_hasher(cs),
255};
256
257/** std::unordered_set, but allocated on a MEM_ROOT. */
258template <class Key, class Hash = std::hash<Key>,
259 class KeyEqual = std::equal_to<Key>>
261 : public std::unordered_set<Key, Hash, KeyEqual, Mem_root_allocator<Key>> {
262 public:
263 /*
264 In theory, we should be allowed to send in the allocator only, but GCC 4.8
265 is missing several unordered_set constructors, so let's give in everything.
266 */
267 explicit mem_root_unordered_set(MEM_ROOT *mem_root, Hash hash = Hash(),
268 KeyEqual key_equal_arg = KeyEqual())
269 : std::unordered_set<Key, Hash, KeyEqual, Mem_root_allocator<Key>>(
270 /*bucket_count=*/10, hash, key_equal_arg,
272};
273
274/**
275 std::unordered_map, but allocated on a MEM_ROOT.
276*/
277template <class Key, class Value, class Hash = std::hash<Key>,
278 class KeyEqual = std::equal_to<Key>>
280 : public std::unordered_map<
281 Key, Value, Hash, KeyEqual,
282 Mem_root_allocator<std::pair<const Key, Value>>> {
283 public:
284 explicit mem_root_unordered_map(MEM_ROOT *mem_root, Hash hash = Hash())
285 : std::unordered_map<Key, Value, Hash, KeyEqual,
286 Mem_root_allocator<std::pair<const Key, Value>>>(
287 /*bucket_count=*/10, hash, KeyEqual(),
288 Mem_root_allocator<std::pair<const Key, Value>>(mem_root)) {}
289};
290
291/**
292 std::unordered_multimap, but allocated on a MEM_ROOT.
293 */
294template <class Key, class Value, class Hash = std::hash<Key>,
295 class KeyEqual = std::equal_to<Key>>
297 : public std::unordered_multimap<
298 Key, Value, Hash, KeyEqual,
299 Mem_root_allocator<std::pair<const Key, Value>>> {
300 public:
301 explicit mem_root_unordered_multimap(MEM_ROOT *mem_root, Hash hash = Hash())
302 : std::unordered_multimap<
303 Key, Value, Hash, KeyEqual,
304 Mem_root_allocator<std::pair<const Key, Value>>>(
305 /*bucket_count=*/10, hash, KeyEqual(),
306 Mem_root_allocator<std::pair<const Key, Value>>(mem_root)) {}
307};
308
309/**
310 std::unordered_map, but collation aware and allocated on a MEM_ROOT.
311*/
312template <class Key, class Value>
314 : public std::unordered_map<
315 Key, Value, Collation_hasher, Collation_key_equal,
316 Mem_root_allocator<std::pair<const Key, Value>>> {
317 public:
320 Mem_root_allocator<std::pair<const Key, Value>>>(
321 /*bucket_count=*/10, Collation_hasher(cs), Collation_key_equal(cs),
322 Mem_root_allocator<std::pair<const Key, Value>>(mem_root)) {}
323};
324
325#endif // MAP_HELPERS_INCLUDED
A Hasher that hashes std::strings according to a MySQL collation.
Definition: map_helpers.h:108
decltype(cs->coll->hash_sort) hash_sort
Definition: map_helpers.h:121
Collation_hasher(const CHARSET_INFO *cs_arg)
Definition: map_helpers.h:110
const CHARSET_INFO * cs
Definition: map_helpers.h:120
size_t operator()(const std::string &s) const
Definition: map_helpers.h:113
A KeyEqual that compares std::strings according to a MySQL collation.
Definition: map_helpers.h:125
decltype(cs->coll->strnncollsp) strnncollsp
Definition: map_helpers.h:137
Collation_key_equal(const CHARSET_INFO *cs_arg)
Definition: map_helpers.h:127
size_t operator()(const std::string &a, const std::string &b) const
Definition: map_helpers.h:130
const CHARSET_INFO * cs
Definition: map_helpers.h:136
Malloc_allocator is a C++ STL memory allocator based on my_malloc/my_free.
Definition: malloc_allocator.h:63
Mem_root_allocator is a C++ STL memory allocator based on MEM_ROOT.
Definition: mem_root_allocator.h:68
a nullable SQL value.
Definition: sql_value.h:40
std::unordered_map, but with my_malloc and collation-aware comparison.
Definition: map_helpers.h:210
collation_unordered_map(const CHARSET_INFO *cs, PSI_memory_key psi_key)
Definition: map_helpers.h:212
std::unordered_multimap, but with my_malloc and collation-aware comparison.
Definition: map_helpers.h:226
collation_unordered_multimap(CHARSET_INFO *cs, PSI_memory_key psi_key)
Definition: map_helpers.h:228
std::unordered_set, but with my_malloc and collation-aware comparison.
Definition: map_helpers.h:242
collation_unordered_set(std::initializer_list< Key > il, CHARSET_INFO *cs, PSI_memory_key psi_key)
Definition: map_helpers.h:249
collation_unordered_set(CHARSET_INFO *cs, PSI_memory_key psi_key)
Definition: map_helpers.h:244
std::unordered_map, but with my_malloc, so that you can track the memory used using PSI memory keys.
Definition: map_helpers.h:148
malloc_unordered_map(PSI_memory_key psi_key)
Definition: map_helpers.h:154
std::unordered_multimap, but with my_malloc, so that you can track the memory used using PSI memory k...
Definition: map_helpers.h:189
malloc_unordered_multimap(PSI_memory_key psi_key)
Definition: map_helpers.h:196
std::unordered_set, but with my_malloc, so that you can track the memory used using PSI memory keys.
Definition: map_helpers.h:168
malloc_unordered_set(PSI_memory_key psi_key)
Definition: map_helpers.h:174
std::unordered_map, but collation aware and allocated on a MEM_ROOT.
Definition: map_helpers.h:316
mem_root_collation_unordered_map(const CHARSET_INFO *cs, MEM_ROOT *mem_root)
Definition: map_helpers.h:318
std::unordered_map, but allocated on a MEM_ROOT.
Definition: map_helpers.h:282
mem_root_unordered_map(MEM_ROOT *mem_root, Hash hash=Hash())
Definition: map_helpers.h:284
std::unordered_multimap, but allocated on a MEM_ROOT.
Definition: map_helpers.h:299
mem_root_unordered_multimap(MEM_ROOT *mem_root, Hash hash=Hash())
Definition: map_helpers.h:301
std::unordered_set, but allocated on a MEM_ROOT.
Definition: map_helpers.h:261
mem_root_unordered_set(MEM_ROOT *mem_root, Hash hash=Hash(), KeyEqual key_equal_arg=KeyEqual())
Definition: map_helpers.h:267
static MEM_ROOT mem_root
Definition: client_plugin.cc:110
Fido Client Authentication nullptr
Definition: fido_client_plugin.cc:222
unsigned int PSI_memory_key
Instrumented memory key.
Definition: psi_memory_bits.h:49
#define free(A)
Definition: lexyy.cc:915
A better implementation of the UNIX ctype(3) library.
Container::iterator erase_specific_element(Container *container, const typename Container::key_type &key, const Value &value)
For unordered_multimap<Key, Value>, erase the first specific element that matches both the given key ...
Definition: map_helpers.h:68
std::unique_ptr< T, Free_deleter > unique_ptr_free
std::unique_ptr, but with free as deleter.
Definition: map_helpers.h:105
std::unique_ptr< T, My_free_deleter > unique_ptr_my_free
std::unique_ptr, but with my_free as deleter.
Definition: map_helpers.h:97
std::unique_ptr< T, void(*)(T *)> unique_ptr_with_deleter
std::unique_ptr, but with a custom delete function.
Definition: map_helpers.h:89
static auto find_or_nullptr(const Container &container, const Key &key)
Some useful helpers for associative arrays with MySQL-specific semantics.
Definition: map_helpers.h:54
Some integer typedefs for easier portability.
uint64_t uint64
Definition: my_inttypes.h:69
void my_free(void *ptr)
Frees the memory pointed by the ptr.
Definition: my_memory.cc:81
int key_type
Definition: http_request.h:50
Definition: atomics_array.h:39
Definition: commit_order_queue.h:34
std::string_view Key
The key type for the hash structure in HashJoinRowBuffer.
Definition: hash_join_buffer.h:102
Definition: gcs_xcom_synode.h:64
std::unordered_map< Key, Value, Hash, Key_equal, ut::allocator< std::pair< const Key, Value > > > unordered_map
Definition: ut0new.h:2898
std::unordered_set< Key, std::hash< Key >, std::equal_to< Key >, ut::allocator< Key > > unordered_set
Definition: ut0new.h:2887
std::conditional_t< !std::is_array< T >::value, std::unique_ptr< T, detail::Deleter< T > >, std::conditional_t< detail::is_unbounded_array_v< T >, std::unique_ptr< T, detail::Array_deleter< std::remove_extent_t< T > > >, void > > unique_ptr
The following is a common type that is returned by all the ut::make_unique (non-aligned) specializati...
Definition: ut0new.h:2438
required string key
Definition: replication_asynchronous_connection_failover.proto:60
Definition: m_ctype.h:385
Definition: map_helpers.h:99
void operator()(void *ptr) const
Definition: map_helpers.h:100
The MEM_ROOT is a simple arena, where allocations are carved out of larger blocks.
Definition: my_alloc.h:83
Definition: map_helpers.h:91
void operator()(void *ptr) const
Definition: map_helpers.h:92