summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexey Botchkov <holyfoot@askmonty.org>2017-02-14 17:51:03 +0400
committerAlexey Botchkov <holyfoot@askmonty.org>2017-02-14 17:51:03 +0400
commitf76d5fefb818760f41488c1793fca27d97c9c2a0 (patch)
tree29cea084ed332b568fe98c4a2140a131d652158c
parent2bf07556e8ba35ea166b1f603706851faa01d9c5 (diff)
downloadmariadb-git-f76d5fefb818760f41488c1793fca27d97c9c2a0.tar.gz
MDEV-11439 No data type JSON, but CAST(something AS JSON) pretends to
work. json_detailed() fixed
-rw-r--r--mysql-test/r/func_json.result22
-rw-r--r--mysql-test/t/func_json.test4
-rw-r--r--sql/item_create.cc25
-rw-r--r--sql/item_jsonfunc.cc69
-rw-r--r--sql/item_jsonfunc.h5
5 files changed, 112 insertions, 13 deletions
diff --git a/mysql-test/r/func_json.result b/mysql-test/r/func_json.result
index e8d11fce56f..4c1c82ed331 100644
--- a/mysql-test/r/func_json.result
+++ b/mysql-test/r/func_json.result
@@ -567,3 +567,25 @@ json_merge('{"a":{"u":12, "x":"b"}}', '{"a":{"x":"c"}}')
select json_merge('{"a":{"u":12, "x":"b", "r":1}}', '{"a":{"x":"c", "r":2}}') ;
json_merge('{"a":{"u":12, "x":"b", "r":1}}', '{"a":{"x":"c", "r":2}}')
{"a": {"u": 12, "x": ["b", "c"], "r": [1, 2]}}
+select json_compact('{"a":1, "b":[1,2,3], "c":{"aa":"v1", "bb": "v2"}}');
+json_compact('{"a":1, "b":[1,2,3], "c":{"aa":"v1", "bb": "v2"}}')
+{"a":1,"b":[1,2,3],"c":{"aa":"v1","bb":"v2"}}
+select json_loose('{"a":1, "b":[1,2,3], "c":{"aa":"v1", "bb": "v2"}}');
+json_loose('{"a":1, "b":[1,2,3], "c":{"aa":"v1", "bb": "v2"}}')
+{"a": 1, "b": [1, 2, 3], "c": {"aa": "v1", "bb": "v2"}}
+select json_detailed('{"a":1, "b":[1,2,3], "c":{"aa":"v1", "bb": "v2"}}');
+json_detailed('{"a":1, "b":[1,2,3], "c":{"aa":"v1", "bb": "v2"}}')
+{
+ "a": 1,
+ "b":
+ [
+ 1,
+ 2,
+ 3
+ ],
+ "c":
+ {
+ "aa": "v1",
+ "bb": "v2"
+ }
+}
diff --git a/mysql-test/t/func_json.test b/mysql-test/t/func_json.test
index aedc65159c5..be56eb46d09 100644
--- a/mysql-test/t/func_json.test
+++ b/mysql-test/t/func_json.test
@@ -234,3 +234,7 @@ select json_merge('{"a":"b"}', '{"a":"c"}') ;
select json_merge('{"a":{"x":"b"}}', '{"a":"c"}') ;
select json_merge('{"a":{"u":12, "x":"b"}}', '{"a":{"x":"c"}}') ;
select json_merge('{"a":{"u":12, "x":"b", "r":1}}', '{"a":{"x":"c", "r":2}}') ;
+
+select json_compact('{"a":1, "b":[1,2,3], "c":{"aa":"v1", "bb": "v2"}}');
+select json_loose('{"a":1, "b":[1,2,3], "c":{"aa":"v1", "bb": "v2"}}');
+select json_detailed('{"a":1, "b":[1,2,3], "c":{"aa":"v1", "bb": "v2"}}');
diff --git a/sql/item_create.cc b/sql/item_create.cc
index d2be36e105f..dee1db1ee2e 100644
--- a/sql/item_create.cc
+++ b/sql/item_create.cc
@@ -1788,10 +1788,10 @@ protected:
};
-class Create_func_json_detailed : public Create_func_arg2
+class Create_func_json_detailed: public Create_native_func
{
public:
- virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2);
+ virtual Item *create_native(THD *thd, LEX_STRING name, List<Item> *item_list);
static Create_func_json_detailed s_singleton;
@@ -1801,7 +1801,6 @@ protected:
};
-
class Create_func_json_type : public Create_func_arg1
{
public:
@@ -5046,9 +5045,25 @@ Create_func_json_exists::create_2_arg(THD *thd, Item *arg1, Item *arg2)
Create_func_json_detailed Create_func_json_detailed::s_singleton;
Item*
-Create_func_json_detailed::create_2_arg(THD *thd, Item *arg1, Item *arg2)
+Create_func_json_detailed::create_native(THD *thd, LEX_STRING name,
+ List<Item> *item_list)
{
- return new (thd->mem_root) Item_func_json_format(thd, arg1, arg2);
+ Item *func= NULL;
+ int arg_count= 0;
+
+ if (item_list != NULL)
+ arg_count= item_list->elements;
+
+ if (arg_count < 1 || arg_count > 2 /* json_doc, [path]...*/)
+ {
+ my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name.str);
+ }
+ else
+ {
+ func= new (thd->mem_root) Item_func_json_format(thd, *item_list);
+ }
+
+ return func;
}
diff --git a/sql/item_jsonfunc.cc b/sql/item_jsonfunc.cc
index ae885dc7702..d955ddb53df 100644
--- a/sql/item_jsonfunc.cc
+++ b/sql/item_jsonfunc.cc
@@ -113,8 +113,24 @@ static int st_append_escaped(String *s, const String *a)
}
+static const int TAB_SIZE_LIMIT= 8;
+static const char tab_arr[TAB_SIZE_LIMIT+1]= " ";
+
+static int append_tab(String *js, int depth, int tab_size)
+{
+ if (js->append("\n", 1))
+ return 1;
+ for (int i=0; i<depth; i++)
+ {
+ if (js->append(tab_arr, tab_size))
+ return 1;
+ }
+ return 0;
+}
+
+
static int json_nice(json_engine_t *je, String *nice_js,
- Item_func_json_format::formats mode)
+ Item_func_json_format::formats mode, int tab_size=4)
{
int depth= 0;
const char *comma, *colon;
@@ -122,19 +138,24 @@ static int json_nice(json_engine_t *je, String *nice_js,
int first_value= 1;
DBUG_ASSERT(je->s.cs == nice_js->charset());
+ DBUG_ASSERT(mode != Item_func_json_format::DETAILED ||
+ (tab_size >= 0 && tab_size <= TAB_SIZE_LIMIT));
+ comma= ", ";
+ colon= "\": ";
if (mode == Item_func_json_format::LOOSE)
{
- comma= ", ";
comma_len= 2;
- colon= "\": ";
+ colon_len= 3;
+ }
+ else if (mode == Item_func_json_format::DETAILED)
+ {
+ comma_len= 1;
colon_len= 3;
}
else
{
- comma= ",";
comma_len= 1;
- colon= "\":";
colon_len= 2;
}
@@ -158,6 +179,10 @@ static int json_nice(json_engine_t *je, String *nice_js,
if (!first_value)
nice_js->append(comma, comma_len);
+ if (mode == Item_func_json_format::DETAILED &&
+ append_tab(nice_js, depth, tab_size))
+ goto error;
+
nice_js->append("\"", 1);
append_simple(nice_js, key_start, key_end - key_start);
nice_js->append(colon, colon_len);
@@ -170,6 +195,11 @@ static int json_nice(json_engine_t *je, String *nice_js,
if (!first_value)
nice_js->append(comma, comma_len);
+ if (mode == Item_func_json_format::DETAILED &&
+ depth > 0 &&
+ append_tab(nice_js, depth, tab_size))
+ goto error;
+
handle_value:
if (json_read_value(je))
goto error;
@@ -183,6 +213,10 @@ handle_value:
}
else
{
+ if (mode == Item_func_json_format::DETAILED &&
+ depth > 0 &&
+ append_tab(nice_js, depth, tab_size))
+ goto error;
nice_js->append((je->value_type == JSON_VALUE_OBJECT) ? "{" : "[", 1);
first_value= 1;
depth++;
@@ -193,6 +227,9 @@ handle_value:
case JST_OBJ_END:
case JST_ARRAY_END:
depth--;
+ if (mode == Item_func_json_format::DETAILED &&
+ append_tab(nice_js, depth, tab_size))
+ goto error;
nice_js->append((je->state == JST_OBJ_END) ? "}": "]", 1);
first_value= 0;
break;
@@ -2941,15 +2978,35 @@ String *Item_func_json_format::val_str(String *str)
{
String *js= args[0]->val_str(&tmp_js);
json_engine_t je;
+ int tab_size;
+
if ((null_value= args[0]->null_value))
return 0;
+ if (fmt == DETAILED)
+ {
+ tab_size= 4;
+ if (arg_count > 1)
+ {
+ tab_size= args[1]->val_int();
+ if (args[1]->null_value)
+ {
+ null_value= 1;
+ return 0;
+ }
+ }
+ if (tab_size < 0)
+ tab_size= 0;
+ else if (tab_size > TAB_SIZE_LIMIT)
+ tab_size= TAB_SIZE_LIMIT;
+ }
+
json_scan_start(&je, js->charset(), (const uchar *) js->ptr(),
(const uchar *) js->ptr()+js->length());
str->length(0);
str->set_charset(js->charset());
- if (json_nice(&je, str, fmt))
+ if (json_nice(&je, str, fmt, tab_size))
{
null_value= 1;
report_json_error(js, &je, 0);
diff --git a/sql/item_jsonfunc.h b/sql/item_jsonfunc.h
index 941123041d2..0eedfa18be1 100644
--- a/sql/item_jsonfunc.h
+++ b/sql/item_jsonfunc.h
@@ -443,8 +443,9 @@ protected:
public:
Item_func_json_format(THD *thd, Item *js, formats format):
Item_str_func(thd, js), fmt(format) {}
- Item_func_json_format(THD *thd, Item *js, Item *tabsize):
- Item_str_func(thd, js, tabsize), fmt(DETAILED) {}
+ Item_func_json_format(THD *thd, List<Item> &list):
+ Item_str_func(thd, list), fmt(DETAILED) {}
+
const char *func_name() const;
void fix_length_and_dec();
String *val_str(String *str);