@@ -55,6 +55,27 @@ def self.sqlserver_connection(config) #:nodoc:
5555
5656 private
5757
58+ # Add basic support for SQL server locking hints
59+ # In the case of SQL server, the lock value must follow the FROM clause
60+ # Mysql: SELECT * FROM tst where testID = 10 LOCK IN share mode
61+ # SQLServer: SELECT * from tst WITH (HOLDLOCK, ROWLOCK) where testID = 10
62+ def self . construct_finder_sql ( options )
63+ scope = scope ( :find )
64+ sql = "SELECT #{ options [ :select ] || ( scope && scope [ :select ] ) || ( ( options [ :joins ] || ( scope && scope [ :joins ] ) ) && quoted_table_name + '.*' ) || '*' } "
65+ sql << "FROM #{ ( scope && scope [ :from ] ) || options [ :from ] || quoted_table_name } "
66+
67+ add_lock! ( sql , options , scope ) if ActiveRecord ::Base . connection . adapter_name == "SQLServer" && !options [ :lock ] . blank? # SQLServer
68+
69+ add_joins! ( sql , options , scope )
70+ add_conditions! ( sql , options [ :conditions ] , scope )
71+
72+ add_group! ( sql , options [ :group ] , scope )
73+ add_order! ( sql , options [ :order ] , scope )
74+ add_limit! ( sql , options , scope )
75+ add_lock! ( sql , options , scope ) unless ActiveRecord ::Base . connection . adapter_name == "SQLServer" # Not SQLServer
76+ sql
77+ end
78+
5879 # Overwrite the ActiveRecord::Base method for SQL server.
5980 # GROUP BY is necessary for distinct orderings
6081 def self . construct_finder_sql_for_association_limiting ( options , join_dependency )
@@ -576,9 +597,17 @@ def add_order_by_for_association_limiting!(sql, options)
576597 sql << " ORDER BY #{ order . join ( ',' ) } "
577598 end
578599
600+ # Appends a locking clause to an SQL statement.
601+ # This method *modifies* the +sql+ parameter.
602+ # # SELECT * FROM suppliers FOR UPDATE
603+ # add_lock! 'SELECT * FROM suppliers', :lock => true
604+ # add_lock! 'SELECT * FROM suppliers', :lock => ' WITH(HOLDLOCK, ROWLOCK)'
605+ # http://blog.sqlauthority.com/2007/04/27/sql-server-2005-locking-hints-and-examples/
579606 def add_lock! ( sql , options )
580- @logger . info "Warning: SQLServer :lock option '#{ options [ :lock ] . inspect } ' not supported" if @logger && options . has_key? ( :lock )
581- sql
607+ case lock = options [ :lock ]
608+ when true then sql << "WITH(HOLDLOCK, ROWLOCK) "
609+ when String then sql << "#{ lock } "
610+ end
582611 end
583612
584613 def recreate_database ( name )
0 commit comments