Skip to content
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

Rails 6.0 switches order of joined queries when combining includes and joins (causing errors) #37133

Closed
codeodor opened this issue Sep 4, 2019 · 1 comment · Fixed by #37235
Assignees

Comments

@codeodor
Copy link
Contributor

codeodor commented Sep 4, 2019

I think this is due to / related to #36834

Steps to reproduce

I used @eileencodes script from the pull request above, modified to illustrate my issue:

require "active_record"
require "minitest/autorun"
require "logger"

ActiveRecord::Base.establish_connection({ "adapter" => "mysql2", "username" => "root", "database" => "activerecord_unittest" })
ActiveRecord::Base.logger = Logger.new(STDOUT)

ActiveRecord::Schema.define do
  create_table :events, force: true do |t|
    t.integer :project_id
  end

  create_table :event_details, force: true do |t|
    t.integer :event_id
  end

  create_table :projects, force: true do |t|
  end
end

class Event < ActiveRecord::Base
  has_one :event_detail
  belongs_to :project

  def self.visible_in_timeline_for
    events_for
  end

  scope :events_for, -> {
    join_project.
    join_event_detail
  }

  scope :join_project, -> {
    join_event_detail.joins(:project)
  }

  scope :join_event_detail, -> {
    joins(<<~SQL)
    INNER JOIN `event_details`
    ON `event_details`.`event_id` = `events`.`id`
    SQL
  }
end

class EventDetail < ActiveRecord::Base
  belongs_to :event
end

class Project < ActiveRecord::Base
  has_many :events
end

class BugTest < Minitest::Test
  def test_scoped_joins
    p ActiveRecord::VERSION::STRING
    # throws ActiveRecord::StatementInvalid: Mysql2::Error: Unknown column 'event_details.id' in 'on clause'
    p Event.includes(:event_detail).references(:event_detail).joins("left outer join projects on projects.id = events.project_id and event_details.id = 0").where("event_details.id = 1")
  end
end

Expected behavior

The query should work as it did in Rails 5.2.3 by having the first join be the includes/references join.

Actual behavior

The query puts the includes/references join at the end, so that the joins that reference it fail.

System configuration

Rails version: 6.0.0

Ruby version: 2.5.0

cc @kamipo (as author of the related pull request)

@codeodor codeodor changed the title Rails 6.0 switches order of joined queries when combining includes and joins Rails 6.0 switches order of joined queries when combining includes and joins (causing errors) Sep 4, 2019
@kamipo kamipo self-assigned this Sep 5, 2019
kamipo added a commit to kamipo/rails that referenced this issue Sep 18, 2019
If a relation has eager_load and string joins only, string joins will be
regarded as leading joins unlike before, due to rails#36805.

To maintain that joining order as before, check eager loading join
first before string joins.

Fixes rails#37133.
@codeodor
Copy link
Contributor Author

🎉

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants