MySQL 9.1.0
Source Code Documentation
item_json_func.cc File Reference
#include "sql/item_json_func.h"
#include <assert.h>
#include <algorithm>
#include <cstring>
#include <limits>
#include <memory>
#include <new>
#include <string>
#include <utility>
#include <vector>
#include "decimal.h"
#include "field_types.h"
#include "lex_string.h"
#include "my_alloc.h"
#include "my_dbug.h"
#include "my_sys.h"
#include "mysql/mysql_lex_string.h"
#include "mysql/strings/m_ctype.h"
#include "mysqld_error.h"
#include "prealloced_array.h"
#include "scope_guard.h"
#include "sql-common/json_diff.h"
#include "sql-common/json_dom.h"
#include "sql-common/json_path.h"
#include "sql-common/json_schema.h"
#include "sql-common/json_syntax_check.h"
#include "sql-common/my_decimal.h"
#include "sql/current_thd.h"
#include "sql/debug_sync.h"
#include "sql/error_handler.h"
#include "sql/field.h"
#include "sql/field_common_properties.h"
#include "sql/item_cmpfunc.h"
#include "sql/item_create.h"
#include "sql/parser_yystype.h"
#include "sql/psi_memory_key.h"
#include "sql/sql_class.h"
#include "sql/sql_const.h"
#include "sql/sql_error.h"
#include "sql/sql_exception_handler.h"
#include "sql/sql_time.h"
#include "sql/system_variables.h"
#include "sql/table.h"
#include "sql/table_function.h"
#include "sql/thd_raii.h"
#include "sql/thr_malloc.h"
#include "sql_string.h"
#include "string_with_len.h"
#include "template_utils.h"

Classes

struct  Item_func_json_value::Default_value
 

Typedefs

typedef Prealloced_array< size_t, 16 > Sorted_index_array
 
typedef Prealloced_array< std::string, 16 > String_set
 

Functions

bool ensure_utf8mb4 (const String &val, String *buf, const char **resptr, size_t *reslength, bool require_string)
 Helper routines. More...
 
bool parse_json (const String &res, Json_dom_ptr *dom, bool require_str_or_json, const JsonParseErrorHandler &error_handler, const JsonErrorHandler &depth_handler)
 Parse a JSON dom out of an argument to a JSON function. More...
 
enum_json_diff_status apply_json_diffs (Field_json *field, const Json_diff_vector *diffs)
 Apply a sequence of JSON diffs to the value stored in a JSON column. More...
 
static enum_field_types get_real_blob_type (const Field *arg)
 Get correct blob type of given Field. More...
 
static enum_field_types get_real_blob_type (const Item *arg)
 Get correct blob type of given Item. More...
 
static enum_field_types get_normalized_field_type (const Item *arg)
 Get the field type of an item. More...
 
bool get_json_object_member_name (const THD *thd, Item *arg_item, String *value, String *utf8_res, const char **safep, size_t *safe_length)
 Gets a JSON object member name from an Item. More...
 
static bool is_convertible_to_json (const Item *item)
 A helper method that checks whether or not the given argument can be converted to JSON. More...
 
static bool check_convertible_to_json (const Item *item, int argument_number, const char *function_name)
 Checks if an Item is of a type that is convertible to JSON. More...
 
static bool json_is_valid (Item **args, uint arg_idx, String *value, const char *func_name, Json_dom_ptr *dom, bool require_str_or_json, bool *valid)
 Helper method for Item_func_json_* methods. More...
 
bool parse_path (const String &path_value, bool forbid_wildcards, Json_path *json_path)
 A helper function that uses the above one as workhorse. More...
 
static enum_one_or_all_type parse_one_or_all (const String *candidate, const char *func_name)
 Parse a oneOrAll argument. More...
 
static enum_one_or_all_type parse_and_cache_ooa (const THD *thd, Item *arg, enum_one_or_all_type *cached_ooa, const char *func_name)
 Parse and cache a (possibly constant) oneOrAll argument. More...
 
static bool evaluate_constant_json_schema (THD *thd, Item *json_schema, Json_schema_validator *cached_schema_validator, Item **ref)
 
