activerecord-sqlserver-adapter 2.3.4 → 2.3.5

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG CHANGED
@@ -2,6 +2,29 @@
2
2
  MASTER
3
3
 
4
4
 
5
+ * 2.3.5
6
+
7
+ * Initial IronRuby ADONET connection mode support baked right in. Removed most &block
8
+ parameters, no handle/request object yielded anymore. Better abstraction and compliance
9
+ per the ActiveRecord abstract adapter to not yielding handles for #execute and only for
10
+ low level #select. Better wrapping of all queries at lowest level in #log so exceptions
11
+ at anytime can be handled correctly by core AR. Critical for System::Data's command
12
+ readers. Better abstraction for introspecting on #connection_mode. Added support for
13
+ running singular test cases via TextMate's Command-R. [Ken Collins]
14
+
15
+ * Force a binary encoding on values coming in and out of those columns for ruby 1.9.
16
+ Fixes ticket #33 [Jeroen Zwartepoorte]
17
+
18
+ * Using change_column will leave default if the type does not change or a new default
19
+ is not included. Fixes issue #22. [Ransom Briggs]
20
+
21
+ * Use correct SP name for sp_MSforeachtable so any collation can get to it. [7to3]
22
+
23
+ * Qualify INFORMATION_SCHEMA.COLUMNS with a correct period DB name if present.
24
+
25
+ * Allow adapter to return multipe results sets, for example from stored procedures. [Chris Hall]
26
+
27
+
5
28
  * 2.3.4
6
29
 
7
30
  * For tables that named with schema(ex. rails.users), they could not get length of column.
@@ -6,7 +6,8 @@ The SQL Server adapter for rails is back for ActiveRecord 2.2 and up! We are cur
6
6
 
7
7
  == What's New
8
8
 
9
- * Strict ODBC required! No DBI means around 20% faster!
9
+ * IronRuby support using ADONET connection mode.
10
+ * Direct ODBC mode. No DBI anymore, means around 20% faster!
10
11
  * Now supports SQL Server 2008 too!
11
12
  * Fully tested under 1.9!!! Correctly encodes/decodes UTF-8 types in ruby 1.9 too.
12
13
  * Now supports both rails 2.2 & 2.3!!!
@@ -129,7 +130,7 @@ It is our goal to match the adapter version with each version of rails. However
129
130
 
130
131
  == Installation
131
132
 
132
- You will need Ruby ODBC. If you are using the adapter under 1.9, then you need at least ruby-odbc version 0.9996. Currently ADO modes are not supported since we dropped the unnecessary DBI dependency and transport layer. This was done so we could incorporate other transports such as ADO.NET (w IronRuby) mode in the future or possibly a straight FreeTDS layer. The sky is the limit now and we have a code that can be accept these optional transports. If you are interested in helping, open a ticket and submit a patch. Or start a conversation on the Google Group.
133
+ You will need Ruby ODBC. If you are using the adapter under 1.9, then you need at least ruby-odbc version 0.9996. ODBC is the preferred mode, however if you are using IronRuby you can use the ADONET connection mode which uses native System.Data connection. Other connection modes may be supported, possibly a straight FreeTDS layer. The sky is the limit now and we have a code that can be accept these optional transports. If you are interested in helping, open a ticket and submit a patch. Or start a conversation on the Google Group.
133
134
 
134
135
  $ gem install activerecord-sqlserver-adapter
135
136
 
@@ -142,6 +143,19 @@ Here are some external links for libraries and/or tutorials on how to install an
142
143
  * http://www.ch-werner.de/rubyodbc/
143
144
 
144
145
 
