fix(mysql): qualify column reference in NULLS LAST CASE simulation#7641
Open
brdbry wants to merge 1 commit into
Open
fix(mysql): qualify column reference in NULLS LAST CASE simulation#7641brdbry wants to merge 1 commit into
brdbry wants to merge 1 commit into
Conversation
… avoid 1052 ambiguity When transpiling ORDER BY <col> from a NULLS-LAST default dialect (e.g. DuckDB) to MySQL, the simulated CASE WHEN <col> IS NULL THEN 1 ELSE 0 END, <col> inlines the raw expression. Inside the CASE, MySQL does not apply ORDER BY's alias-first column resolution, so unqualified references collide with same-named columns in joined base tables (error 1052). Resolve the column against the enclosing SELECT projection and substitute the qualified source where one uniquely exists.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
When transpiling
ORDER BY <col>from aNULL_ORDERING = "nulls_are_last"source dialect (e.g. DuckDB) into MySQL, the generator emits aCASE WHEN <col> IS NULL THEN 1 ELSE 0 END, <col>shim to simulateNULLS LAST(MySQL has no nativeNULLS FIRST/LASTsyntax). The shim inlines the rawORDER BYexpression verbatim — typically a bare column name.That's fine for a single-table query, but in a multi-table
FROMwhere the same unqualified column name exists in more than one table, MySQL raises:…even when there is an unambiguous
SELECT-list projection. MySQL'sORDER BYdoes apply alias-first column resolution against theSELECTlist — but inside theCASEexpression inORDER BY, that alias-first rule does not apply. The bare reference falls through to base-table resolution and collides.Reproducer
Output today (rejected by MySQL 8.0):
After this PR:
Verified against a running MySQL 8.0 container: the pre-fix SQL errors with
1052, the post-fix SQL succeeds.Fix
New helper
Generator._qualified_for_null_ordering_simulationon the base generator walks from theOrderednode to its enclosingSelectand looks for a single qualified-column projection whoseoutput_namematches the bareORDER BYcolumn. If exactly one is found (whether the projection is plaine.employee_idore.employee_id AS <alias>), the simulation substitutes that qualified column inside both theCASEand the trailing sort key. In every other case (already-qualifiedORDER BY, positional/ordinalORDER BY, expressionORDER BY, no enclosingSelect, ambiguous projection match, inside a window function), the helper returnsNoneand the existing behaviour is preserved.Single change:
sqlglot/generator.py.Test
Added
TestMySQL.test_null_ordering_simulation_qualifies_ambiguous_columnsintests/dialects/test_mysql.pycovering three scenarios: the reproducer (multi-tableLEFT JOIN, unqualifiedORDER BY), an aliased projection (SELECT e.employee_id AS emp ... ORDER BY emp), and an already-qualifiedORDER BY(no change in output).Full suite passes locally (
1107 passed, 18002 subtests passed).Scope / out-of-scope
The fix lives in the base
Generator.ordered_sqlsimulation branch, so any dialect withNULL_ORDERING_SUPPORTED is None(currently MySQL and MSSQL/TSQL) benefits in one place. I've only added a MySQL-focused test and PR title because the reported bug is specifically the MySQL1052symptom; happy to broaden the test coverage to TSQL or any other affected dialect in a follow-up if maintainers want it.The fix is deliberately conservative: it only qualifies when a single qualified-column projection unambiguously matches, and never strips or rewrites already-qualified
ORDER BYreferences. I did not modify the parser to track explicit-vs-implicitNULLordering onOrderednodes (broader ripple) or add any per-dialect toggle.Context
Same area of the codebase as #6655 (UPDATE … FROM → UPDATE … JOIN translation) which I authored earlier this year.