MySQL 8.0.40
Source Code Documentation
|
Abstraction for accessing JSON values irrespective of whether they are (started out as) binary JSON values or JSON DOM values. More...
#include <json_dom.h>
Public Member Functions | |
const char * | get_datetime_packed (char *buffer) const |
Get the wrapped datetime value in the packed format. More... | |
Json_wrapper () | |
Create an empty wrapper. More... | |
Json_wrapper (Json_dom *dom_value, bool alias=false) | |
Wrap the supplied DOM value (no copy taken). More... | |
Json_wrapper (Json_dom_ptr dom_value) | |
Wrap the supplied DOM value. More... | |
void | set_alias () |
Only meaningful iff the wrapper encapsulates a DOM. More... | |
Json_wrapper (const json_binary::Value &value) | |
Wrap a binary value. More... | |
Json_wrapper (const Json_wrapper &old) | |
Copy constructor. More... | |
Json_wrapper (Json_wrapper &&old) noexcept | |
Move constructor. More... | |
Json_wrapper & | operator= (const Json_wrapper &old) |
Assignment operator. More... | |
Json_wrapper & | operator= (Json_wrapper &&old) noexcept |
Move-assignment operator. More... | |
~Json_wrapper () | |
bool | empty () const |
A Wrapper is defined to be empty if it is passed a NULL value with the constructor for JSON dom, or if the default constructor is used. More... | |
bool | is_dom () const |
Does this wrapper contain a DOM? More... | |
Json_dom * | to_dom () |
Get the wrapped contents in DOM form. More... | |
const Json_dom * | get_dom () const |
Gets a pointer to the wrapped Json_dom object, if this wrapper holds a DOM. More... | |
const json_binary::Value & | get_binary_value () const |
Gets the wrapped json_binary::Value object, if this wrapper holds a binary JSON value. More... | |
Json_dom_ptr | clone_dom () const |
Get the wrapped contents in DOM form. More... | |
bool | to_binary (const THD *thd, String *str) const |
Get the wrapped contents in binary value form. More... | |
bool | is_binary_backed_by (const String *str) const |
Check if the wrapped JSON document is a binary value (a json_binary::Value), and if that binary is pointing to data stored in the given string. More... | |
bool | to_string (String *buffer, bool json_quoted, const char *func_name, const JsonDocumentDepthHandler &depth_handler) const |
Format the JSON value to an external JSON string in buffer in the format of ISO/IEC 10646. More... | |
void | dbug_print (const char *message, const JsonDocumentDepthHandler &depth_handler) const |
Print this JSON document to the debug trace. More... | |
bool | to_pretty_string (String *buffer, const char *func_name, const JsonDocumentDepthHandler &depth_handler) const |
Format the JSON value to an external JSON string in buffer in the format of ISO/IEC 10646. More... | |
enum_json_type | type () const |
Return the type of the wrapped JSON value. More... | |
enum_field_types | field_type () const |
Return the MYSQL type of the opaque value, see type(). More... | |
Json_wrapper | operator[] (size_t index) const |
If this wrapper holds a JSON array, get an array value by indexing into the array. More... | |
Json_wrapper | lookup (const MYSQL_LEX_CSTRING &key) const |
If this wrapper holds a JSON object, get the value corresponding to the member key. More... | |
const char * | get_data () const |
Get a pointer to the data of a JSON string or JSON opaque value. More... | |
size_t | get_data_length () const |
Get the length to the data of a JSON string or JSON opaque value. More... | |
bool | get_decimal_data (my_decimal *d) const |
Get the MySQL representation of a JSON decimal value. More... | |
double | get_double () const |
Get the value of a JSON double number. More... | |
longlong | get_int () const |
Get the value of a JSON signed integer number. More... | |
ulonglong | get_uint () const |
Get the value of a JSON unsigned integer number. More... | |
void | get_datetime (MYSQL_TIME *t) const |
Get the value of a JSON date/time value. More... | |
bool | get_boolean () const |
Get a boolean value (a JSON true or false literal). More... | |
bool | seek (const Json_seekable_path &path, size_t legs, Json_wrapper_vector *hits, bool auto_wrap, bool only_need_one) |
Finds all of the json sub-documents which match the path expression. More... | |
size_t | length () const |
Compute the length of a document. More... | |
int | compare (const Json_wrapper &other, const CHARSET_INFO *cs=nullptr) const |
Compare this JSON value to another JSON value. More... | |
longlong | coerce_int (const char *msgnam, enum_coercion_error cr_error, bool *err, bool *unsigned_flag) const |
Extract an int (signed or unsigned) from the JSON if possible coercing if need be. More... | |
longlong | coerce_int (const char *msgnam) const |
Shorthand for coerce_int(msgnam, CE_WARNING, nullptr, nullptr). More... | |
double | coerce_real (const char *msgnam, enum_coercion_error cr_error, bool *err) const |
Extract a real from the JSON if possible, coercing if need be. More... | |
double | coerce_real (const char *msgnam) const |
Shorthand for coerce_real(msgnam, CE_WARNING, nullptr). More... | |
my_decimal * | coerce_decimal (my_decimal *decimal_value, const char *msgnam, enum_coercion_error cr_error, bool *err) const |
Extract a decimal from the JSON if possible, coercing if need be. More... | |
my_decimal * | coerce_decimal (my_decimal *decimal_value, const char *msgnam) |
Shorthand for coerce_decimal(decimal_value, msgnam, CE_WARNING, nullptr). More... | |
bool | coerce_date (MYSQL_TIME *ltime, const char *msgnam, enum_coercion_error cr_error=CE_WARNING, my_time_flags_t date_flags_arg=0) const |
Extract a date from the JSON if possible, coercing if need be. More... | |
bool | coerce_time (MYSQL_TIME *ltime, const char *msgnam, enum_coercion_error cr_error=CE_WARNING) const |
Extract a time value from the JSON if possible, coercing if need be. More... | |
size_t | make_sort_key (uchar *to, size_t length) const |
Make a sort key that can be used by filesort to order JSON values. More... | |
ulonglong | make_hash_key (ulonglong hash_val) const |
Make a hash key that can be used by sql_executor.cc/unique_hash in order to support SELECT DISTINCT. More... | |
bool | get_free_space (size_t *space) const |
Calculate the amount of unused space inside a JSON binary value. More... | |
bool | attempt_binary_update (const Field_json *field, const Json_seekable_path &path, Json_wrapper *new_value, bool replace, String *result, bool *partially_updated, bool *replaced_path) |
Attempt a binary partial update by replacing the value at path with new_value. More... | |
bool | binary_remove (const Field_json *field, const Json_seekable_path &path, String *result, bool *found_path) |
Remove a path from a binary JSON document. More... | |
void | sort (const CHARSET_INFO *cs=nullptr) |
Sort contents. More... | |
void | remove_duplicates (const CHARSET_INFO *cs=nullptr) |
Remove duplicate values. More... | |
Private Attributes | |
union { | |
struct { | |
Json_dom * m_value | |
bool m_alias | |
If true, don't deallocate m_dom_value in destructor. More... | |
} m_dom | |
The DOM representation, only used if m_is_dom is true. More... | |
json_binary::Value m_value | |
The binary representation, only used if m_is_dom is false. More... | |
}; | |
bool | m_is_dom |
Wraps a DOM iff true. More... | |
Abstraction for accessing JSON values irrespective of whether they are (started out as) binary JSON values or JSON DOM values.
The purpose of this is to allow uniform access for callers. It allows us to access binary JSON values without necessarily building a DOM (and thus having to read the entire value unless necessary, e.g. for accessing only a single array slot or object field).
Instances of this class are usually created on the stack. In some cases instances are cached in an Item and reused, in which case they are allocated from query-duration memory (by allocating them on a MEM_ROOT).
|
inline |
Create an empty wrapper.
Cf empty().
|
explicit |
Wrap the supplied DOM value (no copy taken).
The wrapper takes ownership, unless alias is true or set_alias
is called after construction. In the latter case the lifetime of the DOM is determined by the owner of the DOM, so clients need to ensure that that lifetime is sufficient, lest dead storage is attempted accessed.
[in,out] | dom_value | the DOM value |
alias | Whether the wrapper is an alias to DOM |
< no deallocation, make us empty
|
inlineexplicit |
Wrap the supplied DOM value.
The wrapper takes over the ownership.
|
explicit |
Wrap a binary value.
Does not copy the underlying buffer, so lifetime is limited the that of the supplied value.
[in] | value | the binary value |
Json_wrapper::Json_wrapper | ( | const Json_wrapper & | old | ) |
Copy constructor.
Does a deep copy of any owned DOM. If a DOM os not owned (aliased), the copy will also be aliased.
|
noexcept |
Move constructor.
Take over the ownership of the other wrapper's DOM, unless it's aliased. If the other wrapper is aliased, this wrapper becomes an alias too. Any already owned DOM will be deallocated.
old | the wrapper whose contents to take over |
Json_wrapper::~Json_wrapper | ( | ) |
bool Json_wrapper::attempt_binary_update | ( | const Field_json * | field, |
const Json_seekable_path & | path, | ||
Json_wrapper * | new_value, | ||
bool | replace, | ||
String * | result, | ||
bool * | partially_updated, | ||
bool * | replaced_path | ||
) |
Attempt a binary partial update by replacing the value at path with new_value.
On successful completion, the updated document will be available in result, and this Json_wrapper will point to result instead of the original binary representation. The modifications that have been applied, will also be collected as binary diffs, which can be retrieved via TABLE::get_binary_diffs().
field | the column being updated | |
path | the path of the value to update | |
new_value | the new value | |
replace | true if we use JSON_REPLACE semantics | |
[in,out] | result | buffer that holds the updated JSON document (is empty if no partial update has been performed on this Json_wrapper so far, or contains the binary representation of the document in this wrapper otherwise) |
[out] | partially_updated | gets set to true if partial update was successful, also if it was a no-op |
[out] | replaced_path | gets set to true if the path was replaced, will be false if this update is a no-op |
false | if the update was successful, or if it was determined that a full update was needed |
true | if an error occurred |
bool Json_wrapper::binary_remove | ( | const Field_json * | field, |
const Json_seekable_path & | path, | ||
String * | result, | ||
bool * | found_path | ||
) |
Remove a path from a binary JSON document.
On successful completion, the updated document will be available in result, and this Json_wrapper will point to result instead of the original binary representation. The modifications that have been applied, will also be collected as binary diffs, which can be retrieved via TABLE::get_binary_diffs().
field | the column being updated | |
path | the path to remove from the document | |
[in,out] | result | buffer that holds the updated JSON document (is empty if no partial update has been performed on this Json_wrapper so far, or contains the binary representation of the document in this wrapper otherwise) |
[out] | found_path | gets set to true if the path is found in the document, false otherwise |
false | if the value was successfully updated |
true | if an error occurred |
Json_dom_ptr Json_wrapper::clone_dom | ( | ) | const |
Get the wrapped contents in DOM form.
Same as to_dom(), except it returns a clone of the original DOM instead of the actual, internal DOM tree.
bool Json_wrapper::coerce_date | ( | MYSQL_TIME * | ltime, |
const char * | msgnam, | ||
enum_coercion_error | cr_error = CE_WARNING , |
||
my_time_flags_t | date_flags_arg = 0 |
||
) | const |
Extract a date from the JSON if possible, coercing if need be.
[in,out] | ltime | a value buffer |
msgnam | to use in error message if conversion failed | |
[in] | cr_error | Whether to raise an error or warning on data truncation |
[in] | date_flags_arg | Flags to use for string -> date conversion |
|
inline |
Shorthand for coerce_decimal(decimal_value, msgnam, CE_WARNING, nullptr).
my_decimal * Json_wrapper::coerce_decimal | ( | my_decimal * | decimal_value, |
const char * | msgnam, | ||
enum_coercion_error | cr_error, | ||
bool * | err | ||
) | const |
Extract a decimal from the JSON if possible, coercing if need be.
[in,out] | decimal_value | a value buffer |
[in] | msgnam | to use in error message if conversion failed |
[in] | cr_error | Whether to raise an error or warning on data truncation |
[out] | err | true <=> error occur during coercion |
|
inline |
Shorthand for coerce_int(msgnam, CE_WARNING, nullptr, nullptr).
longlong Json_wrapper::coerce_int | ( | const char * | msgnam, |
enum_coercion_error | cr_error, | ||
bool * | err, | ||
bool * | unsigned_flag | ||
) | const |
Extract an int (signed or unsigned) from the JSON if possible coercing if need be.
[in] | msgnam | to use in error message if conversion failed |
[in] | cr_error | Whether to raise an error or warning on data truncation |
[out] | err | true <=> error occur during coercion |
[out] | unsigned_flag | Whether the value read from JSON data is unsigned |
|
inline |
Shorthand for coerce_real(msgnam, CE_WARNING, nullptr).
double Json_wrapper::coerce_real | ( | const char * | msgnam, |
enum_coercion_error | cr_error, | ||
bool * | err | ||
) | const |
Extract a real from the JSON if possible, coercing if need be.
[in] | msgnam | to use in error message if conversion failed |
[in] | cr_error | Whether to raise an error or warning on data truncation |
[out] | err | true <=> error occur during coercion |
bool Json_wrapper::coerce_time | ( | MYSQL_TIME * | ltime, |
const char * | msgnam, | ||
enum_coercion_error | cr_error = CE_WARNING |
||
) | const |
Extract a time value from the JSON if possible, coercing if need be.
[in,out] | ltime | a value buffer |
msgnam | to use in error message if conversion failed | |
[in] | cr_error | Whether to raise an error or warning on data truncation |
int Json_wrapper::compare | ( | const Json_wrapper & | other, |
const CHARSET_INFO * | cs = nullptr |
||
) | const |
Compare this JSON value to another JSON value.
[in] | other | the other JSON value |
[in] | cs | if given, this charset will be used in comparison of string values |
-1 | if this JSON value is less than the other JSON value |
0 | if the two JSON values are equal |
1 | if this JSON value is greater than the other JSON value |
void Json_wrapper::dbug_print | ( | const char * | message, |
const JsonDocumentDepthHandler & | depth_handler | ||
) | const |
Print this JSON document to the debug trace.
[in] | message | If given, the JSON document is prefixed with this message. |
|
inline |
A Wrapper is defined to be empty if it is passed a NULL value with the constructor for JSON dom, or if the default constructor is used.
enum_field_types Json_wrapper::field_type | ( | ) | const |
Return the MYSQL type of the opaque value, see type().
Valid for J_OPAQUE. Calling this method if the type is not J_OPAQUE will give undefined results.
|
inline |
Gets the wrapped json_binary::Value object, if this wrapper holds a binary JSON value.
If is_dom() returns true, the result of calling this function is undefined.
bool Json_wrapper::get_boolean | ( | ) | const |
Get a boolean value (a JSON true or false literal).
Valid for J_BOOLEAN. Calling this method if the type is not J_BOOLEAN will give undefined results.
const char * Json_wrapper::get_data | ( | ) | const |
Get a pointer to the data of a JSON string or JSON opaque value.
The data is still owner by the wrapper. The data may not be null terminated, so use in conjunction with get_data_length
. Valid for J_STRING and J_OPAQUE. Calling this method if the type is not one of those will give undefined results.
size_t Json_wrapper::get_data_length | ( | ) | const |
Get the length to the data of a JSON string or JSON opaque value.
Valid for J_STRING and J_OPAQUE. Calling this method if the type is not one of those will give undefined results.
void Json_wrapper::get_datetime | ( | MYSQL_TIME * | t | ) | const |
Get the value of a JSON date/time value.
Valid for J_TIME, J_DATETIME, J_DATE and J_TIMESTAMP. Calling this method if the type is not one of those will give undefined results.
[out] | t | the date/time value |
const char * Json_wrapper::get_datetime_packed | ( | char * | buffer | ) | const |
Get the wrapped datetime value in the packed format.
[in,out] | buffer | a char buffer with space for at least Json_datetime::PACKED_SIZE characters |
bool Json_wrapper::get_decimal_data | ( | my_decimal * | d | ) | const |
Get the MySQL representation of a JSON decimal value.
Valid for J_DECIMAL. Calling this method if the type is not J_DECIMAL will give undefined results.
[out] | d | the decimal value |
|
inline |
Gets a pointer to the wrapped Json_dom object, if this wrapper holds a DOM.
If is_dom() returns false, the result of calling this function is undefined.
double Json_wrapper::get_double | ( | ) | const |
Get the value of a JSON double number.
Valid for J_DOUBLE. Calling this method if the type is not J_DOUBLE will give undefined results.
bool Json_wrapper::get_free_space | ( | size_t * | space | ) | const |
Calculate the amount of unused space inside a JSON binary value.
[out] | space | the amount of unused space, or zero if this is a DOM |
longlong Json_wrapper::get_int | ( | ) | const |
Get the value of a JSON signed integer number.
Valid for J_INT. Calling this method if the type is not J_INT will give undefined results.
ulonglong Json_wrapper::get_uint | ( | ) | const |
Get the value of a JSON unsigned integer number.
Valid for J_UINT. Calling this method if the type is not J_UINT will give undefined results.
|
inline |
Check if the wrapped JSON document is a binary value (a json_binary::Value), and if that binary is pointing to data stored in the given string.
This function can be used to check if overwriting the data in the string might overwrite and corrupt the document contained in this wrapper.
str | a string which contains JSON binary data |
true | if the string contains data that the wrapped document points to from its json_binary::Value representation |
false | otherwise |
|
inline |
Does this wrapper contain a DOM?
true | if the wrapper contains a DOM representation |
false | if the wrapper contains a binary representation |
size_t Json_wrapper::length | ( | ) | const |
Compute the length of a document.
This is the value which would be returned by the JSON_LENGTH() system function. So, this returns
Json_wrapper Json_wrapper::lookup | ( | const MYSQL_LEX_CSTRING & | key | ) | const |
If this wrapper holds a JSON object, get the value corresponding to the member key.
Valid for J_OBJECT. Calling this method if the type is not J_OBJECT will give undefined results.
[in] | key | name for identifying member |
Make a hash key that can be used by sql_executor.cc/unique_hash in order to support SELECT DISTINCT.
[in] | hash_val | An initial hash value. |
size_t Json_wrapper::make_sort_key | ( | uchar * | to, |
size_t | length | ||
) | const |
Make a sort key that can be used by filesort to order JSON values.
[out] | to | a buffer to which the sort key is written |
[in] | length | the length of the sort key |
Key storage format is following:
|<json type>< sort key >| 1 byte / variable length /
JSON is assumed to be non-sql-null and valid (checked by caller). Key length contains full length - the len prefix itself, json type and the sort key. All numeric types are stored as a number, without distinction to double/decimal/int/etc. See make_json_numeric_sort_key()
. Same is done to DATETIME and TIMESTAMP types. For string and opaque types only the prefix that fits into the output buffer is stored. For JSON objects and arrays only their length (number of elements) is stored, this is a limitation of current implementation.
Json_wrapper & Json_wrapper::operator= | ( | const Json_wrapper & | old | ) |
Assignment operator.
Does a deep copy of any owned DOM. If a DOM os not owned (aliased), the copy will also be aliased. Any owned DOM in the left side will be deallocated.
|
noexcept |
Move-assignment operator.
Take over the ownership of the other wrapper's DOM, unless it's aliased. If the other wrapper is aliased, this wrapper becomes an alias too. Any already owned DOM will be deallocated.
old | the wrapper whose contents to take over |
Json_wrapper Json_wrapper::operator[] | ( | size_t | index | ) | const |
If this wrapper holds a JSON array, get an array value by indexing into the array.
Valid for J_ARRAY. Calling this method if the type is not J_ARRAY will give undefined results.
void Json_wrapper::remove_duplicates | ( | const CHARSET_INFO * | cs = nullptr | ) |
Remove duplicate values.
Applicable to JSON arrays only, array will be sorted.
bool Json_wrapper::seek | ( | const Json_seekable_path & | path, |
size_t | legs, | ||
Json_wrapper_vector * | hits, | ||
bool | auto_wrap, | ||
bool | only_need_one | ||
) |
Finds all of the json sub-documents which match the path expression.
Puts the matches on an evolving vector of results. This is a bit inefficient for binary wrappers because you can't build up a binary array incrementally from its cells. Instead, you have to turn each cell into a dom and then add the doms to a dom array.
Calling this if empty() returns true is an error.
Special care must be taken when the path expression contains more than one ellipsis (**) token. That is because multiple paths with ellipses may identify the same value. Consider the following document:
{ "a": { "x" : { "b": { "y": { "b": { "z": { "c": 100 } } } } } } }
The innermost value (the number 100) has the following unique, non-wildcarded address:
$.a.x.b.y.b.z.c
That location is reached by both of the following paths which include the ellipsis token:
$.a.x.b**.c $.a.x.b.y.b**.c
And those addresses both satisfy the following path expression which has two ellipses:
$.a**.b**.c
In this case, we only want to return one instance of $.a.x.b.y.b.z.c
Similarly, special care must be taken if an auto-wrapping array path leg follows an ellipsis. Consider the following document:
{ "a": { "b" : [ 1, 2, 3 ] } }
The first element of the array (the number 1) can be reached with either of these two non-wildcarded addresses, due to array auto-wrapping:
$.a.b[0] $.a.b[0][0]
Both of those addresses match the following path expression, which has an ellipsis followed by an auto-wrapping path leg:
$**[0]
[in] | path | the (possibly wildcarded) address of the sub-documents |
[in] | legs | the number of legs to use from path |
[out] | hits | the result of the search |
[in] | auto_wrap | true of we match a final scalar with search for [0] |
[in] | only_need_one | True if we can stop after finding one match |
false | on success |
true | on error |
|
inline |
Only meaningful iff the wrapper encapsulates a DOM.
Marks the wrapper as not owning the DOM object, i.e. it will not be deallocated in the wrapper's destructor. Useful if one wants a wrapper around a DOM owned by someone else.
void Json_wrapper::sort | ( | const CHARSET_INFO * | cs = nullptr | ) |
Sort contents.
Applicable to JSON arrays only.
Get the wrapped contents in binary value form.
[in] | thd | current session |
[in,out] | str | a string that will be filled with the binary value |
false | on success |
true | on error |
Json_dom * Json_wrapper::to_dom | ( | ) |
Get the wrapped contents in DOM form.
The DOM is (still) owned by the wrapper. If this wrapper originally held a value, it is now converted to hold (and eventually release) the DOM version.
bool Json_wrapper::to_pretty_string | ( | String * | buffer, |
const char * | func_name, | ||
const JsonDocumentDepthHandler & | depth_handler | ||
) | const |
Format the JSON value to an external JSON string in buffer in the format of ISO/IEC 10646.
Add newlines and indentation for readability.
[in,out] | buffer | the buffer that receives the formatted string (the string is appended, so make sure the length is set correctly before calling) |
[in] | func_name | the name of the calling function |
false | on success |
true | on error |
bool Json_wrapper::to_string | ( | String * | buffer, |
bool | json_quoted, | ||
const char * | func_name, | ||
const JsonDocumentDepthHandler & | depth_handler | ||
) | const |
Format the JSON value to an external JSON string in buffer in the format of ISO/IEC 10646.
[in,out] | buffer | the formatted string is appended, so make sure the length is set correctly before calling |
[in] | json_quoted | if the JSON value is a string and json_quoted is false, don't perform quoting on the string. This is only used by JSON_UNQUOTE. |
[in] | func_name | The name of the function that called to_string(). |
enum_json_type Json_wrapper::type | ( | ) | const |
Return the type of the wrapped JSON value.
union { ... } Json_wrapper::@34 |
bool Json_wrapper::m_alias |
If true, don't deallocate m_dom_value in destructor.
struct { ... } Json_wrapper::m_dom |
The DOM representation, only used if m_is_dom is true.
|
private |
Wraps a DOM iff true.
Json_dom* Json_wrapper::m_value |
json_binary::Value Json_wrapper::m_value |
The binary representation, only used if m_is_dom is false.