static bool do_json_schema_validation (const THD *thd, Item *json_schema, Item *json_document, const char *func_name, const Json_schema_validator &cached_schema_validator, bool *null_value, bool *validation_result, Json_schema_validation_report *validation_report)
 
bool json_value (Item *arg, Json_wrapper *result, bool *has_value)
 Return the JSON value of the argument in a wrapper. More...
 
bool get_json_wrapper (Item **args, uint arg_idx, String *str, const char *func_name, Json_wrapper *wrapper)
 Return the JSON value of the argument in a wrapper. More...
 
static Stringval_string_from_json (Item_func *item, String *buffer)
 
static bool get_date_from_json (Item_func *item, MYSQL_TIME *ltime, my_time_flags_t)
 
static bool get_time_from_json (Item_func *item, MYSQL_TIME *ltime)
 
longlong val_int_from_json (Item_func *item)
 
static double val_real_from_json (Item_func *item)
 
static my_decimalval_decimal_from_json (Item_func *item, my_decimal *decimal_value)
 
template<typename T , typename... Args>
static bool create_scalar (Json_scalar_holder *scalar, Json_dom_ptr *dom, Args &&...args)
 Create a new Json_scalar object, either in memory owned by a Json_scalar_holder object or on the heap. More...
 
bool sql_scalar_to_json (Item *arg, const char *calling_function, String *value, String *tmp, Json_wrapper *wr, Json_scalar_holder *scalar, bool scalar_string)
 Get a JSON value from an SQL scalar value. More...
 
bool get_json_atom_wrapper (Item **args, uint arg_idx, const char *calling_function, String *value, String *tmp, Json_wrapper *wr, Json_scalar_holder *scalar, bool accept_string)
 Convert Json values or MySQL values to JSON. More...
 
bool get_atom_null_as_null (Item **args, uint arg_idx, const char *calling_function, String *value, String *tmp, Json_wrapper *wr)
 Convert JSON values or MySQL values to JSON. More...
 
static bool possible_root_path (const Json_path_iterator &begin, const Json_path_iterator &end)
 Is this a path that could possibly return the root node of a JSON document? More...
 
static void disable_logical_diffs (const Field_json *field)
 
static void disable_binary_diffs (const Field_json *field)
 
static bool find_matches (const Json_wrapper &wrapper, String *path, Json_dom_vector *matches, String_set *duplicates, bool one_match, Item *like_node, Item_string *source_string)
 Recursive function to find the string values, nested inside a json document, which satisfy the LIKE condition. More...
 
static void set_data_type_from_cast_type (Item *item, Cast_target cast_type, unsigned length, unsigned decimals, const CHARSET_INFO *charset)
 Sets the data type of an Item_func_array_cast or Item_func_json_value based on the Cast_type. More...
 
static void print_cast_type (Cast_target cast_type, const Item *item, String *str)
 Prints the target type of a cast operation (either CAST or JSON_VALUE). More...
 
static enum Item_result json_cast_result_type (Cast_target cast_type)
 
static enum_field_types data_type_to_real_type (enum_field_types data_type)
 Converts the "data type" used by Item to a "real type" used by Field. More...
 
static bool can_store_json_value_unencoded (const Field *field_to_store_in, const Json_wrapper *json_data)
 Check if a JSON value is a JSON OPAQUE, and if it can be printed in the field as a non base64 value. More...
 
bool save_json_to_field (THD *thd, Field *field, const Json_wrapper *w, bool no_error)
 Save JSON to a given field. More...
 
static bool decimal_within_range (const Item *item, const my_decimal *decimal)
 Checks if a decimal value is within the range of the data type of an Item. More...
 
static bool same_response_type (Json_on_response_type type1, Json_on_response_type type2)
 Checks if two Json_on_response_type values represent the same response. More...
 
static bool handle_json_value_conversion_error (Json_on_response_type on_error, const char *type, Item_func_json_value *item)
 Handles conversion errors for JSON_VALUE according to the ON ERROR clause. More...
 

Typedef Documentation

◆ Sorted_index_array

typedef Prealloced_array<size_t, 16> Sorted_index_array

◆ String_set

typedef Prealloced_array<std::string, 16> String_set

Function Documentation

◆ apply_json_diffs()

