Closed
Description
Issue
Doing the following query Model.distinct.to_sql returns the following query SELECT DISTINCT TOP(1) 1 AS [one] FROM [models]
This happens when running with mssql on Windows with arel_extensions (https://github.com/Faveod/arel-extensions).
The issue is caused by this piece of code:
def distinct_One_As_One_Is_So_Not_Fetch o
core = o.cores.first
distinct = Nodes::Distinct === core.set_quantifier
oneasone = core.projections.all? { |x| x == ActiveRecord::FinderMethods::ONE_AS_ONE }
limitone = [nil, 0, 1].include? node_value(o.limit)
if distinct && oneasone && limitone && !o.offset
core.projections = [Arel.sql("TOP(1) 1 AS [one]")]
o.limit = nil
end
end
interacting with the overriding of the == operator from ArelExtensions:
def ==(other)
Arel::Nodes::Equality.new self, Arel::Nodes.build_quoted(other, self)
end
so when it's running the .all? block, x == ActiveRecord::FinderMethods::ONE_AS_ONE
creates a query from the operator, which is truthy no matter what.
Expected behavior
Should return all distinct models
Actual behavior
Returns one model with its only attribute being 1
How to reproduce
require "bundler/inline"
gemfile(true) do
source "https://rubygems.org"
gem "tiny_tds", "2.1.3.pre"
gem "rails", "6.0.4.1"
gem "activerecord", "6.0.4.1"
gem "activerecord-sqlserver-adapter", "6.0.2"
gem "arel_extensions", "2.1.0"
end
require "active_record"
require "minitest/autorun"
require "logger"
ENV["RAILS_ENV"] = "production"
ActiveRecord::Base.configurations = {
"test": {
adapter: "sqlserver",
timeout: 5000,
pool: 100,
encoding: "utf8",
database: "test_database",
username: "admin",
password: "admin",
host: "localhost",
port: 1433,
}
}
ActiveRecord::Base.establish_connection
ActiveRecord::Base.logger = Logger.new(STDOUT)
ActiveRecord::Schema.define do
drop_table :machines rescue nil
drop_table :capabilities rescue nil
create_table :machines, force: true do |t|
t.string :sn
t.timestamps
end
create_table :capabilities, force: true do |t|
t.string :name
t.belongs_to :machine
t.timestamps
end
end
class Machine < ActiveRecord::Base
has_many :capabilities
end
class Capability < ActiveRecord::Base
has_one :machine
end
class TestEerValueTest < Minitest::Test
def setup
capabilities = [
{name: 'cap_1'},
{name: 'cap_2'},
{name: 'cap_3'},
{name: 'cap_4'}
]
machines = [
{
sn: 'test_1',
capabilities: %w[cap_1 cap_2]
},
{
name: 'test_2',
capabilities: %w[cap_2 cap_3]
},
{
name: 'test_3',
capabilities: %w[cap_4]
}
]
Capability.create!(capabilities)
machines.each do |machine|
m = Machine.new(sn: machine[:sn])
m.capabilities = Capability.where(name: machine[:capabilities])
m.save!
end
end
def test_count
assert_equal 'SELECT DISTINCT TOP(1) 1 AS [one] FROM [machines]', Machine.distinct.to_sql
end
end
Details
- Rails version:
6.0.4.1
- SQL Server adapter version:
6.0.2
- TinyTDS version:
2.1.3.pre
Metadata
Metadata
Assignees
Labels
No labels