asa-2000 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2008-2011
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,49 @@
1
+ require 'set'
2
+ require 'active_record/base'
3
+ require 'active_record/version'
4
+ require 'active_support/concern'
5
+ require 'active_support/core_ext/class/attribute'
6
+
7
+ module ActiveRecord
8
+ module ConnectionAdapters
9
+ module Sqlserver
10
+ module CoreExt
11
+ module ActiveRecord
12
+
13
+ extend ActiveSupport::Concern
14
+
15
+ included do
16
+ class_attribute :coerced_sqlserver_date_columns, :coerced_sqlserver_time_columns
17
+ self.coerced_sqlserver_date_columns = Set.new
18
+ self.coerced_sqlserver_time_columns = Set.new
19
+ end
20
+
21
+ module ClassMethods
22
+
23
+ def execute_procedure(proc_name, *variables)
24
+ if connection.respond_to?(:execute_procedure)
25
+ connection.execute_procedure(proc_name,*variables)
26
+ else
27
+ []
28
+ end
29
+ end
30
+
31
+ def coerce_sqlserver_date(*attributes)
32
+ self.coerced_sqlserver_date_columns += attributes.map(&:to_s)
33
+ end
34
+
35
+ def coerce_sqlserver_time(*attributes)
36
+ self.coerced_sqlserver_time_columns += attributes.map(&:to_s)
37
+ end
38
+
39
+ end
40
+
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+
47
+
48
+ ActiveRecord::Base.send :include, ActiveRecord::ConnectionAdapters::Sqlserver::CoreExt::ActiveRecord
49
+
@@ -0,0 +1,97 @@
1
+ module ActiveRecord
2
+ module ConnectionAdapters
3
+ module Sqlserver
4
+ module CoreExt
5
+ module DatabaseStatements
6
+
7
+ # This is a copy of the current (3.1.3) ActiveRecord's transaction method. We should propose
8
+ # a patch to the default transaction method to make it more callback for adapters that want to
9
+ # do deadlock retry logic. Because this is a copy, we really need to keep an eye out on this when
10
+ # upgradding the adapter.
11
+ def transaction_with_retry_deadlock_victim(options = {})
12
+ options.assert_valid_keys :requires_new, :joinable
13
+
14
+ last_transaction_joinable = defined?(@transaction_joinable) ? @transaction_joinable : nil
15
+ if options.has_key?(:joinable)
16
+ @transaction_joinable = options[:joinable]
17
+ else
18
+ @transaction_joinable = true
19
+ end
20
+ requires_new = options[:requires_new] || !last_transaction_joinable
21
+
22
+ transaction_open = false
23
+ @_current_transaction_records ||= []
24
+
25
+ begin
26
+ if block_given?
27
+ if requires_new || open_transactions == 0
28
+ if open_transactions == 0
29
+ begin_db_transaction
30
+ elsif requires_new
31
+ create_savepoint
32
+ end
33
+ increment_open_transactions
34
+ transaction_open = true
35
+ @_current_transaction_records.push([])
36
+ end
37
+ yield
38
+ end
39
+ rescue Exception => database_transaction_rollback
40
+ if transaction_open && !outside_transaction?
41
+ transaction_open = false
42
+ decrement_open_transactions
43
+ # handle deadlock victim retries at the outermost transaction
44
+ if open_transactions == 0
45
+ if database_transaction_rollback.is_a?(::ActiveRecord::DeadlockVictim)
46
+ # SQL Server has already rolled back, so rollback activerecord's history
47
+ rollback_transaction_records(true)
48
+ retry
49
+ else
50
+ rollback_db_transaction
51
+ rollback_transaction_records(true)
52
+ end
53
+ else
54
+ rollback_to_savepoint
55
+ rollback_transaction_records(false)
56
+ end
57
+ end
58
+ raise unless database_transaction_rollback.is_a?(::ActiveRecord::Rollback)
59
+ end
60
+ ensure
61
+ @transaction_joinable = last_transaction_joinable
62
+
63
+ if outside_transaction?
64
+ @open_transactions = 0
65
+ elsif transaction_open
66
+ decrement_open_transactions
67
+ begin
68
+ if open_transactions == 0
69
+ commit_db_transaction
70
+ commit_transaction_records
71
+ else
72
+ release_savepoint
73
+ save_point_records = @_current_transaction_records.pop
74
+ unless save_point_records.blank?
75
+ @_current_transaction_records.push([]) if @_current_transaction_records.empty?
76
+ @_current_transaction_records.last.concat(save_point_records)
77
+ end
78
+ end
79
+ rescue Exception => database_transaction_rollback
80
+ if open_transactions == 0
81
+ rollback_db_transaction
82
+ rollback_transaction_records(true)
83
+ else
84
+ rollback_to_savepoint
85
+ rollback_transaction_records(false)
86
+ end
87
+ raise
88
+ end
89
+ end
90
+ end
91
+
92
+ end
93
+ end
94
+ end
95
+ end
96
+ end
97
+
@@ -0,0 +1,38 @@
1
+ module ActiveRecord
2
+ module ConnectionAdapters
3
+ module Sqlserver
4
+ module CoreExt
5
+ module ODBC
6
+
7
+ module Statement
8
+
9
+ def finished?
10
+ begin
11
+ connected?
12
+ false
13
+ rescue ::ODBC::Error
14
+ true
15
+ end
16
+ end
17
+
18
+ end
19
+
20
+ module Database
21
+
22
+ def run_block(*args)
23
+ yield sth = run(*args)
24
+ sth.drop
25
+ end
26
+
27
+ end
28
+
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+
35
+
36
+ ODBC::Statement.send :include, ActiveRecord::ConnectionAdapters::Sqlserver::CoreExt::ODBC::Statement
37
+ ODBC::Database.send :include, ActiveRecord::ConnectionAdapters::Sqlserver::CoreExt::ODBC::Database
38
+
@@ -0,0 +1,49 @@
1
+ module ActiveRecord
2
+ module ConnectionAdapters
3
+ module Sqlserver
4
+ module DatabaseLimits
5
+
6
+ def table_alias_length
7
+ 128
8
+ end
9
+
10
+ def column_name_length
11
+ 128
12
+ end
13
+
14
+ def table_name_length
15
+ 128
16
+ end
17
+
18
+ def index_name_length
19
+ 128
20
+ end
21
+
22
+ def columns_per_table
23
+ 1024
24
+ end
25
+
26
+ def indexes_per_table
27
+ 999
28
+ end
29
+
30
+ def columns_per_multicolumn_index
31
+ 16
32
+ end
33
+
34
+ def in_clause_length
35
+ 65536
36
+ end
37
+
38
+ def sql_query_length
39
+ 65536 * 4096
40
+ end
41
+
42
+ def joins_per_query
43
+ 256
44
+ end
45
+
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,445 @@
1
+ module ActiveRecord
2
+ module ConnectionAdapters
3
+ module Sqlserver
4
+ module DatabaseStatements
5
+
6
+ include CoreExt::DatabaseStatements
7
+
8
+ def select_rows(sql, name = nil)
9
+ raw_select sql, name, [], :fetch => :rows
10
+ end
11
+
12
+ def execute(sql, name = nil)
13
+ if id_insert_table_name = query_requires_identity_insert?(sql)
14
+ with_identity_insert_enabled(id_insert_table_name) { do_execute(sql,name) }
15
+ else
16
+ do_execute(sql,name)
17
+ end
18
+ end
19
+
20
+ def exec_query(sql, name = 'SQL', binds = [], sqlserver_options = {})
21
+ if id_insert_table_name = sqlserver_options[:insert] ? query_requires_identity_insert?(sql) : nil
22
+ with_identity_insert_enabled(id_insert_table_name) { do_exec_query(sql, name, binds) }
23
+ else
24
+ do_exec_query(sql, name, binds)
25
+ end
26
+ end
27
+
28
+ def exec_insert(sql, name, binds)
29
+ exec_query sql, name, binds, :insert => true
30
+ end
31
+
32
+ def exec_delete(sql, name, binds)
33
+ sql << "; SELECT @@ROWCOUNT AS AffectedRows"
34
+ super.rows.first.first
35
+ end
36
+
37
+ def exec_update(sql, name, binds)
38
+ sql << "; SELECT @@ROWCOUNT AS AffectedRows"
39
+ super.rows.first.first
40
+ end
41
+
42
+ def outside_transaction?
43
+ info_schema_query { select_value("SELECT @@TRANCOUNT") == 0 }
44
+ end
45
+
46
+ def supports_statement_cache?
47
+ true
48
+ end
49
+
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
+ def begin_db_transaction
59
+ do_execute "BEGIN TRANSACTION"
60
+ end
61
+
62
+ def commit_db_transaction
63
+ disable_auto_reconnect { do_execute "COMMIT TRANSACTION" }
64
+ end
65
+
66
+ def rollback_db_transaction
67
+ do_execute "IF @@TRANCOUNT > 0 ROLLBACK TRANSACTION"
68
+ end
69
+
70
+ def create_savepoint
71
+ disable_auto_reconnect { do_execute "SAVE TRANSACTION #{current_savepoint_name}" }
72
+ end
73
+
74
+ def release_savepoint
75
+ end
76
+
77
+ def rollback_to_savepoint
78
+ disable_auto_reconnect { do_execute "ROLLBACK TRANSACTION #{current_savepoint_name}" }
79
+ end
80
+
81
+ def add_limit_offset!(sql, options)
82
+ raise NotImplementedError, 'This has been moved to the SQLServerCompiler in Arel.'
83
+ end
84
+
85
+ def empty_insert_statement_value
86
+ "DEFAULT VALUES"
87
+ end
88
+
89
+ def case_sensitive_modifier(node)
90
+ node.acts_like?(:string) ? Arel::Nodes::Bin.new(node) : node
91
+ end
92
+
93
+ # === SQLServer Specific ======================================== #
94
+
95
+ def execute_procedure(proc_name, *variables)
96
+ vars = variables.map{ |v| quote(v) }.join(', ')
97
+ sql = "EXEC #{proc_name} #{vars}".strip
98
+ name = 'Execute Procedure'
99
+ log(sql, name) do
100
+ case @connection_options[:mode]
101
+ when :dblib
102
+ result = @connection.execute(sql)
103
+ result.each(:as => :hash, :cache_rows => true) do |row|
104
+ r = row.with_indifferent_access
105
+ yield(r) if block_given?
106
+ end
107
+ result.each.map{ |row| row.is_a?(Hash) ? row.with_indifferent_access : row }
108
+ when :odbc
109
+ results = []
110
+ raw_connection_run(sql) do |handle|
111
+ get_rows = lambda {
112
+ rows = handle_to_names_and_values handle, :fetch => :all
113
+ rows.each_with_index { |r,i| rows[i] = r.with_indifferent_access }
114
+ results << rows
115
+ }
116
+ get_rows.call
117
+ while handle_more_results?(handle)
118
+ get_rows.call
119
+ end
120
+ end
121
+ results.many? ? results : results.first
122
+ end
123
+ end
124
+ end
125
+
126
+ def use_database(database=nil)
127
+ return if sqlserver_azure?
128
+ database ||= @connection_options[:database]
129
+ do_execute "USE #{quote_table_name(database)}" unless database.blank?
130
+ end
131
+
132
+ def user_options
133
+ return {} if sqlserver_azure?
134
+ info_schema_query do
135
+ select_rows("dbcc useroptions").inject(HashWithIndifferentAccess.new) do |values,row|
136
+ set_option = row[0].gsub(/\s+/,'_')
137
+ user_value = row[1]
138
+ values[set_option] = user_value
139
+ values
140
+ end
141
+ end
142
+ end
143
+
144
+ def user_options_dateformat
145
+ if sqlserver_azure?
146
+ info_schema_query { select_value "SELECT [dateformat] FROM [sys].[syslanguages] WHERE [langid] = @@LANGID" }
147
+ else
148
+ user_options['dateformat']
149
+ end
150
+ end
151
+
152
+ def user_options_isolation_level
153
+ if sqlserver_azure?
154
+ info_schema_query do
155
+ sql = %|SELECT CASE [transaction_isolation_level]
156
+ WHEN 0 THEN NULL
157
+ WHEN 1 THEN 'READ UNCOMITTED'
158
+ WHEN 2 THEN 'READ COMITTED'
159
+ WHEN 3 THEN 'REPEATABLE'
160
+ WHEN 4 THEN 'SERIALIZABLE'
161
+ WHEN 5 THEN 'SNAPSHOT' END AS [isolation_level]
162
+ FROM [sys].[dm_exec_sessions]
163
+ WHERE [session_id] = @@SPID|.squish
164
+ select_value(sql)
165
+ end
166
+ else
167
+ user_options['isolation_level']
168
+ end
169
+ end
170
+
171
+ def user_options_language
172
+ if sqlserver_azure?
173
+ info_schema_query { select_value "SELECT @@LANGUAGE AS [language]" }
174
+ else
175
+ user_options['language']
176
+ end
177
+ end
178
+
179
+ def run_with_isolation_level(isolation_level)
180
+ raise ArgumentError, "Invalid isolation level, #{isolation_level}. Supported levels include #{valid_isolation_levels.to_sentence}." if !valid_isolation_levels.include?(isolation_level.upcase)
181
+ initial_isolation_level = user_options_isolation_level || "READ COMMITTED"
182
+ do_execute "SET TRANSACTION ISOLATION LEVEL #{isolation_level}"
183
+ begin
184
+ yield
185
+ ensure
186
+ do_execute "SET TRANSACTION ISOLATION LEVEL #{initial_isolation_level}"
187
+ end if block_given?
188
+ end
189
+
190
+ def newid_function
191
+ select_value "SELECT NEWID()"
192
+ end
193
+
194
+ def newsequentialid_function
195
+ select_value "SELECT NEWSEQUENTIALID()"
196
+ end
197
+
198
+ def activity_stats
199
+ select_all %|
200
+ SELECT
201
+ [session_id] = s.session_id,
202
+ [user_process] = CONVERT(CHAR(1), s.is_user_process),
203
+ [login] = s.login_name,
204
+ [database] = ISNULL(db_name(r.database_id), N''),
205
+ [task_state] = ISNULL(t.task_state, N''),
206
+ [command] = ISNULL(r.command, N''),
207
+ [application] = ISNULL(s.program_name, N''),
208
+ [wait_time_ms] = ISNULL(w.wait_duration_ms, 0),
209
+ [wait_type] = ISNULL(w.wait_type, N''),
210
+ [wait_resource] = ISNULL(w.resource_description, N''),
211
+ [blocked_by] = ISNULL(CONVERT (varchar, w.blocking_session_id), ''),
212
+ [head_blocker] =
213
+ CASE
214
+ -- session has an active request, is blocked, but is blocking others
215
+ WHEN r2.session_id IS NOT NULL AND r.blocking_session_id = 0 THEN '1'
216
+ -- session is idle but has an open tran and is blocking others
217
+ WHEN r.session_id IS NULL THEN '1'
218
+ ELSE ''
219
+ END,
220
+ [total_cpu_ms] = s.cpu_time,
221
+ [total_physical_io_mb] = (s.reads + s.writes) * 8 / 1024,
222
+ [memory_use_kb] = s.memory_usage * 8192 / 1024,
223
+ [open_transactions] = ISNULL(r.open_transaction_count,0),
224
+ [login_time] = s.login_time,
225
+ [last_request_start_time] = s.last_request_start_time,
226
+ [host_name] = ISNULL(s.host_name, N''),
227
+ [net_address] = ISNULL(c.client_net_address, N''),
228
+ [execution_context_id] = ISNULL(t.exec_context_id, 0),
229
+ [request_id] = ISNULL(r.request_id, 0),
230
+ [workload_group] = N''
231
+ FROM sys.dm_exec_sessions s LEFT OUTER JOIN sys.dm_exec_connections c ON (s.session_id = c.session_id)
232
+ LEFT OUTER JOIN sys.dm_exec_requests r ON (s.session_id = r.session_id)
233
+ LEFT OUTER JOIN sys.dm_os_tasks t ON (r.session_id = t.session_id AND r.request_id = t.request_id)
234
+ LEFT OUTER JOIN
235
+ (SELECT *, ROW_NUMBER() OVER (PARTITION BY waiting_task_address ORDER BY wait_duration_ms DESC) AS row_num
236
+ FROM sys.dm_os_waiting_tasks
237
+ ) w ON (t.task_address = w.waiting_task_address) AND w.row_num = 1
238
+ LEFT OUTER JOIN sys.dm_exec_requests r2 ON (r.session_id = r2.blocking_session_id)
239
+ WHERE db_name(r.database_id) = '#{current_database}'
240
+ ORDER BY s.session_id|
241
+ end
242
+
243
+ # === SQLServer Specific (Rake/Test Helpers) ==================== #
244
+
245
+ def recreate_database
246
+ remove_database_connections_and_rollback do
247
+ do_execute "EXEC sp_MSforeachtable 'DROP TABLE ?'"
248
+ end
249
+ end
250
+
251
+ def recreate_database!(database=nil)
252
+ current_db = current_database
253
+ database ||= current_db
254
+ this_db = database.to_s == current_db
255
+ do_execute 'USE master' if this_db
256
+ drop_database(database)
257
+ create_database(database)
258
+ ensure
259
+ use_database(current_db) if this_db
260
+ end
261
+
262
+ def drop_database(database)
263
+ retry_count = 0
264
+ max_retries = 1
265
+ begin
266
+ do_execute "DROP DATABASE #{quote_table_name(database)}"
267
+ rescue ActiveRecord::StatementInvalid => err
268
+ if err.message =~ /because it is currently in use/i
269
+ raise if retry_count >= max_retries
270
+ retry_count += 1
271
+ remove_database_connections_and_rollback(database)
272
+ retry
273
+ elsif err.message =~ /does not exist/i
274
+ nil
275
+ else
276
+ raise
277
+ end
278
+ end
279
+ end
280
+
281
+ def create_database(database)
282
+ do_execute "CREATE DATABASE #{quote_table_name(database)}"
283
+ end
284
+
285
+ def current_database
286
+ select_value 'SELECT DB_NAME()'
287
+ end
288
+
289
+ def charset
290
+ select_value "SELECT SERVERPROPERTY('SqlCharSetName')"
291
+ end
292
+
293
+
294
+ protected
295
+
296
+ def select(sql, name = nil, binds = [])
297
+ exec_query(sql, name, binds).to_a
298
+ end
299
+
300
+ def sql_for_insert(sql, pk, id_value, sequence_name, binds)
301
+ sql = "#{sql}; SELECT CAST(SCOPE_IDENTITY() AS bigint) AS Ident"# unless binds.empty?
302
+ super
303
+ end
304
+
305
+ def last_inserted_id(result)
306
+ super || select_value("SELECT CAST(SCOPE_IDENTITY() AS bigint) AS Ident")
307
+ end
308
+
309
+ # === SQLServer Specific ======================================== #
310
+
311
+ def valid_isolation_levels
312
+ ["READ COMMITTED", "READ UNCOMMITTED", "REPEATABLE READ", "SERIALIZABLE", "SNAPSHOT"]
313
+ end
314
+
315
+ # === SQLServer Specific (Executing) ============================ #
316
+
317
+ def do_execute(sql, name = nil)
318
+ name ||= 'EXECUTE'
319
+ log(sql, name) do
320
+ with_sqlserver_error_handling { raw_connection_do(sql) }
321
+ end
322
+ end
323
+
324
+ def do_exec_query(sql, name, binds)
325
+ statement = quote(sql)
326
+ names_and_types = []
327
+ params = []
328
+ binds.each_with_index do |(column,value),index|
329
+ ar_column = column.is_a?(ActiveRecord::ConnectionAdapters::Column)
330
+ next if ar_column && column.sql_type == 'timestamp'
331
+ v = value
332
+ names_and_types << if ar_column
333
+ v = value.to_i if column.is_integer? && value.present?
334
+ "@#{index} #{column.sql_type_for_statement}"
335
+ elsif column.acts_like?(:string)
336
+ "@#{index} varchar(256)"
337
+ elsif column.is_a?(Fixnum)
338
+ v = value.to_i
339
+ "@#{index} int"
340
+ else
341
+ "@#{index} int"
342
+ #raise "Unknown bind columns. We can account for this."
343
+ end
344
+ quoted_value = ar_column ? quote(v,column) : quote(v,nil)
345
+ params << "@#{index} = #{quoted_value}"
346
+ end
347
+ sql = "EXEC sp_executesql #{statement}"
348
+ sql << ", #{quote(names_and_types.join(', '))}, #{params.join(', ')}" unless binds.empty?
349
+ raw_select sql, name, binds, :ar_result => true
350
+ end
351
+
352
+ def raw_connection_do(sql)
353
+ case @connection_options[:mode]
354
+ when :dblib
355
+ @connection.execute(sql).do
356
+ when :odbc
357
+ @connection.do(sql)
358
+ end
359
+ ensure
360
+ @update_sql = false
361
+ end
362
+
363
+ # === SQLServer Specific (Selecting) ============================ #
364
+
365
+ def raw_select(sql, name=nil, binds=[], options={})
366
+ log(sql,name,binds) { _raw_select(sql, options) }
367
+ end
368
+
369
+ def _raw_select(sql, options={})
370
+ begin
371
+ handle = raw_connection_run(sql)
372
+ handle_to_names_and_values(handle, options)
373
+ ensure
374
+ finish_statement_handle(handle)
375
+ end
376
+ end
377
+
378
+ def raw_connection_run(sql)
379
+ with_sqlserver_error_handling do
380
+ case @connection_options[:mode]
381
+ when :dblib
382
+ @connection.execute(sql)
383
+ when :odbc
384
+ block_given? ? @connection.run_block(sql) { |handle| yield(handle) } : @connection.run(sql)
385
+ end
386
+ end
387
+ end
388
+
389
+ def handle_more_results?(handle)
390
+ case @connection_options[:mode]
391
+ when :dblib
392
+ when :odbc
393
+ handle.more_results
394
+ end
395
+ end
396
+
397
+ def handle_to_names_and_values(handle, options={})
398
+ case @connection_options[:mode]
399
+ when :dblib
400
+ handle_to_names_and_values_dblib(handle, options)
401
+ when :odbc
402
+ handle_to_names_and_values_odbc(handle, options)
403
+ end
404
+ end
405
+
406
+ def handle_to_names_and_values_dblib(handle, options={})
407
+ query_options = {}.tap do |qo|
408
+ qo[:timezone] = ActiveRecord::Base.default_timezone || :utc
409
+ qo[:as] = (options[:ar_result] || options[:fetch] == :rows) ? :array : :hash
410
+ end
411
+ results = handle.each(query_options)
412
+ columns = lowercase_schema_reflection ? handle.fields.map { |c| c.downcase } : handle.fields
413
+ options[:ar_result] ? ActiveRecord::Result.new(columns, results) : results
414
+ end
415
+
416
+ def handle_to_names_and_values_odbc(handle, options={})
417
+ @connection.use_utc = ActiveRecord::Base.default_timezone == :utc
418
+ if options[:ar_result]
419
+ columns = lowercase_schema_reflection ? handle.columns(true).map { |c| c.name.downcase } : handle.columns(true).map { |c| c.name }
420
+ rows = handle.fetch_all || []
421
+ ActiveRecord::Result.new(columns, rows)
422
+ else
423
+ case options[:fetch]
424
+ when :all
425
+ handle.each_hash || []
426
+ when :rows
427
+ handle.fetch_all || []
428
+ end
429
+ end
430
+ end
431
+
432
+ def finish_statement_handle(handle)
433
+ case @connection_options[:mode]
434
+ when :dblib
435
+ handle.cancel if handle
436
+ when :odbc
437
+ handle.drop if handle && handle.respond_to?(:drop) && !handle.finished?
438
+ end
439
+ handle
440
+ end
441
+
442
+ end
443
+ end
444
+ end
445
+ end