Description:
When manipulating the result of JSON_MERGE with JSON_SET, sometimes wrong results are produced.
How to repeat:
mysql> select json_set(json_array(json_merge(json_object('a', 1), json_object('a', 2))), '$[0].a', 123);
+-------------------------------------------------------------------------------------------+
| json_set(json_array(json_merge(json_object('a', 1), json_object('a', 2))), '$[0].a', 123) |
+-------------------------------------------------------------------------------------------+
| 123 |
+-------------------------------------------------------------------------------------------+
1 row in set (0,00 sec)
The query should have returned [{"a": 123}].
Suggested fix:
Json_object::consume(), which is used by JSON_MERGE, does not update the parent pointer when it merges two members. This makes the DOM inconsistent, which confuses JSON_SET and makes it return wrong results. Setting the parent pointer of the merged member seems to fix the bug.
diff --git a/sql/json_dom.cc b/sql/json_dom.cc
index 620c192..341a6ab 100644
--- a/sql/json_dom.cc
+++ b/sql/json_dom.cc
@@ -1225,6 +1225,7 @@ bool Json_object::consume(Json_object *other)
this_iter->second= merge_doms(this_iter->second, value);
if (this_iter->second == NULL)
return true; /* purecov: inspected */
+ this_iter->second->set_parent(this);
}
}
Description: When manipulating the result of JSON_MERGE with JSON_SET, sometimes wrong results are produced. How to repeat: mysql> select json_set(json_array(json_merge(json_object('a', 1), json_object('a', 2))), '$[0].a', 123); +-------------------------------------------------------------------------------------------+ | json_set(json_array(json_merge(json_object('a', 1), json_object('a', 2))), '$[0].a', 123) | +-------------------------------------------------------------------------------------------+ | 123 | +-------------------------------------------------------------------------------------------+ 1 row in set (0,00 sec) The query should have returned [{"a": 123}]. Suggested fix: Json_object::consume(), which is used by JSON_MERGE, does not update the parent pointer when it merges two members. This makes the DOM inconsistent, which confuses JSON_SET and makes it return wrong results. Setting the parent pointer of the merged member seems to fix the bug. diff --git a/sql/json_dom.cc b/sql/json_dom.cc index 620c192..341a6ab 100644 --- a/sql/json_dom.cc +++ b/sql/json_dom.cc @@ -1225,6 +1225,7 @@ bool Json_object::consume(Json_object *other) this_iter->second= merge_doms(this_iter->second, value); if (this_iter->second == NULL) return true; /* purecov: inspected */ + this_iter->second->set_parent(this); } }