146
+ == IronRuby ADONET Mode
147
+
148
+ A few details on this implementation. All that is needed in your database.yml configuration file is "mode: adonet" vs "odbc" and if you are running IronRuby, the connection will be native. You can also specify an "integrated_security: true" option in your configuration, remember to remove the username/password options too. To use this adapter, you will not need need ANY DBI middle layer or special extension gems to the adapter.
149
+
150
+ This adapter is opinionated in regards to IronRuby on types going in and out of the DB. For example strings will be String, not System::String and DateTime vs System::Datetime. There are many more examples but the rule of thumb is that the types will be simple types that correlate to a standard Ruby implementation. We enforce this basic rule because it is necessary to pass the tests and let the framework do its job. We recommend sticking to native Ruby types in your application code too.
151
+
152
+ The adapter establishes a System::Data::SqlClient connection that has both MultipleActiveResultSets (MARS) and Pooling turned off. There are good reasons for this one because the connection would not work otherwise for all the code issued by ActiveRecord. Remember too that ActiveRecord has it's own connection pooling and these underlying features like MARS/Pooling work against the adapter code.
153
+
154
+ Currently IronRuby is passing most of the ActiveRecord and Adapter tests. Here is a list of the ones remaining. Some are in the adapter's realm and some are in Marshaling area of IronRuby's core to fix. Feel like helping knock these out? Submit a patch to github issues.
155
+
156
+ http://gist.github.com/381101
157
+
158
+
145
159
  == Contributing
146
160
 
147
161
  If you’d like to contribute a feature or bugfix, thanks! To make sure your fix/feature has a high chance of being added, please read the following guidelines. First, ask on the Google list, IRC, or post a ticket on github issues. Second, make sure there are tests! We will not accept any patch that is not tested. Please read the RUNNING_UNIT_TESTS file for the details of how to run the unit tests.
@@ -34,9 +34,10 @@ test databases. Use an empty password for said user.
34
34
 
35
35
  == Running with Rake
36
36
 
37
- The easiest way to run the unit tests is through Rake. Either run "rake test_sqlserver"
38
- or "rake test_sqlserver_odbc". For more information, checkout the full array
39
- of rake tasks with "rake -T"
37
+ The easiest way to run the unit tests is through Rake. Either run "rake test" which
38
+ defaults to ODBC mode or being mode specific using either "rake sqlserver:test:adonet"
39
+ or "rake sqlserver:test:odbc". For more information, checkout the full array of rake tasks
40
+ with "rake -T"
40
41
 
41
42
  Rake can be found at http://rake.rubyforge.org
42
43
 
data/Rakefile CHANGED
@@ -4,38 +4,38 @@ require 'rake/rdoctask'
4
4
 
5
5
 
6
6
  namespace :sqlserver do
7
-
8
- ['sqlserver','sqlserver_odbc'].each do |adapter|
9
-
10
- Rake::TestTask.new("test_#{adapter}") do |t|
11
- t.libs << "test"
12
- t.libs << "test/connections/native_#{adapter}"
13
- t.libs << "../../../rails/activerecord/test/"
14
- t.test_files = (
15
- Dir.glob("test/cases/**/*_test_sqlserver.rb").sort +
16
- Dir.glob("../../../rails/activerecord/test/**/*_test.rb").sort )
17
- t.verbose = true
7
+
8
+ namespace :test do
9
+
10
+ ['odbc','adonet'].each do |mode|
11
+
12
+ Rake::TestTask.new(mode) do |t|
13
+ t.libs << "test"
14
+ t.libs << "test/connections/native_sqlserver#{mode == 'adonet' ? '' : "_#{mode}"}"
15
+ t.libs << "../../../rails/activerecord/test/"
16
+ t.test_files = (
17
+ Dir.glob("test/cases/**/*_test_sqlserver.rb").sort +
18
+ Dir.glob("../../../rails/activerecord/test/**/*_test.rb").sort )
19
+ t.verbose = true
20
+ end
21
+
18
22
  end
19
23
 
20
- namespace adapter do
21
- task :test => "test_#{adapter}"
24
+ desc 'Test with unicode types enabled, uses ODBC mode.'
25
+ task :unicode_types do
26
+ ENV['ENABLE_DEFAULT_UNICODE_TYPES'] = 'true'
27
+ test = Rake::Task['sqlserver:test:odbc']
28
+ test.invoke
22
29
  end