enum_json_diff_status apply_json_diffs ( Field_json field,
const Json_diff_vector diffs 
)

Apply a sequence of JSON diffs to the value stored in a JSON column.

Parameters
fieldthe column to update
diffsthe diffs to apply
Returns
an enum_json_diff_status value that tells if the diffs were applied successfully

◆ can_store_json_value_unencoded()

static bool can_store_json_value_unencoded ( const Field field_to_store_in,
const Json_wrapper json_data 
)
static

Check if a JSON value is a JSON OPAQUE, and if it can be printed in the field as a non base64 value.

This is currently used by JSON_TABLE to see if we can print the JSON value in a field without having to encode it in base64.

Parameters
field_to_store_inThe field we want to store the JSON value in
json_dataThe JSON value we want to store.
Returns
true The JSON value can be stored without encoding it in base64 false The JSON value can not be stored without encoding it, or it is not a JSON OPAQUE value.

◆ check_convertible_to_json()

static bool check_convertible_to_json ( const Item item,
int  argument_number,
const char *  function_name 
)
static

Checks if an Item is of a type that is convertible to JSON.

An error is raised if it is not convertible.

◆ create_scalar()

template<typename T , typename... Args>
static bool create_scalar ( Json_scalar_holder scalar,
Json_dom_ptr dom,
Args &&...  args 
)
static

Create a new Json_scalar object, either in memory owned by a Json_scalar_holder object or on the heap.

Parameters
[in,out]scalarthe Json_scalar_holder in which to create the new Json_scalar, or nullptr if it should be created on the heap
[in,out]dompointer to the Json_scalar if it's created on the heap
[in]argsthe arguments to pass to T's constructor
Template Parameters
Tthe type of object to create; a subclass of Json_scalar
Argstype of the arguments to pass to T's constructor
Return values
falseif successful
trueif memory could not be allocated

◆ data_type_to_real_type()

static enum_field_types data_type_to_real_type ( enum_field_types  data_type)
static

Converts the "data type" used by Item to a "real type" used by Field.

◆ decimal_within_range()

static bool decimal_within_range ( const Item item,
const my_decimal decimal 
)
static

Checks if a decimal value is within the range of the data type of an Item.

It is considered within range if it can be converted to the data type without losing any leading significant digits.

◆ disable_binary_diffs()

static void disable_binary_diffs ( const Field_json field)
static

◆ disable_logical_diffs()

static void disable_logical_diffs ( const Field_json field)
static

◆ do_json_schema_validation()

static bool do_json_schema_validation ( const THD thd,
Item json_schema,
Item json_document,
const char *  func_name,
const Json_schema_validator cached_schema_validator,
bool *  null_value,
bool *  validation_result,
Json_schema_validation_report validation_report 
)
static

◆ ensure_utf8mb4()

bool ensure_utf8mb4 ( const String val,
String buf,
const char **  resptr,
size_t *  reslength,
bool  require_string 
)

Helper routines.

Check a non-empty val for character set.

◆ evaluate_constant_json_schema()

static bool evaluate_constant_json_schema ( THD thd,
Item json_schema,
Json_schema_validator cached_schema_validator,
Item **  ref 
)
static

◆ find_matches()

static bool find_matches ( const Json_wrapper wrapper,
String path,
Json_dom_vector matches,
String_set duplicates,
bool  one_match,
Item like_node,
Item_string source_string 
)
static

Recursive function to find the string values, nested inside a json document, which satisfy the LIKE condition.

As matches are found, their path locations are added to an evolving vector of matches.

Parameters
[in]wrapperA subdocument of the original document.
[in]pathThe path location of the subdocument
[in,out]matchesThe evolving vector of matches.
[in,out]duplicatesSorted set of paths found already, which is used to avoid inserting duplicates into matches.
[in]one_matchIf true, then terminate search after first match.
[in]like_nodeThe LIKE node that's evaluated on the string values.
[in]source_stringThe input string item of the LIKE node.
Return values
falseon success
trueon failure

◆ get_atom_null_as_null()

bool get_atom_null_as_null ( Item **  args,
uint  arg_idx,
const char *  calling_function,
String value,
String tmp,
Json_wrapper wr 
)

