MDEV-19888 Add abstract class Item_json_func
This commit is contained in:
parent
cff7cf15d7
commit
323a87b591
@ -439,7 +439,17 @@ bool Item_func_json_value::fix_length_and_dec()
|
|||||||
{
|
{
|
||||||
collation.set(args[0]->collation);
|
collation.set(args[0]->collation);
|
||||||
max_length= args[0]->max_length;
|
max_length= args[0]->max_length;
|
||||||
path.set_constant_flag(args[1]->const_item());
|
set_constant_flag(args[1]->const_item());
|
||||||
|
maybe_null= 1;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Item_func_json_query::fix_length_and_dec()
|
||||||
|
{
|
||||||
|
collation.set(args[0]->collation);
|
||||||
|
max_length= args[0]->max_length;
|
||||||
|
set_constant_flag(args[1]->const_item());
|
||||||
maybe_null= 1;
|
maybe_null= 1;
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
@ -449,88 +459,75 @@ bool Item_func_json_value::fix_length_and_dec()
|
|||||||
Returns NULL, not an error if the found value
|
Returns NULL, not an error if the found value
|
||||||
is not a scalar.
|
is not a scalar.
|
||||||
*/
|
*/
|
||||||
String *Item_func_json_value::val_str(String *str)
|
bool Json_path_extractor::extract(String *str, Item *item_js, Item *item_jp,
|
||||||
|
CHARSET_INFO *cs)
|
||||||
{
|
{
|
||||||
json_engine_t je;
|
String *js= item_js->val_json(&tmp_js);
|
||||||
String *js= args[0]->val_json(&tmp_js);
|
|
||||||
int error= 0;
|
int error= 0;
|
||||||
uint array_counters[JSON_DEPTH_LIMIT];
|
uint array_counters[JSON_DEPTH_LIMIT];
|
||||||
|
|
||||||
if (!path.parsed)
|
if (!parsed)
|
||||||
{
|
{
|
||||||
String *s_p= args[1]->val_str(&tmp_path);
|
String *s_p= item_jp->val_str(&tmp_path);
|
||||||
if (s_p &&
|
if (s_p &&
|
||||||
json_path_setup(&path.p, s_p->charset(), (const uchar *) s_p->ptr(),
|
json_path_setup(&p, s_p->charset(), (const uchar *) s_p->ptr(),
|
||||||
(const uchar *) s_p->ptr() + s_p->length()))
|
(const uchar *) s_p->ptr() + s_p->length()))
|
||||||
goto err_return;
|
return true;
|
||||||
path.parsed= path.constant;
|
parsed= constant;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((null_value= args[0]->null_value || args[1]->null_value))
|
if (item_js->null_value || item_jp->null_value)
|
||||||
return NULL;
|
return true;
|
||||||
|
|
||||||
json_scan_start(&je, js->charset(),(const uchar *) js->ptr(),
|
|
||||||
(const uchar *) js->ptr() + js->length());
|
|
||||||
|
|
||||||
|
Json_engine_scan je(*js);
|
||||||
str->length(0);
|
str->length(0);
|
||||||
str->set_charset(collation.collation);
|
str->set_charset(cs);
|
||||||
|
|
||||||
path.cur_step= path.p.steps;
|
cur_step= p.steps;
|
||||||
continue_search:
|
continue_search:
|
||||||
if (json_find_path(&je, &path.p, &path.cur_step, array_counters))
|
if (json_find_path(&je, &p, &cur_step, array_counters))
|
||||||
{
|
return true;
|
||||||
if (je.s.error)
|
|
||||||
goto err_return;
|
|
||||||
|
|
||||||
null_value= 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (json_read_value(&je))
|
if (json_read_value(&je))
|
||||||
goto err_return;
|
return true;
|
||||||
|
|
||||||
if (unlikely(check_and_get_value(&je, str, &error)))
|
if (unlikely(check_and_get_value(&je, str, &error)))
|
||||||
{
|
{
|
||||||
if (error)
|
if (error)
|
||||||
goto err_return;
|
return true;
|
||||||
goto continue_search;
|
goto continue_search;
|
||||||
}
|
}
|
||||||
|
|
||||||
return str;
|
return false;
|
||||||
|
|
||||||
err_return:
|
|
||||||
null_value= 1;
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool Item_func_json_value::check_and_get_value(json_engine_t *je, String *res,
|
bool Json_engine_scan::check_and_get_value_scalar(String *res, int *error)
|
||||||
int *error)
|
|
||||||
{
|
{
|
||||||
CHARSET_INFO *json_cs;
|
CHARSET_INFO *json_cs;
|
||||||
const uchar *js;
|
const uchar *js;
|
||||||
uint js_len;
|
uint js_len;
|
||||||
|
|
||||||
if (!json_value_scalar(je))
|
if (!json_value_scalar(this))
|
||||||
{
|
{
|
||||||
/* We only look for scalar values! */
|
/* We only look for scalar values! */
|
||||||
if (json_skip_level(je) || json_scan_next(je))
|
if (json_skip_level(this) || json_scan_next(this))
|
||||||
*error= 1;
|
*error= 1;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (je->value_type == JSON_VALUE_TRUE ||
|
if (value_type == JSON_VALUE_TRUE ||
|
||||||
je->value_type == JSON_VALUE_FALSE)
|
value_type == JSON_VALUE_FALSE)
|
||||||
{
|
{
|
||||||
json_cs= &my_charset_utf8mb4_bin;
|
json_cs= &my_charset_utf8mb4_bin;
|
||||||
js= (const uchar *) ((je->value_type == JSON_VALUE_TRUE) ? "1" : "0");
|
js= (const uchar *) ((value_type == JSON_VALUE_TRUE) ? "1" : "0");
|
||||||
js_len= 1;
|
js_len= 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
json_cs= je->s.cs;
|
json_cs= s.cs;
|
||||||
js= je->value;
|
js= value;
|
||||||
js_len= je->value_len;
|
js_len= value_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -538,26 +535,24 @@ bool Item_func_json_value::check_and_get_value(json_engine_t *je, String *res,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool Item_func_json_query::check_and_get_value(json_engine_t *je, String *res,
|
bool Json_engine_scan::check_and_get_value_complex(String *res, int *error)
|
||||||
int *error)
|
|
||||||
{
|
{
|
||||||
const uchar *value;
|
if (json_value_scalar(this))
|
||||||
if (json_value_scalar(je))
|
|
||||||
{
|
{
|
||||||
/* We skip scalar values. */
|
/* We skip scalar values. */
|
||||||
if (json_scan_next(je))
|
if (json_scan_next(this))
|
||||||
*error= 1;
|
*error= 1;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
value= je->value;
|
const uchar *tmp_value= value;
|
||||||
if (json_skip_level(je))
|
if (json_skip_level(this))
|
||||||
{
|
{
|
||||||
*error= 1;
|
*error= 1;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
res->set((const char *) je->value, (uint32)(je->s.c_str - value), je->s.cs);
|
res->set((const char *) value, (uint32)(s.c_str - tmp_value), s.cs);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,6 +40,33 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class Json_engine_scan: public json_engine_t
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Json_engine_scan(CHARSET_INFO *i_cs, const uchar *str, const uchar *end)
|
||||||
|
{
|
||||||
|
json_scan_start(this, i_cs, str, end);
|
||||||
|
}
|
||||||
|
Json_engine_scan(const String &str)
|
||||||
|
:Json_engine_scan(str.charset(), (const uchar *) str.ptr(),
|
||||||
|
(const uchar *) str.end())
|
||||||
|
{ }
|
||||||
|
bool check_and_get_value_scalar(String *res, int *error);
|
||||||
|
bool check_and_get_value_complex(String *res, int *error);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class Json_path_extractor: public json_path_with_flags
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
String tmp_js, tmp_path;
|
||||||
|
virtual ~Json_path_extractor() { }
|
||||||
|
virtual bool check_and_get_value(Json_engine_scan *je,
|
||||||
|
String *to, int *error)=0;
|
||||||
|
bool extract(String *to, Item *js, Item *jp, CHARSET_INFO *cs);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
class Item_func_json_valid: public Item_bool_func
|
class Item_func_json_valid: public Item_bool_func
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
@ -78,32 +105,65 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class Item_func_json_value: public Item_str_func
|
class Item_json_func: public Item_str_func
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Item_json_func(THD *thd)
|
||||||
|
:Item_str_func(thd) { }
|
||||||
|
Item_json_func(THD *thd, Item *a)
|
||||||
|
:Item_str_func(thd, a) { }
|
||||||
|
Item_json_func(THD *thd, Item *a, Item *b)
|
||||||
|
:Item_str_func(thd, a, b) { }
|
||||||
|
Item_json_func(THD *thd, List<Item> &list)
|
||||||
|
:Item_str_func(thd, list) { }
|
||||||
|
bool is_json_type() { return true; }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class Item_func_json_value: public Item_str_func,
|
||||||
|
public Json_path_extractor
|
||||||
{
|
{
|
||||||
protected:
|
|
||||||
json_path_with_flags path;
|
|
||||||
String tmp_js, tmp_path;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Item_func_json_value(THD *thd, Item *js, Item *i_path):
|
Item_func_json_value(THD *thd, Item *js, Item *i_path):
|
||||||
Item_str_func(thd, js, i_path) {}
|
Item_str_func(thd, js, i_path) {}
|
||||||
const char *func_name() const { return "json_value"; }
|
const char *func_name() const { return "json_value"; }
|
||||||
bool fix_length_and_dec();
|
bool fix_length_and_dec();
|
||||||
String *val_str(String *);
|
String *val_str(String *to)
|
||||||
virtual bool check_and_get_value(json_engine_t *je, String *res, int *error);
|
{
|
||||||
|
null_value= Json_path_extractor::extract(to, args[0], args[1],
|
||||||
|
collation.collation);
|
||||||
|
return null_value ? NULL : to;
|
||||||
|
}
|
||||||
|
bool check_and_get_value(Json_engine_scan *je,
|
||||||
|
String *res, int *error) override
|
||||||
|
{
|
||||||
|
return je->check_and_get_value_scalar(res, error);
|
||||||
|
}
|
||||||
Item *get_copy(THD *thd)
|
Item *get_copy(THD *thd)
|
||||||
{ return get_item_copy<Item_func_json_value>(thd, this); }
|
{ return get_item_copy<Item_func_json_value>(thd, this); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class Item_func_json_query: public Item_func_json_value
|
class Item_func_json_query: public Item_json_func,
|
||||||
|
public Json_path_extractor
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Item_func_json_query(THD *thd, Item *js, Item *i_path):
|
Item_func_json_query(THD *thd, Item *js, Item *i_path):
|
||||||
Item_func_json_value(thd, js, i_path) {}
|
Item_json_func(thd, js, i_path) {}
|
||||||
bool is_json_type() { return true; }
|
|
||||||
const char *func_name() const { return "json_query"; }
|
const char *func_name() const { return "json_query"; }
|
||||||
bool check_and_get_value(json_engine_t *je, String *res, int *error);
|
bool fix_length_and_dec();
|
||||||
|
String *val_str(String *to)
|
||||||
|
{
|
||||||
|
null_value= Json_path_extractor::extract(to, args[0], args[1],
|
||||||
|
collation.collation);
|
||||||
|
return null_value ? NULL : to;
|
||||||
|
}
|
||||||
|
bool check_and_get_value(Json_engine_scan *je,
|
||||||
|
String *res, int *error) override
|
||||||
|
{
|
||||||
|
return je->check_and_get_value_complex(res, error);
|
||||||
|
}
|
||||||
Item *get_copy(THD *thd)
|
Item *get_copy(THD *thd)
|
||||||
{ return get_item_copy<Item_func_json_query>(thd, this); }
|
{ return get_item_copy<Item_func_json_query>(thd, this); }
|
||||||
};
|
};
|
||||||
@ -139,18 +199,17 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class Item_json_str_multipath: public Item_str_func
|
class Item_json_str_multipath: public Item_json_func
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
json_path_with_flags *paths;
|
json_path_with_flags *paths;
|
||||||
String *tmp_paths;
|
String *tmp_paths;
|
||||||
public:
|
public:
|
||||||
Item_json_str_multipath(THD *thd, List<Item> &list):
|
Item_json_str_multipath(THD *thd, List<Item> &list):
|
||||||
Item_str_func(thd, list), tmp_paths(0) {}
|
Item_json_func(thd, list), tmp_paths(0) {}
|
||||||
bool fix_fields(THD *thd, Item **ref);
|
bool fix_fields(THD *thd, Item **ref);
|
||||||
void cleanup();
|
void cleanup();
|
||||||
virtual uint get_n_paths() const = 0;
|
virtual uint get_n_paths() const = 0;
|
||||||
bool is_json_type() { return true; }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -217,18 +276,17 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class Item_func_json_array: public Item_str_func
|
class Item_func_json_array: public Item_json_func
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
String tmp_val;
|
String tmp_val;
|
||||||
ulong result_limit;
|
ulong result_limit;
|
||||||
public:
|
public:
|
||||||
Item_func_json_array(THD *thd):
|
Item_func_json_array(THD *thd):
|
||||||
Item_str_func(thd) {}
|
Item_json_func(thd) {}
|
||||||
Item_func_json_array(THD *thd, List<Item> &list):
|
Item_func_json_array(THD *thd, List<Item> &list):
|
||||||
Item_str_func(thd, list) {}
|
Item_json_func(thd, list) {}
|
||||||
String *val_str(String *);
|
String *val_str(String *);
|
||||||
bool is_json_type() { return true; }
|
|
||||||
bool fix_length_and_dec();
|
bool fix_length_and_dec();
|
||||||
const char *func_name() const { return "json_array"; }
|
const char *func_name() const { return "json_array"; }
|
||||||
Item *get_copy(THD *thd)
|
Item *get_copy(THD *thd)
|
||||||
@ -273,7 +331,6 @@ public:
|
|||||||
Item_func_json_object(THD *thd, List<Item> &list):
|
Item_func_json_object(THD *thd, List<Item> &list):
|
||||||
Item_func_json_array(thd, list) {}
|
Item_func_json_array(thd, list) {}
|
||||||
String *val_str(String *);
|
String *val_str(String *);
|
||||||
bool is_json_type() { return true; }
|
|
||||||
const char *func_name() const { return "json_object"; }
|
const char *func_name() const { return "json_object"; }
|
||||||
Item *get_copy(THD *thd)
|
Item *get_copy(THD *thd)
|
||||||
{ return get_item_copy<Item_func_json_object>(thd, this); }
|
{ return get_item_copy<Item_func_json_object>(thd, this); }
|
||||||
@ -288,7 +345,6 @@ public:
|
|||||||
Item_func_json_merge(THD *thd, List<Item> &list):
|
Item_func_json_merge(THD *thd, List<Item> &list):
|
||||||
Item_func_json_array(thd, list) {}
|
Item_func_json_array(thd, list) {}
|
||||||
String *val_str(String *);
|
String *val_str(String *);
|
||||||
bool is_json_type() { return true; }
|
|
||||||
const char *func_name() const { return "json_merge_preserve"; }
|
const char *func_name() const { return "json_merge_preserve"; }
|
||||||
Item *get_copy(THD *thd)
|
Item *get_copy(THD *thd)
|
||||||
{ return get_item_copy<Item_func_json_merge>(thd, this); }
|
{ return get_item_copy<Item_func_json_merge>(thd, this); }
|
||||||
@ -439,7 +495,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class Item_func_json_format: public Item_str_func
|
class Item_func_json_format: public Item_json_func
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
enum formats
|
enum formats
|
||||||
@ -454,15 +510,14 @@ protected:
|
|||||||
String tmp_js;
|
String tmp_js;
|
||||||
public:
|
public:
|
||||||
Item_func_json_format(THD *thd, Item *js, formats format):
|
Item_func_json_format(THD *thd, Item *js, formats format):
|
||||||
Item_str_func(thd, js), fmt(format) {}
|
Item_json_func(thd, js), fmt(format) {}
|
||||||
Item_func_json_format(THD *thd, List<Item> &list):
|
Item_func_json_format(THD *thd, List<Item> &list):
|
||||||
Item_str_func(thd, list), fmt(DETAILED) {}
|
Item_json_func(thd, list), fmt(DETAILED) {}
|
||||||
|
|
||||||
const char *func_name() const;
|
const char *func_name() const;
|
||||||
bool fix_length_and_dec();
|
bool fix_length_and_dec();
|
||||||
String *val_str(String *str);
|
String *val_str(String *str);
|
||||||
String *val_json(String *str);
|
String *val_json(String *str);
|
||||||
bool is_json_type() { return true; }
|
|
||||||
Item *get_copy(THD *thd)
|
Item *get_copy(THD *thd)
|
||||||
{ return get_item_copy<Item_func_json_format>(thd, this); }
|
{ return get_item_copy<Item_func_json_format>(thd, this); }
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user