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