Convert JSON values or MySQL values to JSON.

Converts SQL NULL to the JSON null literal.

Parameters
[in]argsarguments to function
[in]arg_idxthe index of the argument to process
[in]calling_functionname of the calling function
[in,out]valueworking area (if the returned Json_wrapper points to a binary value rather than a DOM, this string will end up holding the binary representation, and it must stay alive until the wrapper is destroyed or converted from binary to DOM)
[in,out]tmptemporary scratch space for converting strings to the correct charset; only used if accept_string is true and conversion is needed
[in,out]wrthe result wrapper
Returns
false if we found a value or NULL, true otherwise

◆ get_date_from_json()

static bool get_date_from_json ( Item_func item,
MYSQL_TIME ltime,
my_time_flags_t   
)
static

◆ get_json_atom_wrapper()

bool get_json_atom_wrapper ( Item **  args,
uint  arg_idx,
const char *  calling_function,
String value,
String tmp,
Json_wrapper wr,
Json_scalar_holder scalar,
bool  accept_string 
)

Convert Json values or MySQL values to JSON.

Parameters
[in]argsarguments to function
[in]arg_idxthe index of the argument to process
[in]calling_functionname of the calling function
[in,out]valueworking area (if the returned Json_wrapper points to a binary value rather than a DOM, this string will end up holding the binary representation, and it must stay alive until the wrapper is destroyed or converted from binary to DOM)
[in,out]tmptemporary scratch space for converting strings to the correct charset; only used if accept_string is true and conversion is needed
[in,out]wrthe result wrapper
[in,out]scalarpointer to pre-allocated memory that can be borrowed by the result wrapper if the result is a scalar. If the pointer is NULL, memory for a scalar result will be allocated on the heap.
[in]accept_stringif true, accept MySQL strings as JSON strings by converting them to UTF8, else emit an error
Returns
false if we found a value or NULL, true otherwise

◆ get_json_object_member_name()

bool get_json_object_member_name ( const THD thd,
Item arg_item,
String value,
String utf8_res,
const char **  safep,
size_t *  safe_length 
)

Gets a JSON object member name from an Item.

An error is raised if the Item evaluates to NULL, or if it cannot be converted to a utf8mb4 string.

Parameters
[in]thdTHD handle
[in]arg_itemAn argument Item
[out]valueWhere to materialize the arg_item's string value
[out]utf8_resBuffer for use by ensure_utf8mb4.
[out]safepString pointer after any relevant conversion
[out]safe_lengthCorresponding string length
Returns
true if the Item is not a utf8mb4 string

◆ get_json_wrapper()

bool get_json_wrapper ( Item **  args,
uint  arg_idx,
String str,
const char *  func_name,
Json_wrapper wrapper 
)

Return the JSON value of the argument in a wrapper.

Abstracts whether the value comes from a field or a function or a valid JSON text.

Parameters
[in]argsthe arguments
[in]arg_idxthe argument index
[out]strthe string buffer
[in]func_namethe name of the function we are executing
[out]wrapperthe JSON value wrapper
Returns
false if we found a value or NULL, true if not.

◆ get_normalized_field_type()

static enum_field_types get_normalized_field_type ( const Item arg)
static

Get the field type of an item.

This function returns the same value as arg->data_type() in most cases, but in some cases it may return another field type in order to ensure that the item gets handled the same way as items of a different type.

◆ get_real_blob_type() [1/2]

static enum_field_types get_real_blob_type ( const Field arg)
static

Get correct blob type of given Field.

A helper function for get_normalized_field_type().

Parameters
argthe field to get blob type of
Returns
correct blob type

◆ get_real_blob_type() [2/2]

static enum_field_types get_real_blob_type ( const Item arg)
static

Get correct blob type of given Item.

A helper function for get_normalized_field_type().

Parameters
argthe item to get blob type of
Returns
correct blob type

◆ get_time_from_json()

static bool get_time_from_json ( Item_func item,
MYSQL_TIME ltime 
)
static

◆ handle_json_value_conversion_error()

static bool handle_json_value_conversion_error ( Json_on_response_type  on_error,
const char *  type,
Item_func_json_value item 
)
static

Handles conversion errors for JSON_VALUE according to the ON ERROR clause.

