activerecord-sqlserver-adapter 3.2.18 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (30) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +4 -28
  3. data/VERSION +1 -1
  4. data/lib/active_record/connection_adapters/sqlserver/core_ext/active_record.rb +2 -7
  5. data/lib/active_record/connection_adapters/sqlserver/core_ext/explain.rb +6 -9
  6. data/lib/active_record/connection_adapters/sqlserver/core_ext/explain_subscriber.rb +3 -25
  7. data/lib/active_record/connection_adapters/sqlserver/core_ext/odbc.rb +4 -14
  8. data/lib/active_record/connection_adapters/sqlserver/core_ext/relation.rb +1 -3
  9. data/lib/active_record/connection_adapters/sqlserver/database_limits.rb +2 -4
  10. data/lib/active_record/connection_adapters/sqlserver/database_statements.rb +74 -80
  11. data/lib/active_record/connection_adapters/sqlserver/errors.rb +10 -14
  12. data/lib/active_record/connection_adapters/sqlserver/quoting.rb +24 -15
  13. data/lib/active_record/connection_adapters/sqlserver/schema_cache.rb +24 -19
  14. data/lib/active_record/connection_adapters/sqlserver/schema_creation.rb +28 -0
  15. data/lib/active_record/connection_adapters/sqlserver/schema_statements.rb +118 -77
  16. data/lib/active_record/connection_adapters/sqlserver/showplan.rb +10 -13
  17. data/lib/active_record/connection_adapters/sqlserver/showplan/printer_table.rb +8 -11
  18. data/lib/active_record/connection_adapters/sqlserver/showplan/printer_xml.rb +2 -5
  19. data/lib/active_record/connection_adapters/sqlserver/table_definition.rb +23 -0
  20. data/lib/active_record/connection_adapters/sqlserver/utils.rb +4 -10
  21. data/lib/active_record/connection_adapters/sqlserver_adapter.rb +121 -247
  22. data/lib/active_record/connection_adapters/sqlserver_column.rb +116 -0
  23. data/lib/active_record/sqlserver_base.rb +28 -0
  24. data/lib/active_record/sqlserver_test_case.rb +17 -0
  25. data/lib/arel/arel_sqlserver.rb +5 -0
  26. data/lib/arel/nodes_sqlserver.rb +14 -0
  27. data/lib/arel/select_manager_sqlserver.rb +62 -0
  28. data/lib/arel/visitors/sqlserver.rb +251 -188
  29. metadata +32 -10
  30. data/lib/active_record/connection_adapters/sqlserver/core_ext/database_statements.rb +0 -97
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 518484bb28fd5a4a70ac12e7d994071c645ff0ea
4
- data.tar.gz: 1eac15ea4105d11cc1f80e4e1416e173808ae9e3
3
+ metadata.gz: e47a3b956b52f24e1dc9f743d5f91590e1fb4337
4
+ data.tar.gz: f4a3544a7539acb775ff6cfa75925f1cf615e4c3
5
5
  SHA512:
6
- metadata.gz: 1f570f10c5ec18d26353568f985bbc06b9d621f6afecc0c71e8f7ad2ee2eca80754d7c7c06cd413e7813394960abaf69d3c9832772095bba5ac5bb4638ae774a
7
- data.tar.gz: e4f8c5d50c6fb2ce27460af6ea53592438964c5c93105ee5c66ce88c7a44e050e9c4faa5a7eec13197365dc531e5be25a4e08ec0b5f696934aec88348f7bd0cd
6
+ metadata.gz: 24465af624f8c38d423bd545842e007eaf86371ea802f8259ed54e6eb5b18ddafaf884b95e93637fc608f2033533415d6ca69663f6489afcaf4d04f8518e0250
7
+ data.tar.gz: 0029cf9f6b4f6de57f61848473ef243234cd32bce09f594e09a87bca8208c88626f06bed6bd186310d4f8b4749e6b03a32e0c88eeb7e6858767d8843518a9708
data/CHANGELOG CHANGED
@@ -1,31 +1,7 @@
1
- * 3.2.18 *
2
-
3
- * Added 2017 to supported list. Fixes #601. Thanks @catks.
4
-
5
- * 3.2.17 *
6
-
7
- * Add `WITH NO_INFOMSGS` to `user_options` method. Fixes #580
8
-
9
-
10
- * 3.2.16 *
11
-
12
- * All user optons to be array/hash. Fixes #540
13
-
14
-
15
- * 3.2.15 *
16
-
17
- * Added vNext support.
18
-
19
-
20
- * 3.2.14 *
21
-
22
- * Added 2016 to supported list.
23
-
24
-
25
- * 3.2.13 *
26
-
27
- * Allow 2014 to be used.
28
-
1
+ * 4.0.0 *
2
+ * Dropped support for ruby 1.8.7
3
+ * Removed deadlock victim retry in favor of Isolation Level
4
+ * Removed auto_explain_threshold_in_seconds (not used in rails 4)
29
5
 
