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

Relation#exists? and empty? return the wrong result when used with distinct() + offset() #35191

Closed
knu opened this issue Feb 8, 2019 · 1 comment

Comments

@knu
Copy link
Contributor

knu commented Feb 8, 2019

Steps to reproduce

# frozen_string_literal: true

require "bundler/inline"

gemfile(true) do
  source "https://rubygems.org"

  git_source(:github) { |repo| "https://github.com/#{repo}.git" }

  # Activate the gem you are reporting the issue against.
  gem "activerecord", "5.2.2"
  gem "sqlite3", "~> 1.3.6"
end

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

# This connection will do for database-independent bug reports.
ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: ":memory:")
ActiveRecord::Base.logger = Logger.new(STDOUT)

ActiveRecord::Schema.define do
  create_table :points, force: true do |t|
    t.integer :x
    t.integer :y
  end
end

class Point < ActiveRecord::Base
end

class BugTest < Minitest::Test
  def test_association_stuff
    Point.create!(x: 1, y: 1)
    Point.create!(x: 1, y: 2)

    relation = Point.select(:x).distinct.offset(1)

    assert_equal [
      true,
      false,
      0,
      []
    ], [
      relation.empty?, # Actual: false
      relation.exists?,  # Actual: true
      relation.count,
      relation.to_a
    ]
  end
end

Expected behavior

The test should pass.

Actual behavior

The test fails with empty? and exists?, due to the way Relation#exists? is implemented. It runs a query that looks like SELECT 1 AS one … LIMIT 1 to check for the existence of records, but DISTINCT is the crucial part of the original query because there is also OFFSET specified; the question is how many distinct records are there.

System configuration

Rails version: 5.2.2, 5.1.6.1, 6.0.0.beta1

Older versions may also be affected.

Ruby version: 2.6.1, 2.6.0, 2.5.3

kamipo added a commit to kamipo/rails that referenced this issue Feb 8, 2019
The `distinct` affects (reduces) rows of the result, so it is important
part when both `distinct` and `offset` are given.

Replacing SELECT clause to `1 AS one` and removing `distinct` and
`order` is just optimization for the `exists?`, we should not apply the
optimization for that case.

Fixes rails#35191.
@knu
Copy link
Contributor Author

knu commented Mar 29, 2019

Just confirmed the problem went away in Rails 5.2.3 and 6.0.0.beta3. 👍

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

No branches or pull requests

2 participants