MySQL 9.1.0
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 "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/// @brief Allocator type used in Map_myalloc
141template <class Key, class Value>
143
144/// @brief Map using custom Malloc_allocator allocator
145template <class Key, class Value, class Compare = std::less<Key>>
147 std::map<Key, Value, Compare, Map_allocator_type<Key, Value>>;
148
149/**
150 std::unordered_map, but with my_malloc, so that you can track the memory
151 used using PSI memory keys.
152*/
153template <class Key, class Value, class Hash = std::hash<Key>,
154 class KeyEqual = std::equal_to<Key>>
156 : public std::unordered_map<Key, Value, Hash, KeyEqual,
157 Malloc_allocator<std::pair<const Key, Value>>> {
158 public:
159 /*
160 In theory, we should be allowed to send in the allocator only, but GCC 4.8
161 is missing several unordered_map constructors, so let's give in everything.
162 */
164 : std::unordered_map<Key, Value, Hash, KeyEqual,
165 Malloc_allocator<std::pair<const Key, Value>>>(
166 /*bucket_count=*/10, Hash(), KeyEqual(),
167 Malloc_allocator<>(psi_key)) {}
168};
169
170/**
171 std::unordered_set, but with my_malloc, so that you can track the memory
172 used using PSI memory keys.
173*/
174template <class Key, class Hash = std::hash<Key>,
175 class KeyEqual = std::equal_to<Key>>
177 : public std::unordered_set<Key, Hash, KeyEqual, Malloc_allocator<Key>> {
178 public:
179 /*
180 In theory, we should be allowed to send in the allocator only, but GCC 4.8
181 is missing several unordered_set constructors, so let's give in everything.
182 */
184 : std::unordered_set<Key, Hash, KeyEqual, Malloc_allocator<Key>>(
185 /*bucket_count=*/10, Hash(), KeyEqual(),
186 Malloc_allocator<>(psi_key)) {}
187};
188
189/**
190 std::unordered_multimap, but with my_malloc, so that you can track the memory
191 used using PSI memory keys.
192*/
193template <class Key, class Value, class Hash = std::hash<Key>,
194 class KeyEqual = std::equal_to<Key>>
196 : public std::unordered_multimap<
197 Key, Value, Hash, KeyEqual,
198 Malloc_allocator<std::pair<const Key, Value>>> {
199 public:
200 /*
201 In theory, we should be allowed to send in the allocator only, but GCC 4.8
202 is missing several unordered_multimap constructors, so let's give in
203 everything.
204 */
206 : std::unordered_multimap<Key, Value, Hash, KeyEqual,
207 Malloc_allocator<std::pair<const Key, Value>>>(
208 /*bucket_count=*/10, Hash(), KeyEqual(),
209 Malloc_allocator<>(psi_key)) {}
210};
211
212/**
213 std::unordered_map, but with my_malloc and collation-aware comparison.
214*/
215template <class Key, class Value>
217 : public std::unordered_map<Key, Value, Collation_hasher,
218 Collation_key_equal,
219 Malloc_allocator<std::pair<const Key, Value>>> {
220 public:
223 Malloc_allocator<std::pair<const Key, Value>>>(
224 /*bucket_count=*/10, Collation_hasher(cs), Collation_key_equal(cs),
225 Malloc_allocator<>(psi_key)) {}
226};
227
228/**
229 std::unordered_multimap, but with my_malloc and collation-aware comparison.
230*/
231template <class Key, class Value>
233 : public std::unordered_multimap<
234 Key, Value, Collation_hasher, Collation_key_equal,
235 Malloc_allocator<std::pair<const Key, Value>>> {
236 public:
238 : std::unordered_multimap<Key, Value, Collation_hasher,
240 Malloc_allocator<std::pair<const Key, Value>>>(
241 /*bucket_count=*/10, Collation_hasher(cs), Collation_key_equal(cs),
242 Malloc_allocator<>(psi_key)) {}
243};
244
245/**
246 std::unordered_set, but with my_malloc and collation-aware comparison.
247*/
248template <class Key>
250 : public std::unordered_set<Key, Collation_hasher, Collation_key_equal,
251 Malloc_allocator<Key>> {
252 public:
256 /*bucket_count=*/10, Collation_hasher(cs), Collation_key_equal(cs),
257 Malloc_allocator<>(psi_key)) {}
258 collation_unordered_set(std::initializer_list<Key> il, CHARSET_INFO *cs,
259 PSI_memory_key psi_key)
262 il, /*bucket_count=*/10, Collation_hasher(cs),
264};
265
266/** std::unordered_set, but allocated on a MEM_ROOT. */
267template <class Key, class Hash = std::hash<Key>,
268 class KeyEqual = std::equal_to<Key>>
270 : public std::unordered_set<Key, Hash, KeyEqual, Mem_root_allocator<Key>> {
271 public:
272 /*
273 In theory, we should be allowed to send in the allocator only, but GCC 4.8
274 is missing several unordered_set constructors, so let's give in everything.
275 */
277 KeyEqual key_equal_arg = KeyEqual())
279 /*bucket_count=*/10, hash, key_equal_arg,
281};
282
283/**
284 std::unordered_map, but allocated on a MEM_ROOT.
285*/
286template <class Key, class Value, class Hash = std::hash<Key>,
287 class KeyEqual = std::equal_to<Key>>
289 : public std::unordered_map<
290 Key, Value, Hash, KeyEqual,
291 Mem_root_allocator<std::pair<const Key, Value>>> {
292 public:
294 : std::unordered_map<Key, Value, Hash, KeyEqual,
295 Mem_root_allocator<std::pair<const Key, Value>>>(
296 /*bucket_count=*/10, hash, KeyEqual(),
297 Mem_root_allocator<std::pair<const Key, Value>>(mem_root)) {}
298};
299
300/**
301 std::unordered_multimap, but allocated on a MEM_ROOT.
302 */
303template <class Key, class Value, class Hash = std::hash<Key>,
304 class KeyEqual = std::equal_to<Key>>
306 : public std::unordered_multimap<
307 Key, Value, Hash, KeyEqual,
308 Mem_root_allocator<std::pair<const Key, Value>>> {
309 public:
311 : std::unordered_multimap<
312 Key, Value, Hash, KeyEqual,
313 Mem_root_allocator<std::pair<const Key, Value>>>(
314 /*bucket_count=*/10, hash, KeyEqual(),
315 Mem_root_allocator<std::pair<const Key, Value>>(mem_root)) {}
316};
317
318/**
319 std::unordered_map, but collation aware and allocated on a MEM_ROOT.
320*/
321template <class Key, class Value>
323 : public std::unordered_map<
324 Key, Value, Collation_hasher, Collation_key_equal,
325 Mem_root_allocator<std::pair<const Key, Value>>> {
326 public:
329 Mem_root_allocator<std::pair<const Key, Value>>>(
330 /*bucket_count=*/10, Collation_hasher(cs), Collation_key_equal(cs),
331 Mem_root_allocator<std::pair<const Key, Value>>(mem_root)) {}
332};
333
334#endif // MAP_HELPERS_INCLUDED
Kerberos Client Authentication nullptr
Definition: auth_kerberos_client_plugin.cc:251
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
std::unordered_map, but with my_malloc and collation-aware comparison.
Definition: map_helpers.h:219
collation_unordered_map(const CHARSET_INFO *cs, PSI_memory_key psi_key)
Definition: map_helpers.h:221
std::unordered_multimap, but with my_malloc and collation-aware comparison.
Definition: map_helpers.h:235
collation_unordered_multimap(CHARSET_INFO *cs, PSI_memory_key psi_key)
Definition: map_helpers.h:237
std::unordered_set, but with my_malloc and collation-aware comparison.
Definition: map_helpers.h:251
collation_unordered_set(std::initializer_list< Key > il, CHARSET_INFO *cs, PSI_memory_key psi_key)
Definition: map_helpers.h:258
collation_unordered_set(CHARSET_INFO *cs, PSI_memory_key psi_key)
Definition: map_helpers.h:253
std::unordered_map, but with my_malloc, so that you can track the memory used using PSI memory keys.
Definition: map_helpers.h:157
malloc_unordered_map(PSI_memory_key psi_key)
Definition: map_helpers.h:163
std::unordered_multimap, but with my_malloc, so that you can track the memory used using PSI memory k...
Definition: map_helpers.h:198
malloc_unordered_multimap(PSI_memory_key psi_key)
Definition: map_helpers.h:205
std::unordered_set, but with my_malloc, so that you can track the memory used using PSI memory keys.
Definition: map_helpers.h:177
malloc_unordered_set(PSI_memory_key psi_key)
Definition: map_helpers.h:183
std::unordered_map, but collation aware and allocated on a MEM_ROOT.
Definition: map_helpers.h:325
mem_root_collation_unordered_map(const CHARSET_INFO *cs, MEM_ROOT *mem_root)
Definition: map_helpers.h:327
std::unordered_map, but allocated on a MEM_ROOT.
Definition: map_helpers.h:291
mem_root_unordered_map(MEM_ROOT *mem_root, Hash hash=Hash())
Definition: map_helpers.h:293
std::unordered_multimap, but allocated on a MEM_ROOT.
Definition: map_helpers.h:308
mem_root_unordered_multimap(MEM_ROOT *mem_root, Hash hash=Hash())
Definition: map_helpers.h:310
std::unordered_set, but allocated on a MEM_ROOT.
Definition: map_helpers.h:270
mem_root_unordered_set(MEM_ROOT *mem_root, Hash hash=Hash(), KeyEqual key_equal_arg=KeyEqual())
Definition: map_helpers.h:276
static MEM_ROOT mem_root
Definition: client_plugin.cc:114
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
std::map< Key, Value, Compare, Map_allocator_type< Key, Value > > Map_myalloc
Map using custom Malloc_allocator allocator.
Definition: map_helpers.h:147
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
std::unordered_map< Key, CHARSET_INFO * > Hash
Definition: collations_internal.cc:548
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:108
int key_type
Definition: method.h:38
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:2900
std::unordered_set< Key, std::hash< Key >, std::equal_to< Key >, ut::allocator< Key > > unordered_set
Definition: ut0new.h:2889
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:2440
required string key
Definition: replication_asynchronous_connection_failover.proto:60
Definition: m_ctype.h:421
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