23
-
24
- end
25
-
26
- desc 'Test with unicode types enabled.'
27
- task :test_unicode_types do
28
- ENV['ENABLE_DEFAULT_UNICODE_TYPES'] = 'true'
29
- test = Rake::Task['sqlserver:test_sqlserver_odbc']
30
- test.invoke
30
+
31
31
  end
32
32
 
33
33
  end
34
34
 
35
35
 
36
- desc 'Test the default ODBC mode, taks sqlserver:test_sqlserver_odbc.'
36
+ desc 'Default runs tests for the adapters ODBC mode.'
37
37
  task :test do
38
- test = Rake::Task['sqlserver:test_sqlserver_odbc']
38
+ test = Rake::Task['sqlserver:test:odbc']
39
39
  test.invoke
40
40
  end
41
41
 
@@ -16,7 +16,9 @@ module ActiveRecord
16
16
  require_library_or_gem 'odbc' unless defined?(ODBC)
17
17
  require 'active_record/connection_adapters/sqlserver_adapter/core_ext/odbc'
18
18
  raise ArgumentError, 'Missing :dsn configuration.' unless config.has_key?(:dsn)
19
- config = config.slice :dsn, :username, :password
19
+ when :adonet
20
+ require 'System.Data'
21
+ raise ArgumentError, 'Missing :database configuration.' unless config.has_key?(:database)
20
22
  when :ado
21
23
  raise NotImplementedError, 'Please use version 2.3.1 of the adapter for ADO connections. Future versions may support ADO.NET.'
22
24
  raise ArgumentError, 'Missing :database configuration.' unless config.has_key?(:database)
@@ -54,10 +56,12 @@ module ActiveRecord
54
56
  end
55
57
 
56
58
  def string_to_binary(value)
59
+ value = value.dup.force_encoding(Encoding::BINARY) if value.respond_to?(:force_encoding)
57
60
  "0x#{value.unpack("H*")[0]}"
58
61
  end
59
62
 
60
63
  def binary_to_string(value)
64
+ value = value.dup.force_encoding(Encoding::BINARY) if value.respond_to?(:force_encoding)
61
65
  value =~ /[^[:xdigit:]]/ ? value : [value].pack('H*')
62
66
  end
63
67
 
@@ -159,17 +163,17 @@ module ActiveRecord
159
163
  class SQLServerAdapter < AbstractAdapter
160
164
 
161
165
  ADAPTER_NAME = 'SQLServer'.freeze
162
- VERSION = '2.3.4'.freeze
166
+ VERSION = '2.3.5'.freeze
163
167
  DATABASE_VERSION_REGEXP = /Microsoft SQL Server\s+(\d{4})/
164
168
  SUPPORTED_VERSIONS = [2000,2005,2008].freeze
165
169
  LIMITABLE_TYPES = ['string','integer','float','char','nchar','varchar','nvarchar'].freeze
166
170
  LOST_CONNECTION_EXCEPTIONS = {
167
- :odbc => ['ODBC::Error'],
168
- :ado => []
171
+ :odbc => ['ODBC::Error'],
172
+ :adonet => ['TypeError','System::Data::SqlClient::SqlException']
169
173
  }
170
174
  LOST_CONNECTION_MESSAGES = {
171
- :odbc => [/link failure/, /server failed/, /connection was already closed/, /invalid handle/i],
172
- :ado => []
175
+ :odbc => [/link failure/, /server failed/, /connection was already closed/, /invalid handle/i],
176
+ :adonet => [/current state is closed/, /network-related/]
173
177
  }
174
178
 
175
179
  cattr_accessor :native_text_database_type, :native_binary_database_type, :native_string_database_type,
@@ -316,11 +320,11 @@ module ActiveRecord
316
320
 
317
321
  # REFERENTIAL INTEGRITY ====================================#
318
322
 
