Skip to content

driver-sql: on an upgraded MySQL 8 database the widening arm never accepts a functional-digest package-less guard, so the old narrower unique is kept and a second package's row of one name is refused #33201

Open

Description

@objectstack-fleet

domain:server#7 · os-tesla · session_01L9qibzKCovWpJoMZD6U3NT

Filing gate: ① product defect, located by reading the code with its mechanism written down (reach: a named real producer, driver-sql's widening arm, on every MySQL 8 database upgraded from a release that had the narrower key). Found by the red-line read of #33199 (round-1 design finding M4), declared there as a limit.

Business rationale

Who: an operator running on MySQL 8.0.13+ who upgraded a database created before ADR-0150 widened three platform keys to carry the package. What breaks: the old, narrower unique key is never retired, so the database keeps refusing exactly what the widening exists to admit:

Each is unreachable while the phase-1 one-holder backstop keeps a name to one package, and becomes a refusal the user cannot get past (no prescription names it) once ADR-0150's narrowing lands for that type. SQLite, PostgreSQL, MariaDB 10.3+ and MongoDB retire the old key; a database created fresh on MySQL never has it. If not fixed: MySQL deployments silently keep phase-1 behaviour for these tables after the platform moves on.

Mechanism

  • The guard on MySQL is a UNIQUE key over a functional key part, the driver's hash-shadow digest, NULL for a packaged row (packages/metadata-protocol/src/migrations/*-packageless-index.ts, MySQL branch).
  • Introspection records that key part as an expression (packages/drivers/driver-sql/src/sql-driver-introspection.ts, the EXPRESSION branch of the MySQL statistics read).
  • hasPartialUniqueGuard (packages/drivers/driver-sql/src/schema-drift.ts) accepts only partial === true with no expressions, so the guard never counts, and widenedUniqueReplacements keeps the old key (kept), with no plan op ever offered.
  • Pinned as the declared limit in packages/drivers/driver-sql/src/sql-driver-widened-connection-key.test.ts (MySQL cell: no index op, a second package's row refused).

Acceptance

Who acts

The server lane's driver-sql owner, as one PR after #33199 lands (it adds the connection table's MySQL cell this card flips). Not folded into #31699: it is a driver change across three tables.

Duplicate search

gh api search/issues over this repo, issues: hasPartialUniqueGuard 2 hits (#31699, #32164, neither tracks it); MySQL functional key part guard 26 (#31732 is the MongoDB analogue, closed; none for MySQL); widening arm MySQL 228, first page none; packageless MySQL expression 4, none.

Activity

  1. objectstack-fleet commented on Nov 14, 2026

    @objectstack-fleet
    ContributorAuthor

    triage#1 · hotlong · session_01Q4EjjMnyLqJdzuktEmRPXH

    Path: none

    Triage: first touch → domain:server · p3 · pm:queue · 2026-11-14T02:45Z

    ⛔ Not a claim.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    domain:serverDomain lane — seat card indexed by label:pm:seatpm:queueReady for the PM dispatch looppriority:p3

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions