Skip to content

fix(mysql): type untyped expression columns by value (SELECT 1 gone-away) - #8

Merged
luthermonson merged 1 commit into
mainfrom
fix/expression-column-type
Jul 11, 2026
Merged

fix(mysql): type untyped expression columns by value (SELECT 1 gone-away)#8
luthermonson merged 1 commit into
mainfrom
fix/expression-column-type

Conversation

@luthermonson

Copy link
Copy Markdown
Contributor

Summary

  • A prepared SELECT 1 (or any table-less expression: SELECT a+b, SELECT 7 AS x) dropped the connection with 2006 server has gone away.
  • Root cause: SQLite gives expression columns no declared type → decltype = Nonesqlite_to_mysql_column_type fell back to VAR_STRING. But the row writer emits each value natively (integer → LONGLONG), and opensrv's binary protocol rejects the declared/actual mismatch (tried to use 1 as MYSQL_TYPE_VAR_STRING) and closes the socket.
  • Fix: for columns with no decltype, derive the wire type from the first non-NULL value (mysql_type_for_value). Declared-type columns unchanged; all-NULL/empty columns stay VAR_STRING.

Test

  • New regression test prepared_select_expression_no_table (SELECT 1, multi-column expression, aliased expression) — fails before, passes after.
  • Full mysql_e2e suite: 24 passed. clippy -D warnings + fmt clean.

Found during ePHPm's DB verification. Impact: bit clients that disable PDO prepare-emulation (Doctrine-style) and issue a real-prepared expression query; direct COM_QUERY was unaffected. Not a v0.4.1 blocker (table queries work) but a clean correctness fix for the follow-up.

A prepared `SELECT 1` (or any table-less expression: `SELECT a+b`,
`SELECT 7 AS x`) dropped the connection with "2006 server has gone
away". SQLite gives expression columns no declared type, so decltype
is None and sqlite_to_mysql_column_type fell back to VAR_STRING — but
the row writer emits each value natively (an integer as LONGLONG), and
opensrv's binary protocol rejects the declared/actual mismatch
("tried to use 1 as MYSQL_TYPE_VAR_STRING") and closes the socket.

Fix: for columns with no decltype, derive the wire type from the first
non-NULL value in the result set (mysql_type_for_value), so the
declared column type matches how the value is encoded. Declared-type
columns are unchanged; all-NULL/empty columns stay VAR_STRING (NULL is
valid against any type).

Regression test prepared_select_expression_no_table covers SELECT 1,
a multi-column expression select, and an aliased expression. Found via
ePHPm DB probing; only bit clients that disable PDO prepare-emulation
(Doctrine-style) and issue a real-prepared expression query.
@luthermonson
luthermonson merged commit fbbfe8d into main Jul 11, 2026
3 checks passed
@luthermonson
luthermonson deleted the fix/expression-column-type branch July 11, 2026 03:21
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