319
- def disable_referential_integrity(&block)
320
- do_execute "EXEC sp_MSForEachTable 'ALTER TABLE ? NOCHECK CONSTRAINT ALL'"
323
+ def disable_referential_integrity
324
+ do_execute "EXEC sp_MSforeachtable 'ALTER TABLE ? NOCHECK CONSTRAINT ALL'"
321
325
  yield
322
326
  ensure
323
- do_execute "EXEC sp_MSForEachTable 'ALTER TABLE ? CHECK CONSTRAINT ALL'"
327
+ do_execute "EXEC sp_MSforeachtable 'ALTER TABLE ? CHECK CONSTRAINT ALL'"
324
328
  end
325
329
 
326
330
  # CONNECTION MANAGEMENT ====================================#
@@ -339,34 +343,14 @@ module ActiveRecord
339
343
  end
340
344
 
341
345
  def disconnect!
342
- raw_connection.disconnect rescue nil
343
- end
344
-
345
- def raw_connection_run(sql)
346
- with_auto_reconnect do
347
- case connection_mode
348
- when :odbc
349
- block_given? ? raw_connection.run_block(sql) { |handle| yield(handle) } : raw_connection.run(sql)
350
- else :ado
351
-
352
- end
353
- end
354
- end
355
-
356
- def raw_connection_do(sql)
357
346
  case connection_mode
358
347
  when :odbc
359
- raw_connection.do(sql)
360
- else :ado
361
-
348
+ raw_connection.disconnect rescue nil
349
+ else :adonet
350
+ raw_connection.close rescue nil
362
351
  end
363
352
  end
364
353
 
365
- def finish_statement_handle(handle)
366
- handle.drop if handle && handle.respond_to?(:drop) && !handle.finished?
367
- handle
368
- end
369
-
370
354
  # DATABASE STATEMENTS ======================================#
371
355
 
372
356
  def user_options
@@ -394,23 +378,26 @@ module ActiveRecord
394
378
  end
395
379
 
396
380
  def select_rows(sql, name = nil)
397
- raw_select(sql,name).last
381
+ raw_select(sql,name).first.last
398
382
  end
399
383
 
400
- def execute(sql, name = nil, &block)
384
+ def execute(sql, name = nil, skip_logging = false)
401
385
  if table_name = query_requires_identity_insert?(sql)
402
- handle = with_identity_insert_enabled(table_name) { raw_execute(sql,name,&block) }
386
+ with_identity_insert_enabled(table_name) { do_execute(sql,name) }
403
387
  else
404
- handle = raw_execute(sql,name,&block)
388
+ do_execute(sql,name)
405
389
  end
406
- finish_statement_handle(handle)
407
390
  end
408
391
 
409
392
  def execute_procedure(proc_name, *variables)
410
393
  vars = variables.map{ |v| quote(v) }.join(', ')
411
394
  sql = "EXEC #{proc_name} #{vars}".strip
412
395
  select(sql,'Execute Procedure',true).inject([]) do |results,row|
413
- results << row.with_indifferent_access
396
+ if row.kind_of?(Array)
397
+ results << row.inject([]) { |rs,r| rs << r.with_indifferent_access }
398
+ else
399
+ results << row.with_indifferent_access
400
+ end
414
401
  end
415
402
  end
416
403
 
@@ -649,10 +636,13 @@ module ActiveRecord
649
636
 
650
637
  def change_column(table_name, column_name, type, options = {})
651
638
  sql_commands = []
652
- remove_default_constraint(table_name, column_name)
639
+ column_object = columns(table_name).detect { |c| c.name.to_s == column_name.to_s }
653
640
  change_column_sql = "ALTER TABLE #{quote_table_name(table_name)} ALTER COLUMN #{quote_column_name(column_name)} #{type_to_sql(type, options[:limit], options[:precision], options[:scale])}"
654
641
  change_column_sql << " NOT NULL" if options[:null] == false
655
642
  sql_commands << change_column_sql
643
+ if options_include_default?(options) || (column_object && column_object.type != type.to_sym)
644
+ remove_default_constraint(table_name,column_name)
645
+ end
656
646
  if options_include_default?(options)
