Overview of the Issue
MySQL's binary JSON format stores richer type information than standard text JSON. Values like CAST('2024-01-15' as DATE), TIME, DATETIME, DECIMAL, BIT, and BLOB all have distinct type tags in the binary representation, but are indistinguishable from plain strings or numbers in text JSON.
During VReplication, the vstreamer decodes binary JSON from the binlog into a json.Value tree (which preserves these types), but then immediately serializes it to text JSON via MarshalTo() before sending it over gRPC (go/mysql/binlog/rbr.go:688-694). This discards the type tags. On the replicator side, marshalJSONForSQL() re-parses that text, but can only recover standard JSON types. The tree-based encoder's code paths for TypeDate, TypeTime, TypeDateTime, TypeBlob, and TypeBit are effectively dead code in the VReplication flow.
As a result, after VReplication copies a table, JSON documents with MySQL-specific typed values will have those values stored as their text equivalents (strings/numbers) on the target. JSON_TYPE() returns different results on source vs. target, and any behavior depending on internal type tags (sorting, comparison) may differ.
Reproduction Steps
- On the source, create a table with a JSON column and insert a value with a typed JSON element:
CREATE TABLE t1 (id INT PRIMARY KEY, doc JSON);
INSERT INTO t1 VALUES (1, JSON_OBJECT('created', CAST('2024-01-15' as DATE)));
- Verify the type on the source:
SELECT JSON_TYPE(JSON_EXTRACT(doc, '$.created')) FROM t1;
-- Returns: DATE
- VReplicate the table to a target.
- Check the type on the target:
SELECT JSON_TYPE(JSON_EXTRACT(doc, '$.created')) FROM t1;
-- Returns: STRING
Binary Version
All versions (the code path has been present since at least the introduction of MarshalTo in rbr.go).
Operating System and Environment details
N/A — this is a logic issue in the vstreamer's JSON serialization, not environment-specific.
Log Fragments
N/A — no errors are produced. The type degradation is silent.
Overview of the Issue
MySQL's binary JSON format stores richer type information than standard text JSON. Values like
CAST('2024-01-15' as DATE),TIME,DATETIME,DECIMAL,BIT, andBLOBall have distinct type tags in the binary representation, but are indistinguishable from plain strings or numbers in text JSON.During VReplication, the vstreamer decodes binary JSON from the binlog into a
json.Valuetree (which preserves these types), but then immediately serializes it to text JSON viaMarshalTo()before sending it over gRPC (go/mysql/binlog/rbr.go:688-694). This discards the type tags. On the replicator side,marshalJSONForSQL()re-parses that text, but can only recover standard JSON types. The tree-based encoder's code paths forTypeDate,TypeTime,TypeDateTime,TypeBlob, andTypeBitare effectively dead code in the VReplication flow.As a result, after VReplication copies a table, JSON documents with MySQL-specific typed values will have those values stored as their text equivalents (strings/numbers) on the target.
JSON_TYPE()returns different results on source vs. target, and any behavior depending on internal type tags (sorting, comparison) may differ.Reproduction Steps
Binary Version
All versions (the code path has been present since at least the introduction of
MarshalToinrbr.go).Operating System and Environment details
N/A — this is a logic issue in the vstreamer's JSON serialization, not environment-specific.
Log Fragments
N/A — no errors are produced. The type degradation is silent.