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