fix(mysql): decode JSON columns in get_full_data by RitiGrover · Pull Request #130 · long2ice/meilisync · GitHub
Skip to content

fix(mysql): decode JSON columns in get_full_data - #130

Open
RitiGrover wants to merge 1 commit into
long2ice:devfrom
RitiGrover:fix/mysql-decode-json-columns-full-sync
Open

RitiGrover wants to merge 1 commit into
long2ice:devfrom
RitiGrover:fix/mysql-decode-json-columns-full-sync

Conversation

@RitiGrover

Copy link
Copy Markdown

Description

MySQL.get_full_data runs a plain SELECT and yields whatever DictCursor.fetchall() returns. For a JSON column, that's the raw text serialization (asyncmy doesn't decode it for a normal query result) - unlike the binlog row-event path used for incremental sync, which already imports FIELD_TYPE.JSON from asyncmy.constants and decodes it natively. So a full sync stores JSON columns as strings in Meilisearch, while incremental updates for the same table store them as proper objects/arrays.

Motivation and Context

Fixes #109. Confirmed directly against a real MySQL 8 instance: SELECT on a JSON column via asyncmy's DictCursor returns a Python str, not a dict/list.

How Has This Been Tested?

  • Verified against a live MySQL 8 container that asyncmy's DictCursor.fetchall() returns JSON columns as str, confirming the root cause.
  • Checked asyncmy.replication.row_events to confirm the binlog decoder already handles FIELD_TYPE.JSON, which is why only the full-sync path is affected.
  • Added test_get_full_data_decodes_json_columns to tests/test_mysql.py, following the existing file's pattern (connects to MySQL directly, no daemon/Meilisearch process needed). Confirmed it fails on the current code (JSON column comes back as a string) and passes with the fix.
  • ruff check/ruff format clean on the changed lines (the file has some pre-existing lint findings on lines I didn't touch - left those alone).

I didn't touch the binlog path since it already decodes JSON correctly; the fix is scoped to get_full_data only.

A plain SELECT returns JSON columns as their raw text serialization;
asyncmy doesn't decode them automatically for a regular query result,
unlike the binlog row-event decoder used for incremental sync, which
already imports FIELD_TYPE.JSON and decodes it natively. So a full
sync stored JSON columns as strings in Meilisearch while incremental
updates stored them as proper objects/arrays.

Use cursor.description to find JSON columns and json.loads() them,
matching what the binlog path already does.

Fixes long2ice#109
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

JSON data from MySQL is synced as strings in Meilisearch

1 participant