Skip to content

[Bug]: MySQL JSON column values shown as NULL in data grid#107

Merged
debba merged 2 commits intodebba:mainfrom
midasism:fix/mysql-json-column-shown-as-null
Mar 28, 2026
Merged

[Bug]: MySQL JSON column values shown as NULL in data grid#107
debba merged 2 commits intodebba:mainfrom
midasism:fix/mysql-json-column-shown-as-null

Conversation

@midasism
Copy link
Copy Markdown

@midasism midasism commented Mar 28, 2026

Summary

  • MySQL JSON type columns display null in the data grid even when they contain valid JSON data
  • JSON columns in the sidebar row editor display [object Object] and cannot be edited
  • Root cause: extract_value in mysql/extract.rs has no dedicated JSON branch — unlike the PostgreSQL driver which explicitly handles serde_json::Value, the MySQL driver falls through all try_get attempts and hits the fallback Null return
  • Additionally, update_record and insert_record reject Object/Array values with "Unsupported Value type" error

Changes

Backend (Rust)

  1. src-tauri/Cargo.toml: add "json" to sqlx features — this registers Decode<MySql> for serde_json::Value
  2. src-tauri/src/drivers/mysql/extract.rs: add a col_type == "JSON" branch before the GEOMETRY block, mirroring the PostgreSQL approach with an additional raw-byte fallback for edge cases
  3. src-tauri/src/drivers/mysql/mod.rs: handle Object/Array values in update_record and insert_record via CAST(? AS JSON) instead of returning an error

Frontend (React/TypeScript)

  1. src/utils/json.ts (new): isJsonColumn, formatJsonForEditor, validateJson, parseJsonEditorValue utility functions
  2. src/components/ui/JsonInput.tsx (new): dedicated JSON editor component with:
    • Pretty-printed textarea display
    • Real-time JSON validation with visual indicator (green ✓ / red ✗)
    • One-click format button
    • Error detail display
  3. src/components/ui/FieldEditor.tsx: wire JsonInput for JSON/JSONB column types in the sidebar editor
  4. src/components/ui/DataGrid.tsx: double-click on JSON cells opens the sidebar editor instead of inline editing
  5. src/i18n/locales/{en,zh,it,es}.json: add jsonInput translation keys

Test plan

  • Connect to a MySQL 8.0+ database with a table containing a JSON column
  • Verify JSON values are rendered correctly in the data grid (not shown as null)
  • Verify actual NULL JSON values still display as null
  • Double-click a JSON cell opens the sidebar with a formatted JSON editor
  • Edit JSON in the sidebar editor with real-time validation
  • Submit edited JSON values back to the database successfully
  • Verify CSV/JSON export includes correct JSON values
  • Verify PostgreSQL and SQLite JSON handling is unaffected

MySQL JSON columns were not being decoded properly because
`extract_value` lacked a dedicated JSON branch. Unlike PostgreSQL
which already handles `serde_json::Value`, the MySQL driver fell
through every `try_get` attempt and returned `Null`.

- Enable the sqlx `json` feature so `Decode<MySql>` is implemented
  for `serde_json::Value`
- Add an explicit JSON type branch in `mysql/extract.rs` that first
  tries `try_get::<serde_json::Value>`, then falls back to raw-byte
  decoding and manual JSON parsing

Made-with: Cursor
@kilo-code-bot
Copy link
Copy Markdown

kilo-code-bot bot commented Mar 28, 2026

Code Review Summary

Status: No Issues Found | Recommendation: Merge

Files Reviewed (8 files)
  • src-tauri/src/drivers/mysql/mod.rs - Added JSON Object/Array handling in update_record and insert_record using CAST(? AS JSON) (lines 521-526, 612-617)
  • src/components/ui/DataGrid.tsx - Added JSON column handling to open sidebar editor on double-click (lines 306-314)
  • src/components/ui/FieldEditor.tsx - Wired JsonInput component for JSON/JSONB column types (lines 100-106)
  • src/components/ui/JsonInput.tsx - New JSON editor component with validation, formatting, and real-time error feedback
  • src/utils/json.ts - New utility functions: isJsonColumn, formatJsonForEditor, validateJson, parseJsonEditorValue
  • src/i18n/locales/en.json, es.json, it.json, zh.json - Added jsonInput translation keys