657
647
  remove_sqlserver_columns_cache_for(table_name)
658
648
  sql_commands << "ALTER TABLE #{quote_table_name(table_name)} ADD CONSTRAINT #{default_name(table_name,column_name)} DEFAULT #{quote(options[:default])} FOR #{quote_column_name(column_name)}"
@@ -773,8 +763,19 @@ module ActiveRecord
773
763
  @connection = case connection_mode
774
764
  when :odbc
775
765
  ODBC.connect config[:dsn], config[:username], config[:password]
776
- when :ado
777
-
766
+ when :adonet
767
+ System::Data::SqlClient::SqlConnection.new.tap do |connection|
768
+ connection.connection_string = System::Data::SqlClient::SqlConnectionStringBuilder.new.tap do |cs|
769
+ cs.user_i_d = config[:username] if config[:username]
770
+ cs.password = config[:password] if config[:password]
771
+ cs.integrated_security = true if config[:integrated_security] == 'true'
772
+ cs.add 'Server', config[:host].to_clr_string
773
+ cs.initial_catalog = config[:database]
774
+ cs.multiple_active_result_sets = false
775
+ cs.pooling = false
776
+ end.to_s
777
+ connection.open
778
+ end
778
779
  end
779
780
  rescue
780
781
  raise unless @auto_connecting
@@ -820,11 +821,50 @@ module ActiveRecord
820
821
  @auto_connecting = false
821
822
  end
822
823
 
824
+ def raw_connection_run(sql)
825
+ with_auto_reconnect do
826
+ case connection_mode
827
+ when :odbc
828
+ block_given? ? raw_connection.run_block(sql) { |handle| yield(handle) } : raw_connection.run(sql)
829
+ else :adonet
830
+ raw_connection.create_command.tap{ |cmd| cmd.command_text = sql }.execute_reader
831
+ end
832
+ end
833
+ end
834
+
835
+ def raw_connection_do(sql)
836
+ case connection_mode
837
+ when :odbc
838
+ raw_connection.do(sql)
839
+ else :adonet
840
+ raw_connection.create_command.tap{ |cmd| cmd.command_text = sql }.execute_non_query
841
+ end
842
+ end
843
+
844
+ def finish_statement_handle(handle)
845
+ case connection_mode
846
+ when :odbc
847
+ handle.drop if handle && handle.respond_to?(:drop) && !handle.finished?
848
+ when :adonet
849
+ handle.close if handle && handle.respond_to?(:close) && !handle.is_closed
850
+ handle.dispose if handle && handle.respond_to?(:dispose)
851
+ end
852
+ handle
853
+ end
854
+
823
855
  # DATABASE STATEMENTS ======================================
824
856
 
825
857
  def select(sql, name = nil, ignore_special_columns = false)
826
858
  repair_special_columns(sql) unless ignore_special_columns
827
- fields, rows = raw_select(sql,name)
859
+ fields_and_row_sets = raw_select(sql,name)
860
+ final_result_set = fields_and_row_sets.inject([]) do |rs,fields_and_rows|
861
+ fields, rows = fields_and_rows
862
+ rs << zip_fields_and_rows(fields,rows)
863
+ end
864
+ final_result_set.many? ? final_result_set : final_result_set.first
865
+ end
866
+
867
+ def zip_fields_and_rows(fields, rows)
828
868
  rows.inject([]) do |results,row|
829
869
  row_hash = {}
830
870
  fields.each_with_index do |f, i|
@@ -847,10 +887,6 @@ module ActiveRecord
847
887
  log_info_schema_queries ? yield : ActiveRecord::Base.silence{ yield }
848
888
  end
849
889
 
850
- def raw_execute(sql, name = nil, &block)
851
- log(sql,name) { raw_connection_run(sql) }
852
- end
853
-
854
890
  def do_execute(sql,name=nil)
855
891
  log(sql, name || 'EXECUTE') do
