MySQL  8.0.27
Source Code Documentation
json_schema.h
Go to the documentation of this file.
1 /* Copyright (c) 2018, 2021, 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 SQL_JSON_SCHEMA_H_INCLUDED
24 #define SQL_JSON_SCHEMA_H_INCLUDED
25 
26 /**
27  @file json_schema.h
28 
29  Functions for validating a string against a JSON Schema
30 
31  A JSON Schema is a way to describe the structure of a JSON document. The JSON
32  Schema is a JSON document in itself, and allows you to define required
33  names/attributes, data types etc. As an example, here is a minimal example of
34  a JSON Schema describing that the JSON document MUST be an object:
35 
36  {
37  "type": "object"
38  }
39 
40  If the JSON document to be validated is anything else than an object (array,
41  scalar), the validation will fail.
42 
43  This file contains one class for validation JSON documents against a cached
44  JSON Schema, and free functions for validation any string input against a
45  (unparsed) JSON Schema. We use the rapidjson library to do the actual
46  validation with the following notable behaviors:
47 
48  1) Remote references are not supported. If the user provides a JSON Schema
49  with a remote reference, an error will be raised.
50  2) JSON Schema supports regex patterns, and we use std::regex as the regex
51  engine. If an invalid regex pattern is provided in the JSON Schema, the
52  regex pattern will be silently ignored.
53  3) rapidjson currently supports JSON Schema draft-v4, while there are newer
54  versions available (as of writing, draft-v7 is the latest version).
55  */
56 
57 #include "my_rapidjson_size_t.h" // IWYU pragma: keep
58 
59 #include <rapidjson/schema.h>
60 #include <cstddef>
61 #include <string>
62 
63 #include "my_alloc.h"
64 
65 struct MEM_ROOT;
66 
67 /**
68  Json_schema_validation_report contains a more detailed report about a failed
69  JSON Schema validation. It's mainly used by the function
70  JSON_SCHEMA_VALIDATION_REPORT to print out a more detailed report to the user.
71 */
73  public:
74  /// @returns a human readable reason why the validation failed
75  std::string human_readable_reason() const;
76 
77  /**
78  @returns a JSON pointer in URI format, pointing to where in the JSON
79  Schema the validation failed
80  */
81  const std::string &schema_location() const { return m_schema_location; }
82 
83  /**
84  @returns a string describing the name of the JSON Schema keyword that
85  failed validation
86  */
87  const std::string &schema_failed_keyword() const {
89  }
90 
91  /**
92  @returns a JSON pointer in URI format, pointing to where in the JSON
93  document the validation failed
94  */
95  const std::string &document_location() const { return m_document_location; }
96 
97  /**
98  Populates the object with validation information.
99 
100  @param schema_location a JSON pointer in URI format, pointing to where in
101  the JSON Schema the validation failed
102  @param schema_failed_keyword a string describing the name of the JSON Schema
103  keyword that failed validation
104  @param document_location a JSON pointer in URI format, pointing to where in
105  the JSON document the validation failed
106  */
107  void set_error_report(std::string &&schema_location,
108  const char *schema_failed_keyword,
109  std::string &&document_location) {
110  m_schema_location = std::move(schema_location);
113  }
114 
115  private:
116  std::string m_schema_location;
118  std::string m_document_location;
119 };
120 
121 /**
122  Json_schema_validator is an object that contains a JSON Schema that can
123  be re-used multiple times. This is useful in the cases where we have a JSON
124  Schema that doesn't change (which should be quite often).
125 */
127  public:
128  /**
129  Construct the cached JSON Schema with the provided JSON document
130 
131  @param schema_document A JSON document that contains the JSON Schema
132  definition
133  */
134  Json_schema_validator(const rapidjson::Document &schema_document);
135 
136  /**
137  Validate a JSON input against the cached JSON Schema
138 
139  @param document_str A pointer to the JSON input
140  @param document_length The length of the JSON input
141  @param function_name The function name of the caller (to be used in error
142  reporting)
143  @param[out] is_valid The result of the validation
144  @param[out] report A structure containing a detailed report from the
145  validation. Is only populated if is_valid is set to
146  "false" Can be nullptr if a detailed report isn't needed.
147 
148  @retval true on error (my_error has been called)
149  @retval false on success (validation result can be found in the output
150  parameter is_valid)
151  */
152  bool is_valid_json_schema(const char *document_str, size_t document_length,
153  const char *function_name, bool *is_valid,
154  Json_schema_validation_report *report) const;
155 
156  private:
157  /**
158  This object acts as a handler/callback for the JSON schema validator and is
159  called whenever a schema reference is encountered in the JSON document. Since
160  MySQL doesn't support schema references, this class is only used to detect
161  whether or not we actually found one in the JSON document.
162  */
164  : public rapidjson::IRemoteSchemaDocumentProvider {
165  public:
166  const rapidjson::SchemaDocument *GetRemoteDocument(
167  const char *, rapidjson::SizeType) override {
168  m_used = true;
169  return nullptr;
170  }
171 
172  bool used() const { return m_used; }
173 
174  private:
175  bool m_used{false};
176  };
177 
179  rapidjson::SchemaDocument m_cached_schema;
180 };
181 
182 /**
183  This function will validate a JSON document against a JSON Schema using the
184  validation provided by rapidjson.
185 
186  @param document_str A pointer to the JSON document to be validated.
187  @param document_length The length of the JSON document to be validated.
188  @param json_schema_str A pointer to the JSON Schema.
189  @param json_schema_length The length of the JSON Schema.
190  @param function_name The name of the SQL function calling this function. Used
191  in error reporting.
192  @param[out] is_valid A variable containing the result of the validation. If
193  true, the JSON document is valid according to the given
194  JSON Schema.
195  @param[out] report A structure containing a detailed report from the
196  validation. Is only populated if is_valid is set to
197  "false". Can be nullptr if a detailed report isn't needed.
198 
199  @retval true if anything went wrong (like parsing the JSON inputs). my_error
200  has been called with an appopriate error message.
201  @retval false if the validation succeeded. The result of the validation can be
202  found in the output variable "is_valid".
203 */
204 bool is_valid_json_schema(const char *document_str, size_t document_length,
205  const char *json_schema_str,
206  size_t json_schema_length, const char *function_name,
207  bool *is_valid,
209 
210 /**
211  Create a Json_schema_validator, allocated on a given MEM_ROOT
212 
213  @param mem_root The MEM_ROOT to allocate the validator on
214  @param json_schema_str A pointer to the JSON Schema
215  @param json_schema_length The length of the JSON Schema input
216  @param function_name The function name of the caller (to be used in error
217  reporting)
218 
219  @retval nullptr on error (my_error has been called)
220 */
222 create_json_schema_validator(MEM_ROOT *mem_root, const char *json_schema_str,
223  size_t json_schema_length,
224  const char *function_name);
225 
226 #endif
Json_schema_validation_report contains a more detailed report about a failed JSON Schema validation.
Definition: json_schema.h:72
const std::string & schema_location() const
Definition: json_schema.h:81
std::string m_schema_location
Definition: json_schema.h:116
const std::string & document_location() const
Definition: json_schema.h:95
std::string human_readable_reason() const
Definition: json_schema.cc:211
std::string m_document_location
Definition: json_schema.h:118
const std::string & schema_failed_keyword() const
Definition: json_schema.h:87
void set_error_report(std::string &&schema_location, const char *schema_failed_keyword, std::string &&document_location)
Populates the object with validation information.
Definition: json_schema.h:107
std::string m_schema_failed_keyword
Definition: json_schema.h:117
This object acts as a handler/callback for the JSON schema validator and is called whenever a schema ...
Definition: json_schema.h:164
bool used() const
Definition: json_schema.h:172
const rapidjson::SchemaDocument * GetRemoteDocument(const char *, rapidjson::SizeType) override
Definition: json_schema.h:166
Json_schema_validator is an object that contains a JSON Schema that can be re-used multiple times.
Definition: json_schema.h:126
bool is_valid_json_schema(const char *document_str, size_t document_length, const char *function_name, bool *is_valid, Json_schema_validation_report *report) const
Validate a JSON input against the cached JSON Schema.
Definition: json_schema.cc:131
Json_schema_validator(const rapidjson::Document &schema_document)
Construct the cached JSON Schema with the provided JSON document.
Definition: json_schema.cc:112
rapidjson::SchemaDocument m_cached_schema
Definition: json_schema.h:179
My_remote_schema_document_provider m_remote_document_provider
Definition: json_schema.h:178
static MEM_ROOT mem_root
Definition: client_plugin.cc:109
bool is_valid_json_schema(const char *document_str, size_t document_length, const char *json_schema_str, size_t json_schema_length, const char *function_name, bool *is_valid, Json_schema_validation_report *report)
This function will validate a JSON document against a JSON Schema using the validation provided by ra...
Definition: json_schema.cc:96
unique_ptr_destroy_only< const Json_schema_validator > create_json_schema_validator(MEM_ROOT *mem_root, const char *json_schema_str, size_t json_schema_length, const char *function_name)
Create a Json_schema_validator, allocated on a given MEM_ROOT.
Definition: json_schema.cc:118
This file follows Google coding style, except for the name MEM_ROOT (which is kept for historical rea...
std::unique_ptr< T, Destroy_only< T > > unique_ptr_destroy_only
std::unique_ptr, but only destroying.
Definition: my_alloc.h:464
Define rapidjson::SizeType to be std::size_t.
bool is_valid(const dd::Spatial_reference_system *srs, const Geometry *g, const char *func_name, bool *is_valid) noexcept
Decides if a geometry is valid.
Definition: is_valid.cc:94
::std::size_t SizeType
Definition: my_rapidjson_size_t.h:38
The MEM_ROOT is a simple arena, where allocations are carved out of larger blocks.
Definition: my_alloc.h:78