30
6
  * 3.2.12 *
31
7
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 3.2.18
1
+ 4.0.0
@@ -3,9 +3,8 @@ module ActiveRecord
3
3
  module Sqlserver
4
4
  module CoreExt
5
5
  module ActiveRecord
6
-
7
6
  extend ActiveSupport::Concern
8
-
7
+
9
8
  included do
10
9
  class_attribute :coerced_sqlserver_date_columns, :coerced_sqlserver_time_columns
11
10
  self.coerced_sqlserver_date_columns = Set.new
@@ -13,10 +12,9 @@ module ActiveRecord
13
12
  end
14
13
 
15
14
  module ClassMethods
16
-
17
15
  def execute_procedure(proc_name, *variables)
18
16
  if connection.respond_to?(:execute_procedure)
19
- connection.execute_procedure(proc_name,*variables)
17
+ connection.execute_procedure(proc_name, *variables)
20
18
  else
21
19
  []
22
20
  end
@@ -29,14 +27,11 @@ module ActiveRecord
29
27
  def coerce_sqlserver_time(*attributes)
30
28
  self.coerced_sqlserver_time_columns += attributes.map(&:to_s)
31
29
  end
32
-
33
30
  end
34
-
35
31
  end
36
32
  end
37
33
  end
38
34
  end
39
35
  end
40
36
 
41
-
42
37
  ActiveRecord::Base.send :include, ActiveRecord::ConnectionAdapters::Sqlserver::CoreExt::ActiveRecord
@@ -3,19 +3,18 @@ module ActiveRecord
3
3
  module Sqlserver
4
4
  module CoreExt
5
5
  module Explain
6
-
7
- SQLSERVER_STATEMENT_PREFIX = "EXEC sp_executesql "
6
+ SQLSERVER_STATEMENT_PREFIX = 'EXEC sp_executesql '
8
7
  SQLSERVER_PARAM_MATCHER = /@\d+ =/
9
-
8
+
10
9
  def exec_explain(queries)
11
10
  unprepared_queries = queries.map { |sql, bind| [unprepare_sqlserver_statement(sql), bind] }
12
11
  super(unprepared_queries)
13
12
  end
14
-
13
+
15
14
  private
16
-
17
- # This is somewhat hacky, but it should reliably reformat our prepared sql statment
18
- # which uses sp_executesql to just the first argument, then unquote it. Likewise our
15
+
16
+ # This is somewhat hacky, but it should reliably reformat our prepared sql statment
17
+ # which uses sp_executesql to just the first argument, then unquote it. Likewise our
19
18
  # do_exec_query method should substitude the @n args withe the quoted values.
20
19
  def unprepare_sqlserver_statement(sql)
21
20
  if sql.starts_with?(SQLSERVER_STATEMENT_PREFIX)
@@ -29,8 +28,6 @@ module ActiveRecord
29
28
  sql
30
29
  end
31
30
  end
32
-
33
-
34
31
  end
35
32
  end
36
33
  end