856
892
  with_auto_reconnect { raw_connection_do(sql) }
@@ -858,9 +894,41 @@ module ActiveRecord
858
894
  end
859
895
 
860
896
  def raw_select(sql, name = nil)
861
- handle = raw_execute(sql,name)
862
- fields = handle.columns(true).map{|c|c.name}
863
- results = handle_as_array(handle)
897
+ fields_and_row_sets = []
898
+ log(sql,name) do
899
+ begin
900
+ handle = raw_connection_run(sql)
901
+ loop do
902
+ fields_and_rows = case connection_mode
903
+ when :odbc
904
+ handle_to_fields_and_rows_odbc(handle)
905
+ when :adonet
906
+ handle_to_fields_and_rows_adonet(handle)
907
+ end
908
+ fields_and_row_sets << fields_and_rows
909
+ break unless handle_more_results?(handle)
910
+ end
911
+ ensure
912
+ finish_statement_handle(handle)
913
+ end
914
+ end
915
+ fields_and_row_sets
916
+ end
917
+
918
+ def handle_more_results?(handle)
919
+ case connection_mode
920
+ when :odbc
921
+ handle.more_results
922
+ when :adonet
923
+ handle.next_result
924
+ end
925
+ end
926
+
927
+ def handle_to_fields_and_rows_odbc(handle)
928
+ fields = handle.columns(true).map { |c| c.name }
929
+ results = handle.inject([]) do |rows,row|
930
+ rows << row.inject([]) { |values,value| values << value }
931
+ end
864
932
  rows = results.inject([]) do |rows,row|
865
933
  row.each_with_index do |value, i|
866
934
  if value.is_a? ODBC::TimeStamp
@@ -869,15 +937,37 @@ module ActiveRecord
869
937
  end
870
938
  rows << row
871
939
  end
872
- return fields, rows
873
- end
874
-
875
- def handle_as_array(handle)
876
- array = handle.inject([]) do |rows,row|
877
- rows << row.inject([]){ |values,value| values << value }
940
+ [fields,rows]
941
+ end
942
+
943
+ def handle_to_fields_and_rows_adonet(handle)
944
+ if handle.has_rows
945
+ fields = []
946
+ rows = []
947
+ fields_named = false
948
+ while handle.read
949
+ row = []
950
+ handle.visible_field_count.times do |row_index|
951
+ value = handle.get_value(row_index)
952
+ value = if value.is_a? System::String
953
+ value.to_s
954
+ elsif value.is_a? System::DBNull
955
+ nil
956
+ elsif value.is_a? System::DateTime
957
+ value.to_string("yyyy-MM-dd HH:MM:ss.fff").to_s
958
+ else
959
+ value
960
+ end
961
+ row << value
962
+ fields << handle.get_name(row_index).to_s unless fields_named
963
+ end
964
+ rows << row
965
+ fields_named = true
966
+ end
967
+ else
968
+ fields, rows = [], []
878
969
  end
879
- finish_statement_handle(handle)
880
- array
970
+ [fields,rows]
881
971
  end
882
972
 
883
973
  def add_limit_offset_for_association_limiting!(sql, options)
@@ -924,7 +1014,7 @@ module ActiveRecord
924
1014
 
925
1015
  # IDENTITY INSERTS =========================================#
926
1016
 
927
- def with_identity_insert_enabled(table_name, &block)
1017
+ def with_identity_insert_enabled(table_name)
928
1018
  table_name = quote_table_name(table_name_or_views_table_name(table_name))
929
1019
  set_identity_insert(table_name, true)
930
1020
  yield
@@ -1031,6 +1121,7 @@ module ActiveRecord
1031
1121
 
1032
1122
  def column_definitions(table_name)
1033
1123
  db_name = unqualify_db_name(table_name)
1124
+ db_name_with_period = "#{db_name}." if db_name
1034
1125
  table_name = unqualify_table_name(table_name)
