Skip to content

driver-sql: the platform-objects schema does not sync onto MySQL — unbounded string fields become TEXT, which MySQL refuses to index #11374

Description

@os-sam

Found while measuring #10792 (driver parity). Filed unassigned.

What

Booting a stack whose default datasource is MySQL (client mysql2) fails schema-sync for every platform object that carries an indexed string field. driver-sql maps a string/text field with no maxLength to a MySQL TEXT column, and MySQL refuses a TEXT/BLOB column in a key without a prefix length:

alter table `sys_user` add unique `uniq_sys_user_phone_number`(`phone_number`)
-> BLOB/TEXT column 'phone_number' used in key specification without a key length

The base CREATE TABLE may succeed, but the ALTER TABLE ... ADD [UNIQUE] INDEX fails, so the table lands without its indexes and the object stays registered-but-broken (the driver logs Schema sync FAILED for object ... its table/columns were NOT created or altered). Downstream effect: the dev-admin seed never lands, and the first sign-in returns 401 INVALID_EMAIL_OR_PASSWORD on a fresh MySQL database.

Evidence

Measured against a real MySQL 8.0.46 server (a minimal ObjectQL + DefaultDatasourcePlugin(driver: 'mysql') + PlatformObjects + Auth boot). ~30 platform objects failed schema-sync. A sample of the offending columns (all in a unique or ordinary index):

  • sys_user.phone_number (unique)
  • sys_session.token (unique)
  • sys_organization.slug (unique)
  • sys_api_key.key (unique), sys_device_code.device_code (unique)
  • sys_metadata unique (type, name, organization_id, package_id)
  • sys_user_preference unique (organization_id, user_id, key)
  • sys_oauth_*client_id / token / provider_id, sys_scim_provider, sys_team.name, etc.

The identical schema syncs cleanly on Postgres 16 (Postgres indexes text freely) and on SQLite (no such restriction). driver-sql stores string/text/textarea/html as TEXT (see the createColumn comment in sql-driver.ts, "Everything else createColumn stores as TEXT").

Why it matters (declared ≠ enforced)

MySQL is a declared-supported driver — createDefaultDatasourceDriverFactory maps mysql / mysql2@objectstack/driver-sql. But the CI Temporal Conformance (live PG + MySQL) job exercises only driver-sql's own suites, which build their tables with explicit knex .string() (VARCHAR); it never runs the platform-objects metadatasyncSchema on MySQL. So this path is untested there and is currently broken end-to-end: a MySQL deployment cannot stand up its own platform schema.

Direction (for triage — not prescribing a fix)

Two shapes, contract-first:

  • an indexed string column should be emitted as VARCHAR(n) on MySQL (a bounded length MySQL can index), rather than TEXT; and/or
  • the platform objects' indexed string fields should declare a maxLength so the driver has a bound to emit.

Repro

Branch claude/issue-10792-remove-user-txn-driver-parity carries the boot probe packages/verify/src/issue-10792-driver-parity.probe.test.ts; run it with PROBE_DIALECT=mysql and OS_TEST_MYSQL_URL pointed at a MySQL 8.0 server. The schema-sync errors appear during beforeAll.

Generated by Claude Code

Metadata

Metadata

Assignees

Labels

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions