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