Skip to content

v2.9.16-beta

Pre-release
Pre-release

Choose a tag to compare

@github-actions github-actions released this 02 Sep 14:13
· 1 commit to master since this release
2d871bc

MySQL client compatibility release. Found by driving LLDAP 0.6.3 (Rust, sqlx + sea-orm) against a live Marmot node and auditing the paths it exercised. 21 defects fixed, each covered by tests that fail on the prior code.

Data correctness

  • Tables with no declared PRIMARY KEY could not replicate UPDATE/DELETE. Rowid is now the replicated identity.
  • BLOB columns silently became TEXT on every replica — would have corrupted password hashes and UUID columns. Storage class is now decided at capture time from column affinity.
  • Segfault on DML against tables with VIRTUAL generated columns. Capture now refuses these tables cleanly.
  • PRAGMA table_info renumbers column ids when hidden columns exist, silently breaking primary-key indexing. Now uses true table_xinfo positions.
  • A forwarded-session eviction racing a slow COMMIT could discard a write while reporting success. Eviction now serializes against in-flight statements, and COMMIT fails loudly if its state disappears.
  • Schema-reload failures after DDL are no longer swallowed; count mismatches fail loud instead of truncating.

Interactive transactions

DML inside BEGIN...COMMIT now executes immediately against a pinned SQLite transaction instead of being buffered until COMMIT behind a fabricated result. Clients get real rows-affected and last_insert_id, and can read their own uncommitted writes. CDC is captured incrementally and replayed through the existing 2PC path.

New transaction.ddl_implicit_commit (default true): DDL commits the open transaction, matching MySQL.

SQL transpilation

  • Partially-parsed DDL is rejected instead of being forwarded truncated into 2PC.
  • HAVING was being emitted as WHERE, breaking every GROUP BY ... HAVING query.
  • Index DDL unified: ADD CONSTRAINT UNIQUE, ADD INDEX, ADD UNIQUE and standalone CREATE [UNIQUE] INDEX all emit valid SQLite; DROP INDEX ... ON is handled.
  • CHARACTER SET/COLLATE stripped on ALTER TABLE ADD/MODIFY/CHANGE COLUMN.

MySQL wire protocol

  • COM_STMT_PREPARE reported zero columns — sqlx builds its column index from that response, so prepared queries could not find their columns. This was the cause of the originally reported client panic.
  • Column types inferred from data and declared types instead of always VAR_STRING; correct time.Time and binary DATETIME encoding.
  • SERVER_STATUS_IN_TRANS is now reported.
  • COM_STMT_SEND_LONG_DATA and COM_STMT_RESET implemented; previously they drew an ERR packet that desynced the connection.
  • Unsigned parameter flag honored, with a proper out-of-range error above MaxInt64.

Parameter handling

Prepared statements against auto-increment tables failed with not enough args to execute query: want 6 got 5, because literal extraction turns the injected id into a placeholder while execution sites used either wire params or extracted params, never both. Parameters are now merged positionally by per-placeholder provenance.

Upgrading

No migration required. transaction.ddl_implicit_commit defaults to true (MySQL-compatible); set it to false to keep DDL inside the transaction and replicate it atomically, accepting that DML in that transaction cannot see the pending schema change.

Known limitation

Generated AUTO_INCREMENT ids are 53-bit (default) or 64-bit and overflow applications that model ids as 32-bit integers — see #170.