Addresses issues found in review of 16ce07df15 (Replicate MySQL binary
JSON to a MariaDB slave), in both the new code and two pieces of
pre-existing core replication code it interacts with. Issue numbers
below refer to the review's own numbering (I001-I039).
Crashes and silent corruption:
- A truncated or malformed Json_diff vector in a
PARTIAL_UPDATE_ROWS_EVENT could NULL-deref the slave:
safe_net_field_length_ll() nulls its cursor on a truncated
encoding, and nothing checked for that. (I001, I002)
- The same unchecked-cursor bug existed in the after-image header
parser, which additionally had no bound on partial_bits
consumption and did not reject out-of-range value_options. (I005)
- A diff that MySQL's own applier would REJECT (its path doesn't
match the slave's document) was silently applied as a no-op
instead of halting replication - the opposite of MySQL's own
behavior (ER_COULD_NOT_APPLY_JSON_DIFF). (I004, I025)
- Corrupt MySQL binary JSON in a diff value was committed as a JSON
null instead of being detected: Field_mysql_json::val_str() pushes
an error but returns a non-null empty string on failure, so the
previous `if (!vtext)` check could never fire. (I003)
- The same silent-corruption class existed on the full-document
conversion path for a native-JSON target. (I038)
- find_row() failing to locate the matched row still read the base
document from stale record[1] data, and did not record the
correct stream position on error, risking a parse desync under
slave_exec_mode=IDEMPOTENT. (I020, I033)
Error reporting:
- Most failure paths in apply_partial_json_column() returned a bare
HA_ERR_GENERIC with nothing reported to the DBA, contradicting the
function's own documented contract. (I024, I026, I027, I031)
- Fixed messages use my_printf_error() rather than
rgi->rli->report(): do_exec_row()'s caller unconditionally
re-derives Last_SQL_Error from thd->is_error() once a row event
returns an error, overwriting anything rgi->rli->report() had
already recorded with a generic "Got error NNN from storage
engine" wrapper - only a message already in the diagnostics area
survives.
- check_wrong_column_usage() only checked an UPDATE event's
before-image bitmap, so an incompatible column visible only in
the after-image (binlog_row_image=MINIMAL) was silently dropped
from the write set instead of being reported. (I006)
- slave.cc's IO-thread statement-end tracking was missing
PARTIAL_UPDATE_ROWS_EVENT, which could produce a false-positive
"did not receive an expected Rows-log end-of-statement" error.
(I008)
- Documented, but did not fix (needs generic plugin refcounting,
out of scope here): Type_handler::handler_by_name() releases its
plugin lock before the caller is done using the returned handler,
a pre-existing race in the data-type plugin framework. (I039)
Design/consistency:
- A MySQL JSON source converting to a plain string/blob target was
always classified as safely widening regardless of actual size;
it is now classified by the target's real declared capacity like
any other blob/string conversion, so a document that doesn't fit
requires slave_type_conversions=ALL_LOSSY instead of silently
truncating under ALL_NON_LOSSY alone. (I007)
- apply_partial_json_column() now builds its per-diff JSON function
Items on a private MEM_ROOT freed per row/column, instead of
thd->mem_root (the statement-level arena), avoiding unbounded
growth on a large multi-row UPDATE. (I028)
- An open-coded bitmap test duplicating the existing
rpl_bitmap_is_set() helper was replaced with a call to it. (I032)
- Corrected a comment overstating MySQL JSON -> native JSON
conversion as lossless; a JSONB OPAQUE temporal/decimal value
loses its original type tag even though its content survives.
(I036)
- Deduplicated the "MYSQL_JSON" plugin-name literal into one
constant. (I037)
Tests:
- Switched the existing tests from unconditional INSTALL/UNINSTALL
SONAME to the repo's have_type_mysql_json.inc convention. (I013)
- Corrected a test comment that misattributed why the from-the-end
array-index diff is refused. (I014)
- Extracted the tests' duplicated binlog-fixture-injection and
post-replication resync logic into shared include files. (I015)
- Added tests for the missing-plugin, conversion-length-gating, and
corrupt-diff-vector error paths above. (I016)
Assisted-by: Claude AI