@@ -1,26 +1,4 @@
1
- module ActiveRecord
2
- module ConnectionAdapters
3
- module Sqlserver
4
- module CoreExt
5
- class ExplainSubscriber
6
- def call(*args)
7
- if queries = Thread.current[:available_queries_for_explain]
8
- payload = args.last
9
- queries << payload.values_at(:sql, :binds) unless ignore_sqlserver_payload?(payload)
10
- end
11
- end
12
-
13
- IGNORED_PAYLOADS = %w(SCHEMA EXPLAIN CACHE)
14
- SQLSERVER_EXPLAINED_SQLS = /(select|update|delete|insert)/i
15
-
16
- # Need to modify the regex for the TSQL generated by this adapter so we can explain the proper sql statements
17
- def ignore_sqlserver_payload?(payload)
18
- payload[:exception] || IGNORED_PAYLOADS.include?(payload[:name]) || payload[:sql] !~ SQLSERVER_EXPLAINED_SQLS
19
- end
20
-
21
- ActiveSupport::Notifications.subscribe("sql.active_record", new)
22
- end
23
- end
24
- end
25
- end
1
+ silence_warnings do
2
+ # Already defined in Rails
3
+ ActiveRecord::ExplainSubscriber::EXPLAINED_SQLS = /(select|update|delete|insert)\b/i
26
4
  end
@@ -3,36 +3,26 @@ module ActiveRecord
3
3
  module Sqlserver
4
4
  module CoreExt
5
5
  module ODBC
6
-
7
6
  module Statement
8
-
9
7
  def finished?
10
- begin
11
- connected?
12
- false
13
- rescue ::ODBC::Error
14
- true
15
- end
8
+ connected?
9
+ false
10
+ rescue ::ODBC::Error
11
+ true
16
12
  end
17
-
18
13
  end
19
14
 
20
15
  module Database
21
-
22
16
  def run_block(*args)
23
17
  yield sth = run(*args)
24
18
  sth.drop
25
19
  end
26
-
27
20
  end
28
-
29
21
  end
30
22
  end
31
23
  end
32
24
  end
33
25
  end
34
26
 
35
-
36
27
  ODBC::Statement.send :include, ActiveRecord::ConnectionAdapters::Sqlserver::CoreExt::ODBC::Statement
37
28
  ODBC::Database.send :include, ActiveRecord::ConnectionAdapters::Sqlserver::CoreExt::ODBC::Database
38
-
@@ -3,13 +3,11 @@ module ActiveRecord
3
3
  module Sqlserver
4
4
  module CoreExt
5
5
  module Relation
6
-
7
6
  private
8
-
7
+
9
8
  def tables_in_string(string)
10
9
  super - ['__rnt']
11
10
  end
12
-
13
11
  end
14
12
  end
15
13
  end
@@ -2,7 +2,6 @@ module ActiveRecord
2
2
  module ConnectionAdapters
3
3
  module Sqlserver
4
4
  module DatabaseLimits
5
-
6
5
  def table_alias_length
7
6
  128
8
7
  end
@@ -32,17 +31,16 @@ module ActiveRecord
32
31
  end
33
32
 
34
33
  def in_clause_length
35
- 65536
34
+ 65_536
36
35
  end
37
36
 
38
37
  def sql_query_length
39
- 65536 * 4096
38
+ 65_536 * 4_096
40
39
  end
41
40
 
42
41
  def joins_per_query
43
42
  256
44
43
  end
45
-
46
44
  end
47
45
  end
48
46
  end
@@ -2,69 +2,58 @@ module ActiveRecord
2
2
  module ConnectionAdapters
3
3
  module Sqlserver
4
4
  module DatabaseStatements
5
-
6
- include CoreExt::DatabaseStatements
7
-
8
- def select_rows(sql, name = nil)
9
- raw_select sql, name, [], :fetch => :rows
5
+ def select_rows(sql, name = nil, binds = [])
6
+ do_exec_query sql, name, binds, fetch: :rows
10
7
  end
11
8
 
12
9
  def execute(sql, name = nil)
13
10
  if id_insert_table_name = query_requires_identity_insert?(sql)
14
- with_identity_insert_enabled(id_insert_table_name) { do_execute(sql,name) }
11
+ with_identity_insert_enabled(id_insert_table_name) { do_execute(sql, name) }
15
12
  else
16
- do_execute(sql,name)
13
+ do_execute(sql, name)
17
14
  end
18
15
  end
19
16
 
20
17
  def exec_query(sql, name = 'SQL', binds = [], sqlserver_options = {})