1035
1126
  sql = %{
1036
1127
  SELECT
@@ -1052,7 +1143,7 @@ module ActiveRecord
1052
1143
  WHEN COLUMNPROPERTY(OBJECT_ID(columns.TABLE_SCHEMA+'.'+columns.TABLE_NAME), columns.COLUMN_NAME, 'IsIdentity') = 0 THEN NULL
1053
1144
  ELSE 1
1054
1145
  END as is_identity
1055
- FROM #{db_name}INFORMATION_SCHEMA.COLUMNS columns
1146
+ FROM #{db_name_with_period}INFORMATION_SCHEMA.COLUMNS columns
1056
1147
  WHERE columns.TABLE_NAME = '#{table_name}'
1057
1148
  ORDER BY columns.ordinal_position
1058
1149
  }.gsub(/[ \t\r\n]+/,' ')
@@ -1072,7 +1163,7 @@ module ActiveRecord
1072
1163
  if ci[:default_value].nil? && views.include?(table_name)
1073
1164
  real_table_name = table_name_or_views_table_name(table_name)
1074
1165
  real_column_name = views_real_column_name(table_name,ci[:name])
1075
- col_default_sql = "SELECT c.COLUMN_DEFAULT FROM INFORMATION_SCHEMA.COLUMNS c WHERE c.TABLE_NAME = '#{real_table_name}' AND c.COLUMN_NAME = '#{real_column_name}'"
1166
+ col_default_sql = "SELECT c.COLUMN_DEFAULT FROM #{db_name_with_period}INFORMATION_SCHEMA.COLUMNS c WHERE c.TABLE_NAME = '#{real_table_name}' AND c.COLUMN_NAME = '#{real_column_name}'"
1076
1167
  ci[:default_value] = info_schema_query { select_value(col_default_sql) }
1077
1168
  end
1078
1169
  ci[:default_value] = case ci[:default_value]
@@ -20,7 +20,6 @@ module ActiveRecord
20
20
  true
21
21
  end
22
22
  end
23
-
24
23
  end
25
24
 
26
25
  module Database
@@ -13,9 +13,9 @@ class ConnectionTestSqlserver < ActiveRecord::TestCase
13
13
 
14
14
 
15
15
  should 'return finished ODBC statment handle from #execute without block' do
16
- handle = @connection.execute('SELECT * FROM [topics]')
17
- assert_instance_of ODBC::Statement, handle
18
- assert handle.finished?
16
+ assert_all_statements_used_are_closed do
17
+ @connection.execute('SELECT * FROM [topics]')
18
+ end
19
19
  end
20
20
 
21
21
  should 'finish ODBC statment handle from #execute with block' do
@@ -24,12 +24,6 @@ class ConnectionTestSqlserver < ActiveRecord::TestCase
24
24
  end
25
25
  end
26
26
 
27
- should 'return an unfinished ODBC statement handler from #raw_execute' do
28
- handle = @connection.send(:raw_execute,'SELECT * FROM [topics]')
29
- assert_instance_of ODBC::Statement, handle
30
- assert !handle.finished?
31
- end
32
-
33
27
  should 'finish connection from #raw_select' do
34
28
  assert_all_statements_used_are_closed do
35
29
  @connection.send(:raw_select,'SELECT * FROM [topics]')
@@ -29,5 +29,16 @@ class ExecuteProcedureTestSqlserver < ActiveRecord::TestCase
29
29
  end if sqlserver_2000?
30
30
  end
31
31
 
32
+ should 'allow multiple result sets to be returned' do
33
+ results1, results2 = @klass.execute_procedure('sp_helpconstraint','accounts')
34
+ assert_instance_of Array, results1
35
+ assert_instance_of HashWithIndifferentAccess, results1.first
36
+ assert results1.first['Object Name']
37
+ assert_instance_of Array, results2
38
+ assert_instance_of HashWithIndifferentAccess, results2.first
39
+ assert results2.first['constraint_name']
40
+ assert results2.first['constraint_type']
41
+ end
42
+
32
43
 