Called when the conversion of the extracted JSON value cannot be converted to the target type without truncation or data loss.

If ERROR ON ERROR is specified, an error is raised, and true is returned.

If NULL ON ERROR is specified (explicitly or implicitly), the item's null_value is set to true, and false is returned.

If DEFAULT ... ON ERROR is specified, the item's null_value is set to false, and false is returned. It is up to the caller to return the correct default value.

Parameters
on_errorthe type of response to give to the error
typethe data type returned by the JSON_VALUE expression
[in,out]itemthe Item representing the JSON_VALUE expression
Return values
truefor ERROR ON ERROR (my_error() is called before returning)
falseif DEFAULT .. ON ERROR or NULL ON ERROR was given

◆ is_convertible_to_json()

static bool is_convertible_to_json ( const Item item)
static

A helper method that checks whether or not the given argument can be converted to JSON.

The function only checks the type of the given item, and doesn't do any parsing or further checking of the item.

Parameters
itemThe item to be checked
Return values
trueThe item is possibly convertible to JSON
falseThe item is not convertible to JSON

◆ json_cast_result_type()

static enum Item_result json_cast_result_type ( Cast_target  cast_type)
static

◆ json_is_valid()

static bool json_is_valid ( Item **  args,
uint  arg_idx,
String value,
const char *  func_name,
Json_dom_ptr dom,
bool  require_str_or_json,
bool *  valid 
)
static

Helper method for Item_func_json_* methods.

Check if a JSON item or JSON text is valid and, for the latter, optionally construct a DOM tree (i.e. only if valid).

Parameters
[in]argsItem_func::args alias
[in]arg_idxIndex (0-based) of argument into the args array
[out]valueAlias for
Item_func_json_*::m_value
[in]func_nameName of the user-invoked JSON_ function
[in,out]domIf non-null, we want any text parsed DOM returned at the location pointed to
[in]require_str_or_jsonIf true, generate an error if other types used as input
[out]validtrue if a valid JSON value was found (or NULL), else false
Returns
true iff syntax error and dom != null, else false

◆ json_value()

bool json_value ( Item arg,
Json_wrapper result,
bool *  has_value 
)

Return the JSON value of the argument in a wrapper.

Handles arguments with type JSON, including array objects (which do not report type JSON but rather the type of individual elements).

Does not handle literals. See also get_json_wrapper.

Parameters
[in]argthe argument
[in,out]resultthe JSON value wrapper
[out]has_valuetrue if argument was handled, false otherwise undefined when error

◆ parse_and_cache_ooa()

static enum_one_or_all_type parse_and_cache_ooa ( const THD thd,
Item arg,
enum_one_or_all_type cached_ooa,
const char *  func_name 
)
static

Parse and cache a (possibly constant) oneOrAll argument.

Parameters
[in]thdTHD handle.
[in]argThe oneOrAll arg passed to the JSON function.
[in]cached_ooaPrevious result of parsing this arg.
[in]func_nameThe name of the calling JSON function.
Returns
ooa_one, ooa_all, ooa_null or ooa_error, based on the match

◆ parse_json()

bool parse_json ( const String res,
Json_dom_ptr dom,
bool  require_str_or_json,
const JsonParseErrorHandler error_handler,
const JsonErrorHandler depth_handler 
)

Parse a JSON dom out of an argument to a JSON function.

Parameters
[in]resPointer to string value of arg.
[in,out]domIf non-null, we want any text parsed DOM returned at the location pointed to
[in]require_str_or_jsonIf true, generate an error if other types used as input
[in]error_handlerPointer to a function that should handle reporting of parsing error.
[in]depth_handlerPointer to a function that should handle error occurred when depth is exceeded.
Returns
false if the arg parsed as valid JSON, true otherwise

◆ parse_one_or_all()

static enum_one_or_all_type parse_one_or_all ( const String candidate,
const char *  func_name 
)
static

Parse a oneOrAll argument.

Parameters
[in]candidateThe string to compare to "one" or "all"
[in]func_nameThe name of the calling function
Returns
ooa_one, ooa_all, or ooa_error, based on the match

◆ parse_path()

bool parse_path ( const String path_value,
bool  forbid_wildcards,
Json_path json_path 
)