Notes:

  • The MySQL JSON handling correctly uses CAST(? AS JSON) syntax for proper type conversion
  • The JsonInput component provides good UX with real-time validation, format button, and visual indicators
  • Implementation follows existing patterns (BlobInput, GeometryInput) for specialized column types
  • Error handling is consistent with the rest of the codebase

Reviewed by kimi-k2.5-0127 · 115,816 tokens

JSON columns in the sidebar row editor previously displayed
"[object Object]" and were not editable. This adds a dedicated
JsonInput component with real-time validation, pretty-print
formatting, and proper read/write support for JSON values.

- Add `src/utils/json.ts` with isJsonColumn, formatJsonForEditor,
  validateJson, and parseJsonEditorValue helpers
- Add `src/components/ui/JsonInput.tsx` — textarea-based JSON editor
  with format button and valid/invalid indicator
- Wire JsonInput into FieldEditor for JSON/JSONB columns
- DataGrid: double-click on JSON cells opens sidebar editor
- Backend: update_record and insert_record now accept Object/Array
  values via CAST(? AS JSON) instead of rejecting them
- Add i18n keys for en, zh, it, es

Made-with: Cursor
@debba
Copy link
Copy Markdown
Owner

debba commented Mar 28, 2026

Hi!
Thanks for your contribution!

Are you already working on it?
Because I did some tests, but always continue to see JSON columns as NULL and inside columns view, I can see the column as LONGTEXT

@midasism
Copy link
Copy Markdown
Author

midasism commented Mar 28, 2026

Hi @debba, thanks for testing!

I verified the fix works correctly on MySQL 8.0.42. The limit_info (JSON column) renders properly in the data grid — showing values like {"minMonths":10}, {"lookbackDays":365,"serviceTypeIds":[18,20]} etc., instead of null.
image

The key difference is likely the MySQL variant you're testing on:

  • On MySQL 8.0+, JSON is a native column type. sqlx reports type_info().name() as "JSON", and String::compatible() does not include ColumnType::Json — which is exactly why the original code falls through to Null. This fix adds a dedicated "JSON" branch with try_get::<serde_json::Value>.

  • On MariaDB, JSON is an alias for LONGTEXT (MariaDB docs). sqlx returns "LONGTEXT" instead of "JSON", so the new branch won't match. However, on MariaDB the existing try_get::<String> path should already work since LONGTEXT maps to ColumnType::LongBlob (without BINARY flag), which is in String::compatible().

Could you confirm which database you're testing on? You can check with SELECT VERSION(). If it contains "MariaDB", that would explain the LONGTEXT type you're seeing — and in that case the JSON display issue on MariaDB would be a separate bug with a different root cause.

My test environment:

  • MySQL 8.0.42
  • DDL:
CREATE TABLE `tapp_appointment_recommend_rule_limit` (
  `id` int NOT NULL AUTO_INCREMENT,
  `limit_type` tinyint NOT NULL,
  `limit_info` json NOT NULL,
  `delete_flag` tinyint NOT NULL DEFAULT 0,
  `rule_id` int NOT NULL,
  `created` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`)
);

@debba
Copy link
Copy Markdown
Owner

debba commented Mar 28, 2026

Sorry, you're right.
I'll merge it, thanks a lot :)

@debba debba merged commit 318dbc8 into debba:main Mar 28, 2026
1 check passed
@debba
Copy link
Copy Markdown
Owner

debba commented Mar 29, 2026

I added my thanks here:

https://tabularis.dev/blog/v0912-tokio-postgres-minimax-json-editor

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.

2 participants