21
18
  if id_insert_table_name = sqlserver_options[:insert] ? query_requires_identity_insert?(sql) : nil
22
19
  with_identity_insert_enabled(id_insert_table_name) { do_exec_query(sql, name, binds) }
20
+ elsif update_sql?(sql)
21
+ sql = strip_ident_from_update(sql)
22
+ do_exec_query(sql, name, binds)
23
23
  else
24
24
  do_exec_query(sql, name, binds)
25
25
  end
26
26
  end
27
27
 
28
- def exec_insert(sql, name, binds)
29
- exec_query sql, name, binds, :insert => true
28
+ # The abstract adapter ignores the last two parameters also
29
+ def exec_insert(sql, name, binds, _pk = nil, _sequence_name = nil)
30
+ exec_query sql, name, binds, insert: true
30
31
  end
31
32
 
32
33
  def exec_delete(sql, name, binds)
33
- sql << "; SELECT @@ROWCOUNT AS AffectedRows"
34
+ sql << '; SELECT @@ROWCOUNT AS AffectedRows'
34
35
  super.rows.first.first
35
36
  end
36
37
 
37
38
  def exec_update(sql, name, binds)
38
- sql << "; SELECT @@ROWCOUNT AS AffectedRows"
39
+ sql << '; SELECT @@ROWCOUNT AS AffectedRows'
39
40
  super.rows.first.first
40
41
  end
41
42
 
42
- def outside_transaction?
43
- uncached { select_value('SELECT @@TRANCOUNT', 'SCHEMA') == 0 }
44
- end
45
-
46
43
  def supports_statement_cache?
47
44
  true
48
45
  end
49
46
 
50
- def transaction(options = {})
51
- if retry_deadlock_victim?
52
- block_given? ? transaction_with_retry_deadlock_victim(options) { yield } : transaction_with_retry_deadlock_victim(options)
53
- else
54
- block_given? ? super(options) { yield } : super(options)
55
- end
56
- end
57
-
58
47
  def begin_db_transaction
59
- do_execute "BEGIN TRANSACTION"
48
+ do_execute 'BEGIN TRANSACTION'
60
49
  end
61
50
 
62
51
  def commit_db_transaction
63
- disable_auto_reconnect { do_execute "COMMIT TRANSACTION" }
52
+ disable_auto_reconnect { do_execute 'COMMIT TRANSACTION' }
64
53
  end
65
54
 
66
55
  def rollback_db_transaction
67
- do_execute "IF @@TRANCOUNT > 0 ROLLBACK TRANSACTION"
56
+ do_execute 'IF @@TRANCOUNT > 0 ROLLBACK TRANSACTION'
68
57
  end
69
58
 
70
59
  def create_savepoint
@@ -78,12 +67,12 @@ module ActiveRecord
78
67
  disable_auto_reconnect { do_execute "ROLLBACK TRANSACTION #{current_savepoint_name}" }
79
68
  end
80
69
 
81
- def add_limit_offset!(sql, options)
70
+ def add_limit_offset!(_sql, _options)
82
71
  raise NotImplementedError, 'This has been moved to the SQLServerCompiler in Arel.'
83
72
  end
84
73
 
85
74
  def empty_insert_statement_value
86
- "DEFAULT VALUES"
75
+ 'DEFAULT VALUES'
87
76
  end
88
77
 
89
78
  def case_sensitive_modifier(node)
@@ -94,7 +83,7 @@ module ActiveRecord
94
83
 
95
84
  def execute_procedure(proc_name, *variables)
96
85
  vars = if variables.any? && variables.first.is_a?(Hash)
97
- variables.first.map { |k,v| "@#{k} = #{quote(v)}" }
86
+ variables.first.map { |k, v| "@#{k} = #{quote(v)}" }
98
87
  else
99
88
  variables.map { |v| quote(v) }
100
89
  end.join(', ')
@@ -104,41 +93,36 @@ module ActiveRecord
104
93
  case @connection_options[:mode]
105
94
  when :dblib
106
95
  result = @connection.execute(sql)
107
- result.each(:as => :hash, :cache_rows => true) do |row|
96
+ result.each(as: :hash, cache_rows: true) do |row|
108
97
  r = row.with_indifferent_access
109
98
  yield(r) if block_given?
110
99
  end
111
- result.each.map{ |row| row.is_a?(Hash) ? row.with_indifferent_access : row }
100
+ result.each.map { |row| row.is_a?(Hash) ? row.with_indifferent_access : row }
112
101
  when :odbc
113
102
  results = []
114
103
  raw_connection_run(sql) do |handle|
115
- get_rows = lambda {
116
- rows = handle_to_names_and_values handle, :fetch => :all
117
- rows.each_with_index { |r,i| rows[i] = r.with_indifferent_access }
104
+ get_rows = lambda do
105
+ rows = handle_to_names_and_values handle, fetch: :all
106
+ rows.each_with_index { |r, i| rows[i] = r.with_indifferent_access }
118
107
  results << rows
119
- }
120
- get_rows.call
121
- while handle_more_results?(handle)
122
- get_rows.call
123
108
  end
109
+ get_rows.call
110
+ get_rows.call while handle_more_results?(handle)
124
111
  end
125
112
  results.many? ? results : results.first
126
113
  end
127
114
  end
128
115
  end
129
116
 
130
- def use_database(database=nil)
117
+ def use_database(database = nil)
131
118
  return if sqlserver_azure?
132
119
  database ||= @connection_options[:database]
133
- do_execute "USE #{quote_table_name(database)}" unless database.blank?
120
+ do_execute "USE #{quote_database_name(database)}" unless database.blank?
134
121
  end
135
122
 
136
123
  def user_options
137
124
  return {} if sqlserver_azure?
138
- # fixes #535
139
- rows = select_rows('DBCC USEROPTIONS WITH NO_INFOMSGS', 'SCHEMA')
140
- rows = rows.first if rows.size == 2 && rows.last.empty?
141
- rows.reduce(HashWithIndifferentAccess.new) do |values, row|
125
+ select_rows('dbcc useroptions', 'SCHEMA').reduce(HashWithIndifferentAccess.new) do |values, row|
142
126
  if row.instance_of? Hash
143
127
  set_option = row.values[0].gsub(/\s+/, '_')
144
128
  user_value = row.values[1]
@@ -151,6 +135,7 @@ module ActiveRecord
151
135
  end
152
136
  end
153
137
 
138
+ # TODO: Rails 4 now supports isolation levels
154
139
  def user_options_dateformat
155
140
  if sqlserver_azure?
156
141
  select_value 'SELECT [dateformat] FROM [sys].[syslanguages] WHERE [langid] = @@LANGID', 'SCHEMA'
@@ -161,7 +146,7 @@ module ActiveRecord
161
146
 
162
147
  def user_options_isolation_level
163
148
  if sqlserver_azure?
164
- sql = %|SELECT CASE [transaction_isolation_level]
149
+ sql = %(SELECT CASE [transaction_isolation_level]
165
150
  WHEN 0 THEN NULL
166
151
  WHEN 1 THEN 'READ UNCOMITTED'
167
152
  WHEN 2 THEN 'READ COMITTED'
@@ -169,7 +154,7 @@ module ActiveRecord
169
154
  WHEN 4 THEN 'SERIALIZABLE'
170
155
  WHEN 5 THEN 'SNAPSHOT' END AS [isolation_level]
171
156
  FROM [sys].[dm_exec_sessions]
172
- WHERE [session_id] = @@SPID|.squish
157
+ WHERE [session_id] = @@SPID).squish
173
158
  select_value sql, 'SCHEMA'
174
159
  else
175
160
  user_options['isolation_level']
@@ -185,8 +170,10 @@ module ActiveRecord
185
170
  end
186
171
 
187
172
  def run_with_isolation_level(isolation_level)
188
- raise ArgumentError, "Invalid isolation level, #{isolation_level}. Supported levels include #{valid_isolation_levels.to_sentence}." if !valid_isolation_levels.include?(isolation_level.upcase)
189
- initial_isolation_level = user_options_isolation_level || "READ COMMITTED"
173
+ unless valid_isolation_levels.include?(isolation_level.upcase)
174
+ raise ArgumentError, "Invalid isolation level, #{isolation_level}. Supported levels include #{valid_isolation_levels.to_sentence}."
175
+ end
176
+ initial_isolation_level = user_options_isolation_level || 'READ COMMITTED'
190
177
  do_execute "SET TRANSACTION ISOLATION LEVEL #{isolation_level}"
