Skip to content

find_each broken with Arel condition #55801

@JochenLutz

Description

@JochenLutz

Steps to reproduce

Create an ActiveRecord scope using an Arel::Nodes::Or as a condition to #where.

Post.where(Arel::Nodes::Or.new([Post.arel_table[:author_id].eq(1), Post.arel_table[:author_id].eq(2)])
).find_each(batch_size: 10) { [] }

See gist for a complete working example.

The linked gist also contains two examples where #find_each works as expected — one when using an SQL literal as a condition to #where, the other with an Arel::Nodes::Grouping as outer-most node of the condition.

Expected behavior

find_each correctly loops the scope.

Actual behavior

ActiveRecord::Batches#batch_on_unloaded_relation generates the invalid SQL […] author_id = 1 OR author_id = 2 AND id IN (1, 2). By SQL standard, this is parsed as author_id = 1 OR (author_id = 2 AND id IN (1, 2)) instead of the expected (author_id = 1 OR author_id = 2) AND id IN (1, 2).

With more data, this leads to an endless loop, because the list of ids does not change.

System configuration

Rails version: 8.0.2.1 (also tested with 8.0.3 with same result)

Ruby version: 3.4.2

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions