Skip to content

Commit ca45984

Browse files
authored
fix(plugin-mysql): read MARIADB_CONST_STRING by length to stop JSON detection flicker (#1216)
1 parent ba28ce8 commit ca45984

2 files changed

Lines changed: 7 additions & 2 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
9999
### Fixed
100100

101101
- Data grid: dropdown / boolean / date / JSON / blob cells now show or hide their chevron accessory when the cell's editability changes (refresh, safe-mode toggle, view-to-table switch). The performance pass in #1212 made `configure` skip `needsDisplay = true` when nothing visible changed, but the editability flag was updated unconditionally without flagging a redraw, so chevrons could stick in their stale state (visible in `audit_log.payload` JSON cells after save / refresh / reopen)
102+
- MySQL/MariaDB: JSON column detection no longer flickers across refreshes. The plugin reads `mariadb_field_attr(MARIADB_FIELD_ATTR_FORMAT_NAME)` to recognize JSON-stored-as-LONGTEXT. The returned `MARIADB_CONST_STRING` is a length-prefixed buffer (not null-terminated), but we were reading it with `String(cString:)`, which scans bytes until the next `\0` and so reads past the buffer into adjacent memory. When that memory happened to contain a null byte the comparison passed and we tagged the column `JSON`; when it contained garbage the comparison failed and we fell through to `LONGTEXT`. Read exactly `attr.length` bytes via `String(data: Data(bytes:count:), encoding: .utf8)`
102103
- Welcome window sometimes failed to open on launch (and Dock-icon clicks did nothing) when the previous session restored only main connection windows. `WindowOpenerBridge` was mounted only in the Welcome scene and used `.onAppear`, so if Welcome got `orderOut`'d before its first appearance the bridge never wired and every `openWelcome()` call queued forever. The bridge now mounts in all four SwiftUI scenes (Welcome, ConnectionForm, IntegrationsActivity, Settings) and uses `.task` so wiring fires reliably whenever any scene materializes
103104
- Plugin upgrades for built-in drivers (MySQL, PostgreSQL, SQLite, ClickHouse, Redis, etc.) no longer revert to the bundled version after restart. Discovery now scans both built-in and user plugin directories, picks the newest version by `CFBundleShortVersionString`, and only prunes user copies that are older than or equal to the built-in (#1192)
104105
- Concurrent plugin installs from the registry can no longer race past the `isInstalling` guard; the lock now wraps `installFromRegistry` and `updateFromRegistry` end-to-end

Plugins/MySQLDriverPlugin/MariaDBPluginConnection.swift

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,11 +78,15 @@ func mysqlTypeToString(_ fieldPtr: UnsafePointer<MYSQL_FIELD>) -> String {
7878
let flags = UInt(field.flags)
7979
let length = field.length
8080

81-
// MariaDB extended metadata: detect JSON stored as LONGTEXT (best-effort)
81+
// MariaDB extended metadata: detect JSON stored as LONGTEXT.
82+
// `MARIADB_CONST_STRING` is length-prefixed (not null-terminated), so we must read
83+
// exactly `attr.length` bytes. `String(cString:)` would scan past the buffer into
84+
// adjacent memory and intermittently fail the comparison when that memory is non-zero.
8285
var attr = MARIADB_CONST_STRING()
8386
if mariadb_field_attr(&attr, fieldPtr, MARIADB_FIELD_ATTR_FORMAT_NAME) == 0,
8487
let str = attr.str, attr.length > 0,
85-
String(cString: str) == "json" {
88+
let value = String(data: Data(bytes: str, count: Int(attr.length)), encoding: .utf8),
89+
value == "json" {
8690
return "JSON"
8791
}
8892

0 commit comments

Comments
 (0)