Skip to content

fix(database): qualify orderBy fields against the base table - #2306

Open
radoslav-grencik wants to merge 1 commit into
tempestphp:3.xfrom
radoslav-grencik:fix/database-orderby-table-qualification
Open

radoslav-grencik wants to merge 1 commit into
tempestphp:3.xfrom
radoslav-grencik:fix/database-orderby-table-qualification

Conversation

@radoslav-grencik

Copy link
Copy Markdown
Contributor

Summary

SelectQueryBuilder::orderBy('name') rendered ORDER BY `name` — an unqualified column name. As soon as the query joins another table that shares the column (e.g. authors JOIN publishers where both have name), SQLite raises:

SQLSTATE[HY000]: General error: 1 ambiguous column name: name

SQLite resolves an ambiguous bare column by the first table in the FROM clause, which makes ordering dependent on join order rather than the base model's column — a latent correctness bug even where it does not error.

Change

packages/database/src/Builder/QueryBuilders/SelectQueryBuilder.php — orderBy() now qualifies bare fields with the base model's table name, leaving dotted paths untouched:

if (! str_contains($field, '.')) {
    $field = $this->model->getTableName() . '.' . $field;
}

$this->select->orderBy[] = new OrderByStatement(field: $field, direction: $direction);
  • orderBy('name') → ORDER BY `authors`.`name` — resolved against the base table.
  • orderBy('publishers.name') → ORDER BY `publishers`.`name` — a dotted path is a relation column, passed through unchanged so joined-table ordering keeps working.
  • orderByRaw() shorthand and raw fragments are untouched.

Why qualify at the builder level

OrderByStatement cannot distinguish "bare base column" from "already-qualified column" — it renders a quoted identifier either way, and quoting a dotted string twice (`authors.name`) would break every call site. The base-table qualification belongs where the model context is known: SelectQueryBuilder.

Tests

tests/Integration/Database/Builder/SelectQueryBuilderTest.php:

  • order_by_sql_generation — updated to the new qualified SQL (ORDER BY `books`.`title` ) for ASC and DESC; dotted-field generation asserted unchanged.
  • order_by_qualifies_bare_field_with_base_table_and_leaves_dotted_fields_alone — pins authors.name vs publishers.name compilation side by side.
  • order_by_with_joined_table_uses_base_table_column_for_ambiguous_bare_field — regression: authors JOIN publishers (both with a name column), orderBy('name') now returns Alpha Author, Beta Author instead of raising the ambiguous-column error.

@github-actions

Copy link
Copy Markdown

Benchmark Results

Comparison of fix/database-orderby-table-qualification against 3.x (0f478fb487e12a5891738a15a1663fa44c47295b).

Open to see the benchmark results

No benchmark changes above ±5%.

Generated by phpbench against commit 47ff16f

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