1 /*
2 Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License, version 2.0,
6 as published by the Free Software Foundation.
7
8 This program is also distributed with certain software (including
9 but not limited to OpenSSL) that is licensed under separate terms,
10 as designated in a particular file or component or in included license
11 documentation. The authors of MySQL hereby grant you an additional
12 permission to link the program and your derivative works with the
13 separately licensed software that they have included with MySQL.
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
25 // Implements the function defined in ndb_dd_sdi.h
26 #include "storage/ndb/plugin/ndb_dd_sdi.h"
27
28 // Using
29 #include "my_rapidjson_size_t.h" // IWYU pragma: keep
30
31 #include <rapidjson/document.h> // rapidjson::Document
32 #include <rapidjson/prettywriter.h> // rapidjson::PrettyWriter
33 #include <rapidjson/stringbuffer.h>
34 #include <rapidjson/writer.h> // rapidjson::Writer
35
36 #include "my_sys.h" // my_error
37 #include "mysql_version.h" // MYSQL_VERSION_ID
38 #include "mysqld_error.h" // ER_IMP_INCOMPATIBLE_MYSQLD_VERSION
39 #include "sql/dd/impl/sdi.h"
40 #include "sql/dd/sdi_fwd.h"
41 #include "sql/dd/string_type.h"
42
43 typedef rapidjson::Writer<dd::RJ_StringBuffer, dd::RJ_Encoding, dd::RJ_Encoding,
44 dd::RJ_Allocator, 0>
45 MinifyWriter;
46 typedef rapidjson::PrettyWriter<dd::RJ_StringBuffer, dd::RJ_Encoding,
47 dd::RJ_Encoding, dd::RJ_Allocator, 0>
48 PrettyWriter;
49
50 #ifndef DBUG_OFF
51 /*
52 @brief minify a JSON formatted SDI. Remove whitespace and other
53 useless data.
54
55 @note the JSON format is normally in 'pretty' format which takes
56 up much more storage space and network bandwidth than 'minified' format.
57
58 @sdi the JSON string to minify
59
60 @return minified JSON string or empty string on failure.
61 */
62
minify(dd::sdi_t sdi)63 static dd::sdi_t minify(dd::sdi_t sdi) {
64 dd::RJ_Document doc;
65 doc.Parse<0>(sdi.c_str());
66
67 if (doc.HasParseError()) {
68 return "";
69 }
70
71 dd::RJ_StringBuffer buf;
72 MinifyWriter w(buf);
73 if (!doc.Accept(w)) {
74 return "";
75 }
76
77 return buf.GetString();
78 }
79 #endif
80
ndb_dd_sdi_prettify(dd::sdi_t sdi)81 dd::sdi_t ndb_dd_sdi_prettify(dd::sdi_t sdi) {
82 dd::RJ_Document doc;
83 doc.Parse<0>(sdi.c_str());
84
85 if (doc.HasParseError()) {
86 return "";
87 }
88
89 dd::RJ_StringBuffer buf;
90 PrettyWriter w(buf);
91 if (!doc.Accept(w)) {
92 return "";
93 }
94
95 return buf.GetString();
96 }
97
check_sdi_compatibility(const dd::RJ_Document & doc)98 static bool check_sdi_compatibility(const dd::RJ_Document &doc) {
99 // Check mysql_version_id
100 DBUG_ASSERT(doc.HasMember("mysqld_version_id"));
101 const dd::RJ_Value &mysqld_version_id = doc["mysqld_version_id"];
102 DBUG_ASSERT(mysqld_version_id.IsUint64());
103 if (mysqld_version_id.GetUint64() > std::uint64_t(MYSQL_VERSION_ID)) {
104 // Cannot deserialize SDIs from newer versions
105 my_error(ER_IMP_INCOMPATIBLE_MYSQLD_VERSION, MYF(0),
106 mysqld_version_id.GetUint64(), std::uint64_t(MYSQL_VERSION_ID));
107 return true;
108 }
109 // Skip dd_version and sdi_version checks to ensure compatibility during
110 // upgrades
111 return false;
112 }
113
ndb_dd_sdi_deserialize(THD * thd,const dd::sdi_t & sdi,dd::Table * table)114 bool ndb_dd_sdi_deserialize(THD *thd, const dd::sdi_t &sdi, dd::Table *table) {
115 const dd::SdiCompatibilityChecker comp_checker = check_sdi_compatibility;
116 return dd::deserialize(thd, sdi, table, comp_checker);
117 }
118
ndb_dd_sdi_serialize(THD * thd,const dd::Table & table,const dd::String_type & schema_name)119 dd::sdi_t ndb_dd_sdi_serialize(THD *thd, const dd::Table &table,
120 const dd::String_type &schema_name) {
121 #ifndef DBUG_OFF
122 // Verify that dd::serialize generates SDI in minimzed format
123 dd::sdi_t sdi = dd::serialize(thd, table, schema_name);
124 DBUG_ASSERT(minify(sdi) == sdi);
125 #endif
126 return dd::serialize(thd, table, schema_name);
127 }
128