diff --git a/lib/arel/visitors/sqlserver.rb b/lib/arel/visitors/sqlserver.rb index d230684e7..783d4f780 100644 --- a/lib/arel/visitors/sqlserver.rb +++ b/lib/arel/visitors/sqlserver.rb @@ -60,6 +60,9 @@ def visit_Arel_Nodes_SelectStatementDistinctNonPresentOrders(o, a) groups = core.groups orders = o.orders.uniq + # split out any projections that may have > 1 specified (comma-separated) + projections = projections.each_with_object(',').map(&:split).flatten + select_frags = projections.map do |x| frag = projection_to_sql_remove_distinct(x, core, a) # Remove the table specifier @@ -76,6 +79,9 @@ def visit_Arel_Nodes_SelectStatementDistinctNonPresentOrders(o, a) projection_list = projections.map { |x| projection_to_sql_remove_distinct(x, core, a) }.join(', ') + # strip aliases from projection list for PARTITION BY value expression + partitions = projection_list.gsub(/\s+AS\s+[^,]*/i, '') + sql = [ ('SELECT'), (visit(core.set_quantifier, a) if core.set_quantifier && !o.offset), @@ -90,7 +96,7 @@ def visit_Arel_Nodes_SelectStatementDistinctNonPresentOrders(o, a) ("ORDER BY #{orders.map { |x| visit(x, a) }.join(', ')}" unless orders.empty?), (') AS __order'), (', ROW_NUMBER() OVER ('), - ("PARTITION BY #{projection_list}" if !orders.empty?), + ("PARTITION BY #{partitions}" if !orders.empty?), (" ORDER BY #{orders.map { |x| visit(x, a) }.join(', ')}" unless orders.empty?), (') AS __joined_row_num') ].join('') diff --git a/test/cases/finder_test_sqlserver.rb b/test/cases/finder_test_sqlserver.rb index beb0162be..ae0971a67 100644 --- a/test/cases/finder_test_sqlserver.rb +++ b/test/cases/finder_test_sqlserver.rb @@ -34,6 +34,23 @@ def test_find_with_order_on_included_associations_with_construct_finder_sql_for_ ) end + def test_multiple_select_with_count_distinct_and_order + posts = Post.joins(:authors) + .select('COUNT(DISTINCT authors.id) as total') + .select('title as x, body as y') + .group(:title, :body) + .order(:title).to_a + + # quick sanity check, known number of records were returned + assert_equal(3, posts.size) + + # the defined aliases should be present + post = posts.first + assert_respond_to(post, :total) + assert_respond_to(post, :x) + assert_respond_to(post, :y) + end + def test_coerced_exists_does_not_select_columns_without_alias assert_sql(/SELECT TOP \(1\) 1 AS one FROM \[topics\]/i) do Topic.exists?