summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Barkov <bar@mariadb.com>2019-06-28 12:35:02 +0400
committerAlexander Barkov <bar@mariadb.com>2019-06-28 12:35:02 +0400
commit323a87b591d3e9bcedb7dea09b69d9eeb1c42880 (patch)
tree6562f42e84209dd655edb8a2a8c66d5e5b992116
parentcff7cf15d7a089639ed0fb2ad038e023cce49df5 (diff)
downloadmariadb-git-323a87b591d3e9bcedb7dea09b69d9eeb1c42880.tar.gz
MDEV-19888 Add abstract class Item_json_func
-rw-r--r--sql/item_jsonfunc.cc95
-rw-r--r--sql/item_jsonfunc.h101
2 files changed, 123 insertions, 73 deletions
diff --git a/sql/item_jsonfunc.cc b/sql/item_jsonfunc.cc
index a90e7fb3a1a..14bffc998e3 100644
--- a/sql/item_jsonfunc.cc
+++ b/sql/item_jsonfunc.cc
@@ -439,7 +439,17 @@ bool Item_func_json_value::fix_length_and_dec()
{
collation.set(args[0]->collation);
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;
return FALSE;
}
@@ -449,115 +459,100 @@ bool Item_func_json_value::fix_length_and_dec()
Returns NULL, not an error if the found value
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= args[0]->val_json(&tmp_js);
+ String *js= item_js->val_json(&tmp_js);
int error= 0;
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 &&
- 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()))
- goto err_return;
- path.parsed= path.constant;
+ return true;
+ parsed= constant;
}
- if ((null_value= args[0]->null_value || args[1]->null_value))
- return NULL;
-
- json_scan_start(&je, js->charset(),(const uchar *) js->ptr(),
- (const uchar *) js->ptr() + js->length());
+ if (item_js->null_value || item_jp->null_value)
+ return true;
+ Json_engine_scan je(*js);
str->length(0);
- str->set_charset(collation.collation);
+ str->set_charset(cs);
- path.cur_step= path.p.steps;
+ cur_step= p.steps;
continue_search:
- if (json_find_path(&je, &path.p, &path.cur_step, array_counters))
- {
- if (je.s.error)
- goto err_return;
-
- null_value= 1;
- return 0;
- }
+ if (json_find_path(&je, &p, &cur_step, array_counters))
+ return true;
if (json_read_value(&je))
- goto err_return;
+ return true;
if (unlikely(check_and_get_value(&je, str, &error)))
{
if (error)
- goto err_return;
+ return true;
goto continue_search;
}
- return str;
-
-err_return:
- null_value= 1;
- return 0;
+ return false;
}
-bool Item_func_json_value::check_and_get_value(json_engine_t *je, String *res,
- int *error)
+bool Json_engine_scan::check_and_get_value_scalar(String *res, int *error)
{
CHARSET_INFO *json_cs;
const uchar *js;
uint js_len;
- if (!json_value_scalar(je))
+ if (!json_value_scalar(this))
{
/* 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;
return true;
}
- if (je->value_type == JSON_VALUE_TRUE ||
- je->value_type == JSON_VALUE_FALSE)
+ if (value_type == JSON_VALUE_TRUE ||
+ value_type == JSON_VALUE_FALSE)
{
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;
}
else
{
- json_cs= je->s.cs;
- js= je->value;
- js_len= je->value_len;
+ json_cs= s.cs;
+ js= value;
+ js_len= value_len;
}
- return st_append_json(res, json_cs, js, js_len);
+ return st_append_json(res, json_cs, js, js_len);
}
-bool Item_func_json_query::check_and_get_value(json_engine_t *je, String *res,
- int *error)
+bool Json_engine_scan::check_and_get_value_complex(String *res, int *error)
{
- const uchar *value;
- if (json_value_scalar(je))
+ if (json_value_scalar(this))
{
/* We skip scalar values. */
- if (json_scan_next(je))
+ if (json_scan_next(this))
*error= 1;
return true;
}
- value= je->value;
- if (json_skip_level(je))
+ const uchar *tmp_value= value;
+ if (json_skip_level(this))
{
*error= 1;
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;
}
diff --git a/sql/item_jsonfunc.h b/sql/item_jsonfunc.h
index e9b77502e80..a9e6f39b5c8 100644
--- a/sql/item_jsonfunc.h
+++ b/sql/item_jsonfunc.h
@@ -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
{
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:
Item_func_json_value(THD *thd, Item *js, Item *i_path):
Item_str_func(thd, js, i_path) {}
const char *func_name() const { return "json_value"; }
bool fix_length_and_dec();
- String *val_str(String *);
- virtual bool check_and_get_value(json_engine_t *je, String *res, int *error);
+ 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_scalar(res, error);
+ }
Item *get_copy(THD *thd)
{ 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:
Item_func_json_query(THD *thd, Item *js, Item *i_path):
- Item_func_json_value(thd, js, i_path) {}
- bool is_json_type() { return true; }
+ Item_json_func(thd, js, i_path) {}
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)
{ 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:
json_path_with_flags *paths;
String *tmp_paths;
public:
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);
void cleanup();
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:
String tmp_val;
ulong result_limit;
public:
Item_func_json_array(THD *thd):
- Item_str_func(thd) {}
+ Item_json_func(thd) {}
Item_func_json_array(THD *thd, List<Item> &list):
- Item_str_func(thd, list) {}
+ Item_json_func(thd, list) {}
String *val_str(String *);
- bool is_json_type() { return true; }
bool fix_length_and_dec();
const char *func_name() const { return "json_array"; }
Item *get_copy(THD *thd)
@@ -273,7 +331,6 @@ public:
Item_func_json_object(THD *thd, List<Item> &list):
Item_func_json_array(thd, list) {}
String *val_str(String *);
- bool is_json_type() { return true; }
const char *func_name() const { return "json_object"; }
Item *get_copy(THD *thd)
{ 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_array(thd, list) {}
String *val_str(String *);
- bool is_json_type() { return true; }
const char *func_name() const { return "json_merge_preserve"; }
Item *get_copy(THD *thd)
{ 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:
enum formats
@@ -454,15 +510,14 @@ protected:
String tmp_js;
public:
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_str_func(thd, list), fmt(DETAILED) {}
+ Item_json_func(thd, list), fmt(DETAILED) {}
const char *func_name() const;
bool fix_length_and_dec();
String *val_str(String *str);
String *val_json(String *str);
- bool is_json_type() { return true; }
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_json_format>(thd, this); }
};