0.1.15: the pagination rewrite now runs on MySQL
The audit that found this was the obvious one the test suite had never done: take the SQL the tool emits and run it. SIA006's deferred join for an unaliased deep-page query failed on a live MySQL 8.0.46 with ERROR 1052: Column 'id' in on clause is ambiguous - the derived table exposes id too - and it had quietly widened a three-column projection to SELECT *. The rewrite now carries its own alias, and it is withdrawn whenever the projection cannot be carried over honestly.
0.1.15 — 2026-09-22
Fixed
- SIA006's deferred-join rewrite did not run. For a deep page on a table the
query did not alias —SELECT id, user_id, amount FROM orders WHERE … LIMIT 100000, 20—
the emitted SQL was
SELECT * FROM (SELECTidFROMorders… ) AS page JOIN orders ONid= page.id``,
and MySQL answeredERROR 1052 (23000): Column 'id' in on clause is ambiguous:
the derived table exposes `id` too. The same statement also turned a three-column
projection into `SELECT *`, so even if it had run it would have handed the caller
columns nothing asked for. Found by executing the tool's own output against a live
8.0.46, which is now the standard way this project audits a rewrite.
The rewrite always introduces its own alias (`t`) and qualifies the join, the
projection and the outer sort through it. - A rewrite that cannot be faithful is withdrawn instead of approximated. The
projection is rebuilt column by column only when it is a column list:SELECT *
becomest.*; a computed value, anASrename, a barex yrename,DISTINCT
or a sort key that cannot be re-qualified all produce norewritefield, with the
template and the reason in the message (both languages).SELECT amount + 0was
the case that made this a parse-level flag rather than a guess: the column inside
the expression was being collected as if the projection were that column, which
would have quietly changed a returned value.
Added
ParsedQuery.selectPlain/selectDistinct, so a rule can tell "a list of columns
I can carry over" from "a projection I must not rebuild".
Verified
CREATE TEMPORARY TABLE … AS <rewrite> against the live 8.0.46 demo database: the
rewrite runs, returns the same 20 rows and the same three columns as the original,
and the outer ORDER BY is preserved. Re-running the whole pipeline after applying
the generated migration produced no repeated DDL. 290 tests pass.