@@ -21,14 +21,16 @@ def eql?(other)
2121 end
2222
2323 class SelectManager < Arel ::TreeManager
24-
24+
25+ AR_CA_SQLSA_NAME = 'ActiveRecord::ConnectionAdapters::SQLServerAdapter' . freeze
26+
2527 # Getting real Ordering objects is very important for us. We need to be able to call #uniq on
2628 # a colleciton of them reliably as well as using their true object attributes to mutate them
2729 # to grouping objects for the inner sql during a select statment with an offset/rownumber. So this
2830 # is here till ActiveRecord & ARel does this for us instead of using SqlLiteral objects.
2931 alias :order_without_sqlserver :order
3032 def order ( *expr )
31- return order_without_sqlserver ( *expr ) unless Arel :: Visitors :: SQLServer === @visitor
33+ return order_without_sqlserver ( *expr ) unless engine_activerecord_sqlserver_adapter?
3234 @ast . orders . concat ( expr . map { |x |
3335 case x
3436 when Arel ::Attributes ::Attribute
@@ -55,7 +57,7 @@ def order(*expr)
5557 # custom string hints down. See the visit_Arel_Nodes_LockWithSQLServer delegation method.
5658 alias :lock_without_sqlserver :lock
5759 def lock ( locking = true )
58- if Arel :: Visitors :: SQLServer === @visitor
60+ if engine_activerecord_sqlserver_adapter?
5961 case locking
6062 when true
6163 locking = Arel . sql ( 'WITH(HOLDLOCK, ROWLOCK)' )
@@ -69,7 +71,13 @@ def lock(locking=true)
6971 lock_without_sqlserver ( locking )
7072 end
7173 end
72-
74+
75+ private
76+
77+ def engine_activerecord_sqlserver_adapter?
78+ @engine . connection && @engine . connection . class . name == AR_CA_SQLSA_NAME
79+ end
80+
7381 end
7482
7583 module Visitors
@@ -117,7 +125,7 @@ def visit_Arel_Nodes_Ordering(o)
117125 end
118126
119127 def visit_Arel_Nodes_Bin ( o )
120- "#{ visit o . expr } #{ @engine . connection . cs_equality_operator } "
128+ "#{ visit o . expr } #{ @connection . cs_equality_operator } "
121129 end
122130
123131 # SQLServer ToSql/Visitor (Additions)
@@ -189,7 +197,7 @@ def visit_Arel_Nodes_SelectStatementForComplexCount(o)
189197
190198 def source_with_lock_for_select_statement ( o )
191199 core = o . cores . first
192- source = visit ( core . source ) . strip if core . source
200+ source = "FROM #{ visit ( core . source ) . strip } " if core . source
193201 if source && o . lock
194202 lock = visit o . lock
195203 index = source . match ( /FROM [\w \[ \] \. ]+/ ) [ 0 ] . length
@@ -272,6 +280,14 @@ def complex_count_sql?(o)
272280 o . limit &&
273281 !join_in_select_statement? ( o )
274282 end
283+
284+ def select_primary_key_sql? ( o )
285+ core = o . cores . first
286+ return false if core . projections . size != 1
287+ p = core . projections . first
288+ t = table_from_select_statement ( o )
289+ Arel ::Attributes ::Attribute === p && t . primary_key && t . primary_key . name == p . name
290+ end
275291
276292 def find_and_fix_uncorrelated_joins_in_select_statement ( o )
277293 core = o . cores . first
@@ -315,6 +331,8 @@ def rowtable_projections(o)
315331 end
316332 elsif function_select_statement? ( o )
317333 [ Arel . star ]
334+ elsif select_primary_key_sql? ( o )
335+ [ Arel . sql ( "[__rnt].#{ quote_column_name ( core . projections . first . name ) } " ) ]
318336 else
319337 core . projections . map do |x |
320338 if x . respond_to? ( :relation )
0 commit comments