Skip to content

[12.x] Fix: Make Paginated Queries Consistent Across Pages #55176

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Mar 27, 2025

Conversation

tomchkk
Copy link
Contributor

@tomchkk tomchkk commented Mar 26, 2025

Problem

When using Illuminate\Database\Query\Builder methods orderedChunkById and orderedLazyById without specifying $column and $alias property values, where the query includes a join on another table, the query for the first page may work as expected while the query for subsequent pages may throw Illuminate\Database\QueryException with the following message:

SQLSTATE[23000]: Integrity constraint violation: 1052 Column 'id' in where clause is ambiguous...

The cause of this issue is that the query for the first page doesn't include a where clause for the id column, but the subsequent queries do. So it may not be clear that the column is ambiguous until at least the query for the second page is run.

-- page 1 passes
select * from users join profiles on profiles.user_id = users.id order by id asc limit 15
-- page 2 fails due to ambiguity in where clause
select * from users join profiles on profiles.user_id = users.id where id > 15 order by id asc limit 15

Impact

In non-production environments, since it's common to encounter a smaller dataset, use of these methods without the mentioned properties may work without a problem. However, when releasing a feature into an environment with a large enough dataset to cause the paged query to run more than once, suddenly a working, tested change may fail.

Solution

The PR modifies the forPageBeforeId and forPageAfterId methods in Illuminate\Database\Query\Builder to always include a where clause on the given $column property; specifically, if property $lastId evaluates to null, the clause $this->whereNotNull($column) is added.

-- page 1 fails due to ambiguity in where clause
select * from users join profiles on profiles.user_id = users.id where id is not null order by id asc limit 15
-- page 2 fails due to ambiguity in where clause
select * from users join profiles on profiles.user_id = users.id where id > 15 order by id asc limit 15

Benefits

The benefit of always including a where clause on the given column name is that any ambiguity in the query is immediately evident, even when used on a small dataset.

@taylorotwell taylorotwell merged commit 16ad066 into laravel:12.x Mar 27, 2025
41 checks passed
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.

2 participants