8000 feat(mysql): type vector columns and parameters as number[] by colinhacks · Pull Request #8 · colinhacks/reylo · GitHub
[go: up one dir, main page]

Skip to content

feat(mysql): type vector columns and parameters as number[] - #8

Merged
colinhacks merged 1 commit into
mainfrom
mysql-vector
Oct 22, 2026
Merged

colinhacks merged 1 commit into
mainfrom
mysql-vector

Conversation

@colinhacks
Copy link
Copy Markdown
Owner

MySQL 9's VECTOR (protocol type 242) was typed unknown, so a number[] parameter type-checked and then failed at run time on every driver.

What changes

  • Engine (engine/mysql/src/mysql.rs): type 242 is an array of float4 whose elements are never null, for a column and for a ? the prepare types from its context. Each such ? is sent as to_vector(?), and the map back to the author's text keeps the placeholder's place.
  • Run time: a vector column is a number[] on every driver that reads one. mysql2 decodes the floats itself; mariadb and PlanetScale hand over the little-endian bytes, which src/values.ts reads. A parameter is bound as the JSON text of its floats. A non-number element, NaN or an infinity is refused before the statement runs, with the parameter named.
  • Docs: a Vectors section and table rows on the MySQL page, and a row in the main page's types table.
  • packages/mysql/engine.wasm rebuilt.

Why text and not bytes

All three driver paths bind bytes for an insert. But mariadb and PlanetScale write values into the statement's text, where bytes are a binary string, and MySQL refuses one beside = with a vector (Incorrect arguments to =). to_vector('[…]') works in every position on every driver.

Verified

  • On MySQL 9.7.2 and 26.7.0, with mysql2 3.24.4 and mariadb 3.5.4: a typed .sql import type-checks as { id: number; v: number[]; vn: number[] | null }, and a string element is a type error. Inserts, where v = :v, NULL vectors and reads all round-trip, and the stored values match vector_to_string.
  • Bun.sql 1.4.3 can't read a VECTOR at all (ERR_MYSQL_UNSUPPORTED_COLUMN_TYPE, and the connection closes); the docs say so.
  • Local gates: engine tests, wasm fingerprints, the oracle, the typecheck, loader tests (192, none skipped), the package, the site and the MySQL lab pass. The Postgres driver-matrix jobs differ from RESULTS.md only in the 24 S11 round-trip rows that main already fails.
  • CI's MySQL is 8.4, which has no VECTOR, so CI covers this through the engine and loader unit tests.

A MySQL 9 VECTOR was unknown, so a number[] parameter type-checked and
then failed on every driver. A parameter is now wrapped in to_vector()
and bound as the text of its floats, which also works on the drivers
that write values into the statement's text, where bytes compared with
a vector are refused.
Copilot AI balanced review requested due to automatic review settings October 22, 2026 16:41
Copilot AI left a comment
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@vercel
vercel Bot commented Oct 22, 2026 •
Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
reylo Ready Ready Preview Oct 22, 2026 4:42pm UTC

Request Review

@pullfrog pullfrog Bot left a comment
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ No new issues found.

Reviewed changes

This review covers the first pass over MySQL 9 VECTOR support: typing, binding, decoding and docs.

  • Engine typing: column_type maps protocol type 242 to an array of non-null float4, for columns and for ? parameters typed by context.
  • to_vector(?) rewrite: vectors_as_text wraps each 242-typed ? after settle and the cardinality pass have used the unwrapped text. Its spans line up with raw.params, as settle already assumes. The structured-parameter span remap in engine/core/src/structured.rs works from span deltas, so it absorbs the added length.
  • Parameter encoding: on MySQL, encode sends an array parameter as its JSON text through vectorText. VECTOR is the only Type::Array the MySQL engine produces, so no other parameter takes this path. NaN, the infinities and non-numbers are refused, and null elements are already caught by nullElement. MySQL's STRING_TO_VECTOR accepts scientific notation, so JSON.stringify's 1e-7 form is safe.
  • Decoding: byKind("float[]") routes vector columns through coerce. A Uint8Array (mariadb's, and PlanetScale's via bytesOf for charset 63) is read as little-endian float32s, honouring byteOffset. mysql2's decoded arrays and Bun.sql's Postgres Float32Array go down the existing paths, unchanged.
  • Docs: the VECTOR rows, a Vectors section and the Bun.sql limitation on the MySQL page, plus a row in the shared data types table.

Pullfrog  | View workflow run | Using claude-opus-5-5 | 𝕏

@colinhacks
colinhacks merged commit 9aaf203 into main Oct 22, 2026
4 checks passed
@colinhacks
colinhacks deleted the mysql-vector branch October 22, 2026 16:45
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

0