33
44
  end
@@ -46,9 +46,21 @@ class MigrationTestSqlserver < ActiveRecord::TestCase
46
46
  assert lock_version_column.default.nil?
47
47
  end
48
48
 
49
+ should 'not drop the default contraint if just renaming' do
50
+ find_default = lambda do
51
+ @connection.select_all("EXEC sp_helpconstraint 'defaults','nomsg'").select do |row|
52
+ row['constraint_type'] == "DEFAULT on column decimal_number"
53
+ end.last
54
+ end
55
+ default_before = find_default.call
56
+ @connection.change_column :defaults, :decimal_number, :decimal, :precision => 4
57
+ default_after = find_default.call
58
+ assert default_after
59
+ assert_equal default_before['constraint_keys'], default_after['constraint_keys']
60
+ end
61
+
49
62
  end
50
63
 
51
-
52
64
  end
53
65
 
54
66
 
@@ -1,6 +1,10 @@
1
1
  require 'rubygems'
2
2
  require 'shoulda'
3
3
  require 'mocha'
4
+ [ File.expand_path(File.join(File.dirname(__FILE__),'..','..','test')),
5
+ File.expand_path(File.join(File.dirname(__FILE__),'..','..','test','connections','native_sqlserver_odbc')),
6
+ File.expand_path(File.join(File.dirname(__FILE__),'..','..','..','..','..','rails','activerecord','test'))
7
+ ].each{ |lib| $:.unshift(lib) unless $:.include?(lib) } if ENV['TM_DIRECTORY']
4
8
  require 'cases/helper'
5
9
  require 'models/topic'
6
10
  require 'active_record/version'
@@ -1,4 +1,4 @@
1
- print "Using native SQLServer\n"
1
+ print "Using SQLServer via ADONET\n"
2
2
  require_dependency 'models/course'
3
3
  require 'logger'
4
4
 
@@ -7,12 +7,14 @@ ActiveRecord::Base.logger = Logger.new("debug.log")
7
7
  ActiveRecord::Base.configurations = {
8
8
  'arunit' => {
9
9
  :adapter => 'sqlserver',
10
+ :mode => 'ADONET',
10
11
  :host => 'localhost',
11
12
  :username => 'rails',
12
13
  :database => 'activerecord_unittest'
13
14
  },
14
15
  'arunit2' => {
15
16
  :adapter => 'sqlserver',
17
+ :mode => 'ADONET',
16
18
  :host => 'localhost',
17
19
  :username => 'rails',
18
20
  :database => 'activerecord_unittest2'
@@ -1,4 +1,4 @@
1
- print "Using native SQLServer via ODBC\n"
1
+ print "Using SQLServer via ODBC\n"
2
2
  require_dependency 'models/course'
3
3
  require 'logger'
4
4
 
metadata CHANGED
@@ -1,7 +1,12 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activerecord-sqlserver-adapter
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.3.4
4
+ prerelease: false
5
+ segments:
6
+ - 2
7
+ - 3
8
+ - 5
9
+ version: 2.3.5
5
10
  platform: ruby
6
11
  authors:
7
12
  - Ken Collins
@@ -54,18 +59,20 @@ required_ruby_version: !ruby/object:Gem::Requirement
54
59
  requirements:
55
60
  - - ">="
56
61
  - !ruby/object:Gem::Version
62
+ segments:
63
+ - 0
57
64
  version: "0"
58
- version:
59
65
  required_rubygems_version: !ruby/object:Gem::Requirement
60
66
  requirements:
61
67
  - - ">="
62
68
  - !ruby/object:Gem::Version
69
+ segments:
70
+ - 0
63
71
  version: "0"
64
- version:
65
72
  requirements: []
66
73
 
67
74
  rubyforge_project:
68
- rubygems_version: 1.3.5
75
+ rubygems_version: 1.3.6
69
76
  signing_key:
70
77
  specification_version: 3
71
78
  summary: SQL Server 2000, 2005 and 2008 Adapter For Rails.