A helper function that uses the above one as workhorse.

Entry point for for JSON_TABLE (Table_function_json class) and Json_path_cache. Raises an error if the path expression is syntactically incorrect. Raises an error if the path expression contains wildcard tokens but is not supposed to. Otherwise updates the supplied Json_path object with the parsed path.

Parameters
[in]path_valueA String to be interpreted as a path.
[in]forbid_wildcardsTrue if the path shouldn't contain * or **
[out]json_pathThe object that will hold the parsed path
Returns
false on success (valid path or NULL), true on error

◆ possible_root_path()

static bool possible_root_path ( const Json_path_iterator begin,
const Json_path_iterator end 
)
static

Is this a path that could possibly return the root node of a JSON document?

A path that returns the root node must be on one of the following forms:

  • the root ('$'), or
  • a sequence of array cells at index 0 or last that any non-array element at the top level could have been autowrapped to, i.e. '$[0]' or '$[0][0]...[0]'.
See also
Json_path_leg::is_autowrap
Parameters
beginthe beginning of the path
endthe end of the path (exclusive)
Returns
true if the path may match the root, false otherwise

◆ print_cast_type()

static void print_cast_type ( Cast_target  cast_type,
const Item item,
String str 
)
static

Prints the target type of a cast operation (either CAST or JSON_VALUE).

Parameters
cast_typethe cast type
itemthe Item in which the cast operation is performed
[out]strthe string to print to

◆ same_response_type()

static bool same_response_type ( Json_on_response_type  type1,
Json_on_response_type  type2 
)
static

Checks if two Json_on_response_type values represent the same response.

Implicit responses are equal to NULL ON EMPTY/ERROR.

◆ save_json_to_field()

bool save_json_to_field ( THD thd,
Field field,
const Json_wrapper w,
bool  no_error 
)

Save JSON to a given field.

Value is saved in type-aware manner. Into a JSON-typed column any JSON data could be saved. Into an SQL scalar field only a scalar could be saved. If data being saved isn't scalar or can't be coerced to the target type, an error is returned.

Parameters
thdThread handler
fieldField to save data to
wJSON data to save
no_errorIf true, don't raise an error when the value cannot be converted to the target type
Returns
false ok true coercion error occur

◆ set_data_type_from_cast_type()

static void set_data_type_from_cast_type ( Item item,
Cast_target  cast_type,
unsigned  length,
unsigned  decimals,
const CHARSET_INFO charset 
)
static

Sets the data type of an Item_func_array_cast or Item_func_json_value based on the Cast_type.

Parameters
itemthe Item whose data type to set
cast_typethe type of cast
lengththe declared length of the target type
decimalsthe declared precision of the target type
charsetthe character set of the target type (nullptr if not specified)

◆ sql_scalar_to_json()

bool sql_scalar_to_json ( Item arg,
const char *  calling_function,
String value,
String tmp,
Json_wrapper wr,
Json_scalar_holder scalar,
bool  scalar_string 
)

Get a JSON value from an SQL scalar value.

Parameters
[in]argthe function argument
[in]calling_functionthe name of the calling function
[in,out]valuea scratch area
[in,out]tmptemporary scratch space for converting strings to the correct charset; only used if accept_string is true and conversion is needed
[out]wrthe retrieved JSON value
[in,out]scalarpointer to pre-allocated memory that can be borrowed by the result wrapper to hold the scalar result. If the pointer is NULL, memory will be allocated on the heap.
[in]scalar_stringif true, interpret SQL strings as scalar JSON strings. if false, interpret SQL strings as JSON objects. If conversion fails, return the string as a scalar JSON string instead.
Returns
false if we could get a value or NULL, otherwise true

Scalar processing is irrelevant. Geometry types are converted to JSON objects.

◆ val_decimal_from_json()

static my_decimal * val_decimal_from_json ( Item_func item,
my_decimal decimal_value 
)
static

◆ val_int_from_json()

longlong val_int_from_json ( Item_func item)

◆ val_real_from_json()

static double val_real_from_json ( Item_func item)
static

◆ val_string_from_json()

static String * val_string_from_json ( Item_func item,
String buffer 
)
static