191
178
  begin
192
179
  yield
@@ -196,11 +183,11 @@ module ActiveRecord
196
183
  end
197
184
 
198
185
  def newid_function
199
- select_value "SELECT NEWID()"
186
+ select_value 'SELECT NEWID()'
200
187
  end
201
188
 
202
189
  def newsequentialid_function
203
- select_value "SELECT NEWSEQUENTIALID()"
190
+ select_value 'SELECT NEWSEQUENTIALID()'
204
191
  end
205
192
 
206
193
  def activity_stats
@@ -256,7 +243,7 @@ module ActiveRecord
256
243
  end
257
244
  end
258
245
 
259
- def recreate_database!(database=nil)
246
+ def recreate_database!(database = nil)
260
247
  current_db = current_database
261
248
  database ||= current_db
262
249
  this_db = database.to_s == current_db
@@ -271,7 +258,7 @@ module ActiveRecord
271
258
  retry_count = 0
272
259
  max_retries = 1
273
260
  begin
274
- do_execute "DROP DATABASE #{quote_table_name(database)}"
261
+ do_execute "DROP DATABASE #{quote_database_name(database)}"
275
262
  rescue ActiveRecord::StatementInvalid => err
276
263
  if err.message =~ /because it is currently in use/i
277
264
  raise if retry_count >= max_retries
@@ -286,8 +273,12 @@ module ActiveRecord
286
273
  end
287
274
  end
288
275
 
289
- def create_database(database)
290
- do_execute "CREATE DATABASE #{quote_table_name(database)}"
276
+ def create_database(database, collation = @connection_options[:collation])
277
+ if collation
278
+ do_execute "CREATE DATABASE #{quote_database_name(database)} COLLATE #{collation}"
279
+ else
280
+ do_execute "CREATE DATABASE #{quote_database_name(database)}"
281
+ end
291
282
  end
292
283
 
293
284
  def current_database
@@ -298,26 +289,26 @@ module ActiveRecord
298
289
  select_value "SELECT SERVERPROPERTY('SqlCharSetName')"
299
290
  end
300
291
 
301
-
302
292
  protected
303
293
 
304
294
  def select(sql, name = nil, binds = [])
305
- exec_query(sql, name, binds).to_a
295
+ exec_query(sql, name, binds)
306
296
  end
307
297
 
308
298
  def sql_for_insert(sql, pk, id_value, sequence_name, binds)
309
- sql = "#{sql}; SELECT CAST(SCOPE_IDENTITY() AS bigint) AS Ident"# unless binds.empty?
299
+ sql =
300
+ if pk
301
+ sql.insert(sql.index(/ (DEFAULT )?VALUES/), " OUTPUT inserted.#{pk}")
302
+ else
303
+ "#{sql}; SELECT CAST(SCOPE_IDENTITY() AS bigint) AS Ident"
304
+ end
310
305
  super
311
306
  end
312
307
 
313
- def last_inserted_id(result)
314
- super || select_value("SELECT CAST(SCOPE_IDENTITY() AS bigint) AS Ident")
315
- end
316
-
317
308
  # === SQLServer Specific ======================================== #
318
309
 
319
310
  def valid_isolation_levels
320
- ["READ COMMITTED", "READ UNCOMMITTED", "REPEATABLE READ", "SERIALIZABLE", "SNAPSHOT"]
311
+ ['READ COMMITTED', 'READ UNCOMMITTED', 'REPEATABLE READ', 'SERIALIZABLE', 'SNAPSHOT']
321
312
  end
322
313
 
323
314
  # === SQLServer Specific (Executing) ============================ #
@@ -328,11 +319,17 @@ module ActiveRecord
328
319
  end
329
320
  end
330
321
 
331
- def do_exec_query(sql, name, binds)
322
+ def do_exec_query(sql, name, binds, options = {})
323
+ # This allows non-AR code to utilize the binds
324
+ # handling code, e.g. select_rows()
325
+ if options[:fetch] != :rows
326
+ options[:ar_result] = true
327
+ end
328
+
332
329
  explaining = name == 'EXPLAIN'
