Bug #80787 Wrong result when manipulating result of JSON_MERGE
Submitted: 17 Mar 2016 22:50 Modified: 27 Jun 2016 17:41
Reporter: Knut Anders Hatlen Email Updates:
Status: Closed Impact on me:
None 
Category:MySQL Server: JSON Severity:S3 (Non-critical)
Version:5.7 OS:Any
Assigned to: CPU Architecture:Any

[17 Mar 2016 22:50] Knut Anders Hatlen
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);
     }
   }
[27 Jun 2016 17:41] Jon Stephens
Documented fix in the MySQL 8.0.0 changelog as follows:

    Manipulation of a value returned by the JSON_MERGE() function using
    JSON_SET() sometimes produced an invalid result.

Closed.
[3 Jan 2018 12:27] Jon Stephens
Also fixed in MySQL 5.7.22, same changelog entry. Closed.