Skip to content

fix(schema): encode msgpack fields with the dialect binary literal (#1219) - #1421

Open
ChrisJr404 wants to merge 2 commits into
uptrace:masterfrom
ChrisJr404:fix-msgpack-dialect-bytes
Open

fix(schema): encode msgpack fields with the dialect binary literal (#1219)#1421
ChrisJr404 wants to merge 2 commits into
uptrace:masterfrom
ChrisJr404:fix-msgpack-dialect-bytes

Conversation

@ChrisJr404

Copy link
Copy Markdown

Describe the pull request

Fields tagged with bun:",msgpack" did not round-trip on SQLite (and MySQL) — only on PostgreSQL.

appendMsgpack encoded the value straight through internal.HexEncoder, which always emits PostgreSQL's '\x...' bytea literal. SQLite and MySQL don't recognize that syntax, so the payload was stored verbatim as text and reading the row back failed with a msgpack decode error:

sql: Scan error on column index 1, name "encoded": msgpack: unexpected code=5c decoding map length

(0x5c is the leading \ of the \x prefix that got stored as data.)

The fix encodes the msgpack payload into a buffer and delegates to Dialect.AppendBytes, the same routine bun already uses for regular []byte columns. Each dialect now emits its own binary literal — '\x...' for PostgreSQL, X'...' for SQLite and MySQL. The PostgreSQL output is byte-for-byte identical to before, so existing behavior is unchanged.

internal.HexEncoder was the only consumer of that code and is now unused, so it's removed.

Link to the issue: #1219

Tests

  • internal/dbtest: TestMsgpackRoundTrip — create/insert/select round-trip of a ,msgpack field, run for every dialect via testEachDB (verified green on SQLite locally).
  • schema: TestAppendMsgpack_DialectSpecificLiteral — asserts the appended literal matches the dialect's AppendBytes and that PostgreSQL still produces the '\x...' form.

Checklist

  • I agree to follow the Code of Conduct by submitting this pull request.
  • I have read and acknowledge the Contributing guide.
  • I have added test cases to cover the new code.

The msgpack field appender always emitted the encoded value using
PostgreSQL's '\x...' bytea literal, regardless of the target dialect.
SQLite and MySQL do not recognize that syntax and stored the payload
verbatim as text, so reading the row back failed with a msgpack decode
error (e.g. "unexpected code=5c decoding map length").

Encode into a buffer and delegate to Dialect.AppendBytes so each dialect
emits its own binary literal ('\x...' for PostgreSQL, X'...' for SQLite
and MySQL). The PostgreSQL output is byte-for-byte identical to before.

Fixes uptrace#1219
Emitting the dialect binary literal was only half of it. The column type
was still derived from the field's Go type, so a msgpack struct became a
JSON/text column (JSONB on Postgres, JSON on MySQL, NVARCHAR on MSSQL).
Inserting the binary literal into those columns fails on every strict
database, which is why TestMsgpackRoundTrip was red for pg, mysql, mariadb
and mssql.

Force msgpack fields to the Blob type so each dialect creates a real
binary column (bytea, blob, varbinary) that matches the literal we append.
Sqlite already passed and still does.
@ChrisJr404

Copy link
Copy Markdown
Author

The round-trip test was still failing on pg, mysql, mariadb and mssql because the value literal was only half the problem. A msgpack struct was still mapped to a JSON/text column, so inserting the binary literal got rejected. Pushed a follow-up that forces msgpack fields to a Blob column (bytea, blob, varbinary), so the column type matches the literal. Verified the sqlite round-trip passes locally and confirmed the generated DDL is a binary column on all four dialects.

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.

1 participant