333
330
  names_and_types = []
334
331
  params = []
335
- binds.each_with_index do |(column,value),index|
332
+ binds.each_with_index do |(column, value), index|
336
333
  ar_column = column.is_a?(ActiveRecord::ConnectionAdapters::Column)
337
334
  next if ar_column && column.sql_type == 'timestamp'
338
335
  v = value
@@ -345,9 +342,9 @@ module ActiveRecord
345
342
  v = value.to_i
346
343
  "@#{index} int"
347
344
  else
348
- raise "Unknown bind columns. We can account for this."
345
+ raise 'Unknown bind columns. We can account for this.'
349
346
  end
350
- quoted_value = ar_column ? quote(v,column) : quote(v,nil)
347
+ quoted_value = ar_column ? quote(v, column) : quote(v, nil)
351
348
  params << (explaining ? quoted_value : "@#{index} = #{quoted_value}")
352
349
  end
353
350
  if explaining
@@ -359,7 +356,7 @@ module ActiveRecord
359
356
  sql = "EXEC sp_executesql #{quote(sql)}"
360
357
  sql << ", #{quote(names_and_types.join(', '))}, #{params.join(', ')}" unless binds.empty?
361
358
  end
362
- raw_select sql, name, binds, :ar_result => true
359
+ raw_select sql, name, binds, options
363
360
  end
364
361
 
365
362
  def raw_connection_do(sql)
@@ -375,17 +372,15 @@ module ActiveRecord
375
372
 
376
373
  # === SQLServer Specific (Selecting) ============================ #
377
374
 
378
- def raw_select(sql, name='SQL', binds=[], options={})
379
- log(sql,name,binds) { _raw_select(sql, options) }
375
+ def raw_select(sql, name = 'SQL', binds = [], options = {})
376
+ log(sql, name, binds) { _raw_select(sql, options) }
380
377
  end
381
378
 
382
- def _raw_select(sql, options={})
383
- begin
384
- handle = raw_connection_run(sql)
385
- handle_to_names_and_values(handle, options)
386
- ensure
387
- finish_statement_handle(handle)
388
- end
379
+ def _raw_select(sql, options = {})
380
+ handle = raw_connection_run(sql)
381
+ handle_to_names_and_values(handle, options)
382
+ ensure
383
+ finish_statement_handle(handle)
389
384
  end
390
385
 
391
386
  def raw_connection_run(sql)
@@ -407,7 +402,7 @@ module ActiveRecord
407
402
  end
408
403
  end
409
404
 
410
- def handle_to_names_and_values(handle, options={})
405
+ def handle_to_names_and_values(handle, options = {})
411
406
  case @connection_options[:mode]
412
407
  when :dblib
413
408
  handle_to_names_and_values_dblib(handle, options)
@@ -416,7 +411,7 @@ module ActiveRecord
416
411
  end
417
412
  end
418
413
 
419
- def handle_to_names_and_values_dblib(handle, options={})
414
+ def handle_to_names_and_values_dblib(handle, options = {})
420
415
  query_options = {}.tap do |qo|
421
416
  qo[:timezone] = ActiveRecord::Base.default_timezone || :utc
422
417
  qo[:as] = (options[:ar_result] || options[:fetch] == :rows) ? :array : :hash
@@ -426,7 +421,7 @@ module ActiveRecord
426
421
  options[:ar_result] ? ActiveRecord::Result.new(columns, results) : results
427
422
  end
428
423
 
429
- def handle_to_names_and_values_odbc(handle, options={})
424
+ def handle_to_names_and_values_odbc(handle, options = {})
430
425
  @connection.use_utc = ActiveRecord::Base.default_timezone == :utc
431
426
  if options[:ar_result]
432
427
  columns = lowercase_schema_reflection ? handle.columns(true).map { |c| c.name.downcase } : handle.columns(true).map { |c| c.name }
@@ -451,7 +446,6 @@ module ActiveRecord
451
446
  end
452
447
  handle
453
448
  end
454
-
455
449
  end
456
450
  end
457
451
  end