MySQL 9.1.0
Source Code Documentation
sdi_impl.h
Go to the documentation of this file.
1/* Copyright (c) 2015, 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 DD_SERIALIZE_IMPL_H_INCLUDED
25#define DD_SERIALIZE_IMPL_H_INCLUDED
26
27#include "my_rapidjson_size_t.h" // IWYU pragma: keep
28
29#include <assert.h>
30#include <rapidjson/document.h> // rapidjson::GenericValue
31#include <rapidjson/prettywriter.h> // rapidjson::PrettyWriter
32#include <memory>
33
34#include "base64.h" // base64_encode
35
36#include "prealloced_array.h" // Prealloced_array
37#include "sql/dd/object_id.h" // Object_id typedef
38#include "sql/dd/string_type.h"
39
40/**
41 @file
42 @ingroup SDI
43 Internal (private) header file for the (de)serialization code. This
44 file is made up of 5 parts:
45
46 @ref int_func_decl
47 @ref prealloced_typedefs
48 @ref value_overloads
49 @ref key_templates
50 @ref special_composite_templates
51*/
52
53/**
54 @defgroup int_func_decl Internal Sdi_context Functions
55 @ingroup sdi
56
57 Declarations of internal functions which operate on Sdi_context
58 objects. Conceptually these are member functions of Sdi_context,
59 but declaring them as such would mean that the definition of
60 Sdi_context would have had to be made available in every
61 translation unit where these functions get called (most data
62 dictionary object implementation files).
63
64 This is essentially a modification of the pimpl (Pointer to
65 IMPLementation) idiom where we avoid the need to create separate
66 api and implementation classes and avoid the extra indirection of
67 going through the pimpl pointer.
68
69 @{
70*/
71
72namespace dd {
73class Column;
74class Index;
75class Properties;
76template <typename T>
77class Collection;
78/**
79 Factory function for creating a Property object from String_type.
80
81 @param str string representation of properties
82 */
84
85class Sdi_wcontext;
86
87/**
88 Return a non-owning pointer to a char buffer which can be used
89 for e.g. base64 encoding.
90 @param wctx opaque context.
91 @param sz size of buffer.
92*/
93char *buf_handle(Sdi_wcontext *wctx, size_t sz);
94
95/**
96 Returns const reference to string holding schema name to use in SDI.
97 @param wctx opaque context.
98 @return schema name to use.
99*/
100
102
103/**
104 Look up the tablespace name for a tablespace id. Returns a reference
105 to the name string inside an acquired tablespace object. The
106 lifetime of these tablespace objects are managed by the
107 Auto_releaser in the scope where the dd store is initiated.
108
109 @param wctx opaque context
110 @param id tablespace id to look up
111 @return tablespace name ref
112*/
113
115 dd::Object_id id);
116
117class Sdi_rcontext;
118
119/**
120 Register Column objects being deserialized so that it will be
121 possible to resolve references to it after deserialization has
122 finished.
123
124 @param rctx opaque context
125 @param column_object object which may be referenced by other objects.
126*/
127
128void track_object(Sdi_rcontext *rctx, Column *column_object);
129
130/**
131 Register Index objects being deserialized so that it will be
132 possible to resolve references to it after deserialization has
133 finished.
134
135 @param rctx opaque context
136 @param index_object object which may be referenced by other objects.
137*/
138
139void track_object(Sdi_rcontext *rctx, Index *index_object);
140
141/**
142 Return an non-owning raw pointer to the deserialized Index object
143 with ordinal position index opx (ordinal position opx+1). The unused
144 const Index* argument is needed for overload resolution.
145
146 @param rctx opaque context
147 @param opx ordinal position index
148*/
149
150Index *get_by_opx(Sdi_rcontext *rctx, const Index *, uint opx);
151
152/**
153 Return an non-owning raw pointer to the deserialized Column object
154 with ordinal position index opx (ordinal position opx+1). The unused
155 const Column* argument is needed for overload resolution.
156
157 @param rctx opaque context
158 @param opx ordinal position index
159*/
160
161Column *get_by_opx(Sdi_rcontext *rctx, const Column *, uint opx);
162
163/**
164 Return a non-owning pointer to a char buffer which can be used
165 for e.g. base64 encoding.
166 @param rctx opaque context
167 @param sz size of buffer
168 @return non-owning pointer to buffer
169*/
170
171char *buf_handle(Sdi_rcontext *rctx, size_t sz);
172
173/**
174 Return the the Object_id of a schema name in the current data
175 dictionary. Used to recreate a reference to a schema during
176 deserialization.
177
178 @param rctx opaque context.
179 @param name schema name used as reference.
180 @param idp [OUT] pointer to Object_id variable where result is stored.
181 @return MySQL error handling.
182 */
183
185 Object_id *idp);
186
187/**
188 Return the the Object_id of a tablespace name in the current data
189 dictionary. Used to recreate a reference to a tablespace during
190 deserialization.
191
192 @param rctx opaque context.
193 @param name schema name used as reference.
194 @param idp [OUT] pointer to Object_id variable where result is stored.
195 @return MySQL error handling.
196
197 */
198
200 Object_id *idp);
201
202} // namespace dd
203
204/** @} */ // int_func_decl
205
206/**
207 @defgroup prealloced_typedefs Prealloced_array Typedefs
208 @ingroup sdi
209
210 Defines a sub-class of Prealloced_array and some useful typedefs for use in
211 (de)serialization code.
212 @{
213*/
214
216template <typename T, size_t PREALLOC = 16>
217struct dd_vector : public Prealloced_array<T, PREALLOC> {
219 : Prealloced_array<T, PREALLOC>(psi_key) {}
220};
221
223
224/** @} */ // prealloced_typedefs
225
226/**
227 @defgroup value_overloads Value Function Overloads
228 @ingroup sdi
229
230 Defines function templates for writing a "bare" (without the key) json value.
231 Each definition is overloaded on the second argument (which isn't a template
232 argument) to handle each builtin type that has a corresponding rapidjson type.
233 @{
234*/
235
236template <typename W>
237void write_value(W *w, bool a) {
238 w->Bool(a);
239}
240
241template <typename GV>
242bool read_value(bool *ap, const GV &gv) {
243 if (!gv.IsBool()) {
244 return true;
245 }
246 *ap = gv.GetBool();
247 return false;
248}
249
250template <typename W>
251void write_value(W *w, int a) {
252 w->Int(a);
253}
254
255template <typename GV>
256bool read_value(int *ap, const GV &gv) {
257 if (!gv.IsInt()) {
258 return true;
259 }
260 *ap = gv.GetInt();
261 return false;
262}
263
264template <typename W>
265void write_value(W *w, uint a) {
266 w->Uint(a);
267}
268
269template <typename GV>
270bool read_value(uint *ap, const GV &gv) {
271 if (!gv.IsUint()) {
272 return true;
273 }
274 *ap = gv.GetUint();
275 return false;
276}
277
278template <typename W>
279void write_value(W *w, ulong a) {
280 w->Uint64(a);
281}
282
283template <typename GV>
284bool read_value(ulong *ap, const GV &gv) {
285 if (!gv.IsUint64()) {
286 return true;
287 }
288 *ap = gv.GetUint64();
289 return false;
290}
291
292template <typename W>
293void write_value(W *w, ulonglong a) {
294 w->Uint64(a);
295}
296
297template <typename GV>
298bool read_value(ulonglong *ap, const GV &gv) {
299 if (!gv.IsUint64()) {
300 return true;
301 }
302 *ap = gv.GetUint64();
303 return false;
304}
305
306template <typename W>
307void write_value(W *w, const dd::String_type &a) {
308 w->String(a.c_str(), a.size());
309}
310
311template <typename GV>
312bool read_value(dd::String_type *ap, const GV &gv) {
313 if (!gv.IsString()) {
314 return true;
315 }
316 *ap = dd::String_type(gv.GetString(), gv.GetStringLength());
317 return false;
318}
319/** @} */ // value_overloads
320
321template <typename W>
323
324/**
325 @defgroup key_templates Key-related Function Templates
326 @ingroup sdi
327
328 Defines wrapper function templates which handles the key part when
329 writing and writing json.
330
331 @{
332*/
333
334template <typename W, typename T>
335void write(W *w, const T &t, const char *key, size_t key_sz) {
336 w->String(key, key_sz);
337 write_value(w, t);
338}
339
340template <typename T, typename GV>
341bool read(T *ap, const GV &gv, const char *key) {
342 if (!gv.HasMember(key)) {
343 return true;
344 }
345
346 return read_value(ap, gv[key]);
347}
348
349/** @} */ // key_templates
350
351/**
352 @defgroup special_composite_templates Function Templates for Composite Types
353 @ingroup sdi
354
355 Defines function templates to handle types that do not map directly
356 to a rapidjson type, and require some amount of converson/adaptation.
357
358 @{
359*/
360
361template <typename W, typename ENUM_T>
362void write_enum(W *w, ENUM_T enum_val, const char *key, size_t keysz) {
363 write(w, static_cast<ulonglong>(enum_val), key, keysz);
364}
365
366template <typename ENUM_T, typename GV>
367bool read_enum(ENUM_T *ep, const GV &gv, const char *key) {
368 ulonglong v = 0;
369 if (read(&v, gv, key)) {
370 return true;
371 }
372 *ep = static_cast<ENUM_T>(v);
373 return false;
374}
375
376template <typename W>
377void write_binary(dd::Sdi_wcontext *wctx, W *w, const binary_t &b,
378 const char *key, size_t keysz) {
379 int binsz = static_cast<int>(b.size());
380 int b64sz = base64_needed_encoded_length(binsz);
381
382 char *bp = dd::buf_handle(wctx, static_cast<size_t>(b64sz));
383 assert(bp);
384
385 base64_encode(b.c_str(), binsz, bp);
386 w->String(key, keysz);
387 w->String(bp);
388}
389
390template <typename GV>
391bool read_binary(dd::Sdi_rcontext *rctx, binary_t *b, const GV &gv,
392 const char *key) {
393 if (!gv.HasMember(key)) {
394 return true;
395 }
396
397 const GV &a_gv = gv[key];
398
399 if (!a_gv.IsString()) {
400 return true;
401 }
402
403 const char *b64 = a_gv.GetString();
404 size_t b64sz = a_gv.GetStringLength();
405 int binsz = base64_needed_decoded_length(b64sz);
406
407 char *bp = dd::buf_handle(rctx, static_cast<size_t>(binsz));
408 binsz = base64_decode(b64, b64sz, bp, nullptr, 0);
409 *b = binary_t(bp, binsz);
410 return false;
411}
412
413template <typename W, typename PP>
414void write_properties(W *w, const PP &p, const char *key, size_t keysz) {
415 write(w, p.raw_string(), key, keysz);
416}
417
418template <typename PP, typename GV>
419bool read_properties(PP *p, const GV &gv, const char *key) {
420 dd::String_type raw_string;
421 if (read(&raw_string, gv, key)) {
422 return true;
423 }
424 p->insert_values(raw_string);
425 return false;
426}
427
428template <typename W, typename PP>
429void write_opx_reference(W *w, const PP &p, const char *key, size_t keysz) {
430 uint opx = 0;
431 if (p) {
432 assert(p->ordinal_position() > 0);
433 opx = p->ordinal_position() - 1;
434 write(w, opx, key, keysz);
435 }
436}
437
438template <typename PP, typename GV>
439bool read_opx_reference(dd::Sdi_rcontext *rctx, PP *p, const GV &gv,
440 const char *key) {
441 uint opx = 0;
442 if (read(&opx, gv, key)) {
443 return true;
444 }
445 *p = get_by_opx(rctx, *p, opx);
446 return false;
447}
448
449template <typename GV>
451 const GV &gv, const char *key) {
452 dd::String_type schema_name;
453 return (read(&schema_name, gv, key) ||
454 lookup_schema_ref(rctx, schema_name, p));
455}
456
457template <typename W>
459 dd::Object_id tablespace_id, const char *key,
460 size_t keysz) {
461 if (tablespace_id == dd::INVALID_OBJECT_ID) {
462 // There is no name to look up (will be the case for SEs not using
463 // tablespaces
464 return;
465 }
466 const dd::String_type &tablespace_name =
467 lookup_tablespace_name(wctx, tablespace_id);
468
469 if (tablespace_name.empty()) {
470 return;
471 }
472 write(w, tablespace_name, key, keysz);
473}
474
475template <typename GV>
477 const GV &gv, const char *key) {
478 dd::String_type tablespace_name;
479 if (read(&tablespace_name, gv, key)) {
480 return false; // Ok not to have this
481 }
482 return lookup_tablespace_ref(rctx, tablespace_name, p);
483}
484
485template <typename W, typename C>
487 const char *key, size_t keysz) {
488 w->String(key, keysz);
489 w->StartArray();
490 for (const C *vp : cp) {
491 vp->serialize(wctx, w);
492 }
493 w->EndArray(cp.size());
494}
495
496template <typename ADD_BINDER, typename GV>
497bool deserialize_each(dd::Sdi_rcontext *rctx, ADD_BINDER add_binder,
498 const GV &obj_gv, const char *key) {
499 if (!obj_gv.HasMember(key)) {
500 return true;
501 }
502
503 const GV &array_gv = obj_gv[key];
504 if (!array_gv.IsArray()) {
505 return true;
506 }
507
508 const typename GV::ConstValueIterator end = array_gv.End();
509 for (typename GV::ConstValueIterator it = array_gv.Begin(); it != end; ++it) {
510 if (add_binder()->deserialize(rctx, *it)) {
511 return true;
512 }
513 }
514 return false;
515}
516/** @} */ // special_composite_templates
517
518//} // namespace dd_sdi_impl
519
520#endif /* DD_SERIALIZE_IMPL_H_INCLUDED */
A typesafe replacement for DYNAMIC_ARRAY.
Definition: prealloced_array.h:71
Definition: collection.h:44
size_t size() const
Definition: collection.h:229
Definition: column.h:88
Definition: index.h:51
The Properties class defines an interface for storing key=value pairs, where both key and value may b...
Definition: properties.h:74
Opaque context which keeps reusable resoureces needed during deserialization.
Definition: sdi.cc:231
Opaque context which keeps reusable resources needed during serialization.
Definition: sdi.cc:129
const char * p
Definition: ctype-mb.cc:1225
bool read(T *ap, const GV &gv, const char *key)
Definition: sdi_impl.h:341
void write(W *w, const T &t, const char *key, size_t key_sz)
Definition: sdi_impl.h:335
dd::String_type binary_t
Definition: sdi_impl.h:215
dd_vector< char, 32 > Byte_buffer
Definition: sdi_impl.h:222
unsigned int PSI_memory_key
Instrumented memory key.
Definition: psi_memory_bits.h:49
bool deserialize(THD *thd, const Sdi_type &sdi, Table *dst_table, SdiCompatibilityChecker comp_checker, String_type *deser_schema_name)
Deserialize a dd::Table object.
Definition: sdi.cc:475
bool read_properties(PP *p, const GV &gv, const char *key)
Definition: sdi_impl.h:419
void serialize_each(dd::Sdi_wcontext *wctx, W *w, const dd::Collection< C * > &cp, const char *key, size_t keysz)
Definition: sdi_impl.h:486
bool read_opx_reference(dd::Sdi_rcontext *rctx, PP *p, const GV &gv, const char *key)
Definition: sdi_impl.h:439
bool deserialize_each(dd::Sdi_rcontext *rctx, ADD_BINDER add_binder, const GV &obj_gv, const char *key)
Definition: sdi_impl.h:497
bool read_enum(ENUM_T *ep, const GV &gv, const char *key)
Definition: sdi_impl.h:367
void write_binary(dd::Sdi_wcontext *wctx, W *w, const binary_t &b, const char *key, size_t keysz)
Definition: sdi_impl.h:377
bool deserialize_schema_ref(dd::Sdi_rcontext *rctx, dd::Object_id *p, const GV &gv, const char *key)
Definition: sdi_impl.h:450
bool deserialize_tablespace_ref(dd::Sdi_rcontext *rctx, dd::Object_id *p, const GV &gv, const char *key)
Definition: sdi_impl.h:476
void serialize_tablespace_ref(dd::Sdi_wcontext *wctx, W *w, dd::Object_id tablespace_id, const char *key, size_t keysz)
Definition: sdi_impl.h:458
void write_opx_reference(W *w, const PP &p, const char *key, size_t keysz)
Definition: sdi_impl.h:429
bool read_binary(dd::Sdi_rcontext *rctx, binary_t *b, const GV &gv, const char *key)
Definition: sdi_impl.h:391
void write_enum(W *w, ENUM_T enum_val, const char *key, size_t keysz)
Definition: sdi_impl.h:362
void write_properties(W *w, const PP &p, const char *key, size_t keysz)
Definition: sdi_impl.h:414
bool read_value(bool *ap, const GV &gv)
Definition: sdi_impl.h:242
void write_value(W *w, bool a)
Definition: sdi_impl.h:237
static uint64 base64_needed_decoded_length(uint64 length_of_encoded_data)
Definition: base64.h:227
static uint64 base64_needed_encoded_length(uint64 length_of_data)
Definition: base64.h:203
static int64 base64_decode(const char *src_base, size_t len, void *dst, const char **end_ptr, int flags)
Decode a base64 string The base64-encoded data in the range ['src','*end_ptr') will be decoded and st...
Definition: base64.h:304
static int base64_encode(const void *src, size_t src_len, char *dst)
Definition: base64.h:243
unsigned long long int ulonglong
Definition: my_inttypes.h:56
Define rapidjson::SizeType to be std::uint64_t.
std::string str(const mysqlrouter::ConfigGenerator::Options::Endpoint &ep)
Definition: config_generator.cc:1105
The version of the current data dictionary table definitions.
Definition: dictionary_client.h:43
const String_type & lookup_tablespace_name(Sdi_wcontext *wctx, dd::Object_id id)
Look up the tablespace name for a tablespace id.
Definition: sdi.cc:189
Index * get_by_opx(dd::Sdi_rcontext *sdictx, const Index *, uint opx)
Return an non-owning raw pointer to the deserialized Index object with ordinal position index opx (or...
Definition: sdi.cc:298
unsigned long long Object_id
Definition: object_id.h:31
bool lookup_schema_ref(Sdi_rcontext *sdictx, const String_type &name, dd::Object_id *idp)
Return the the Object_id of a schema name in the current data dictionary.
Definition: sdi.cc:341
const String_type & lookup_schema_name(Sdi_wcontext *wctx)
Returns const reference to string holding schema name to use in SDI.
Definition: sdi.cc:157
char * buf_handle(Sdi_wcontext *wctx, size_t sz)
Return a non-owning pointer to a char buffer which can be used for e.g.
Definition: sdi.cc:153
const Object_id INVALID_OBJECT_ID
The default object ID which represents that the DD object is new and not persistent in dictionary tab...
Definition: object_id.h:37
bool lookup_tablespace_ref(Sdi_rcontext *sdictx, const String_type &name, Object_id *idp)
Return the the Object_id of a tablespace name in the current data dictionary.
Definition: sdi.cc:348
void track_object(Sdi_rcontext *sdictx, Column *column_object)
Register Column objects being deserialized so that it will be possible to resolve references to it af...
Definition: sdi.cc:290
Char_string_template< String_type_allocator > String_type
Definition: string_type.h:51
Properties * parse_properties(const String_type &str)
Factory function for creating a Property object from String_type.
Cursor end()
A past-the-end Cursor.
Definition: rules_table_service.cc:192
required string key
Definition: replication_asynchronous_connection_failover.proto:60
case opt name
Definition: sslopt-case.h:29
Definition: sdi_impl.h:217
dd_vector(PSI_memory_key psi_key=0)
Definition: sdi_impl.h:218