activerecord-sqlserver-adapter 2.3.8 → 2.3.9

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG CHANGED
@@ -1,5 +1,20 @@
1
1
 
2
- MASTER
2
+
3
+ * 2.3.9
4
+
5
+ * Support DSN'less connections. Resolves ticket 38.
6
+
7
+ * Support upcoming ruby odbc 0.99992
8
+
9
+ * Include new raw connection interfaces developed and optimized under the 3.0 branch.
10
+
11
+ * The remove_column conforms to ArgumentError exceptions. [Ken Collins]
12
+
13
+ * Add support for default function values in schema reflection. Allows for uniqueidentifier default
14
+ values like NEWID(). These are not automatically inserted into the INSERT statement as of yet, that
15
+ could be done user side on a before save callback now. Includes new #newid_function and
16
+ #newsequentialid_function on the connection for helping. Resolves tikcet #42. [Ken Collins]
17
+
3
18
 
4
19
  * 2.3.8
5
20
 
@@ -11,55 +11,17 @@ assumes you have a DSN setup that matches the name of the default database names
11
11
 
12
12
  == Requirements
13
13
 
14
- The following gems need to be installed. Make sure you have gems.github.com as a
15
- source. Info here. http://gems.github.com/
16
-
17
- We use echoe for packagemanagement to rubyforge. Not needed really for the tests
18
- but since we need it... you need to install it.
19
-
20
- * gem install echoe
21
- * gem install thoughtbot-shoulda -s http://gems.github.com
14
+ * gem install shoulda
22
15
  * gem install mocha
23
16
 
24
- The tests of this adapter depend on the existence of rails checkout. All the tests
25
- defined by rails are re-used. For this to work the following directory structure
26
- is assumed to exist:
27
-
28
- #{RAILS_ROOT}/vendor/plugins/adapters/sqlserver
29
- #{RAILS_ROOT}/vendor/rails/activerecord/test
17
+ The tests of this adapter depend on the existence of rails checkout. Make sure
18
+ to checkout remotes/origin/2-3-stable, then make sure to export RAILS_SOURCE to
19
+ the full path of that repo.
30
20
 
31
21
  Define a user named 'rails' in SQL Server with all privileges granted for the
32
22
  test databases. Use an empty password for said user.
33
23
 
34
24
 
35
- == Running with Rake
36
-
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"
41
-
42
- Rake can be found at http://rake.rubyforge.org
43
-
44
-
45
- == Running with Autotest
46
-
47
- Using autotest is easy, just run "autotest" and the tests will run continually in the
48
- same order as the rake test command. By default autotest will use ODBC connection. If
49
- you want to change this you can edit the autotest/sqlserver.rb file and set odbc_mode
50
- to false.
51
-
52
- Lastly, you can run autotest on just the adapter specific tests with "autotest sqlserver".
53
- This will continuously run ONLY the SQL Sever specific behavior tests which are much
54
- quicker to run than the entire active record test suite.
55
-
56
-
57
- == Running by hand
58
25
 
59
- Unit tests are located in test directory. If you only want to run a single test suite,
60
- you can do so with:
61
26
 
62
- rake test_sqlserver TEST=base_test.rb
63
-
64
- That'll run the base suite using the SQLServer-Ruby adapter.
65
27
 
data/Rakefile CHANGED
@@ -3,39 +3,65 @@ require 'rake/testtask'
3
3
  require 'rake/rdoctask'
4
4
 
5
5
 
6
- namespace :sqlserver do
6
+ def test_libs(mode='odbc')
7
+ ['lib',
8
+ 'test',
9
+ "test/connections/native_sqlserver#{mode == 'adonet' ? '' : "_#{mode}"}",
10
+ "#{ENV['RAILS_SOURCE']}/activerecord/test"]
11
+ end
12
+
13
+ def test_files
14
+ Dir.glob("test/cases/**/*_test_sqlserver.rb").sort +
15
+ (Dir.glob("#{ENV['RAILS_SOURCE']}/activerecord/test/cases/**/*_test.rb") -
16
+ Dir.glob("#{ENV['RAILS_SOURCE']}/activerecord/test/cases/adapters/**/*_test.rb")).sort
17
+ end
18
+
19
+
20
+ task :test => ['test:odbc']
21
+
22
+
23
+ namespace :test do
7
24
 
8
- namespace :test do
25
+ ['odbc','adonet'].each do |mode|
9
26
 
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
-
22
- end
23
-
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
27
+ Rake::TestTask.new(mode) do |t|
28
+ t.libs = test_libs(mode)
29
+ t.test_files = test_files
30
+ t.verbose = true
29
31
  end
30
32
 
31
33
  end
34
+
35
+ desc 'Test without unicode types enabled, uses ODBC mode.'
36
+ task :non_unicode_types do
37
+ ENV['ENABLE_DEFAULT_UNICODE_TYPES'] = 'false'
38
+ test = Rake::Task['test:odbc']
39
+ test.invoke
40
+ end
32
41
 
33
42
  end
34
43
 
35
44
 
36
- desc 'Default runs tests for the adapters ODBC mode.'
37
- task :test do
38
- test = Rake::Task['sqlserver:test:odbc']
39
- test.invoke
45
+ namespace :profile do
46
+
47
+ ['odbc','adonet'].each do |mode|
48
+ namespace mode.to_sym do
49
+
50
+ Dir.glob("test/profile/*_profile_case.rb").sort.each do |test_file|
51
+
52
+ profile_case = File.basename(test_file).sub('_profile_case.rb','')
53
+
54
+ Rake::TestTask.new(profile_case) do |t|
55
+ t.libs = test_libs(mode)
56
+ t.test_files = [test_file]
57
+ t.verbose = true
58
+ end
59
+
60
+ end
61
+
62
+ end
63
+ end
64
+
40
65
  end
41
66
 
67
+
@@ -20,7 +20,7 @@ module ActiveRecord
20
20
  require 'System.Data'
21
21
  raise ArgumentError, 'Missing :database configuration.' unless config.has_key?(:database)
22
22
  when :ado
23
- raise NotImplementedError, 'Please use version 2.3.1 of the adapter for ADO connections. Future versions may support ADO.NET.'
23
+ raise NotImplementedError, 'Please use version 2.3.1 of the adapter for ADO connections. Future versions support ADO.NET.'
24
24
  raise ArgumentError, 'Missing :database configuration.' unless config.has_key?(:database)
25
25
  else
26
26
  raise ArgumentError, "Unknown connection mode in #{config.inspect}."
@@ -45,7 +45,7 @@ module ActiveRecord
45
45
  class SQLServerColumn < Column
46
46
 
47
47
  def initialize(name, default, sql_type = nil, null = true, sqlserver_options = {})
48
- @sqlserver_options = sqlserver_options
48
+ @sqlserver_options = sqlserver_options.symbolize_keys
49
49
  super(name, default, sql_type, null)
50
50
  end
51
51
 
@@ -88,12 +88,15 @@ module ActiveRecord
88
88
  end
89
89
 
90
90
  def is_special?
91
- # TODO: Not sure if these should be added: varbinary(max), nchar, nvarchar(max)
92
- sql_type =~ /^text|ntext|image$/
91
+ @sql_type =~ /^text|ntext|image$/
93
92
  end
94
93
 
95
94
  def is_utf8?
96
- sql_type =~ /nvarchar|ntext|nchar/i
95
+ @sql_type =~ /nvarchar|ntext|nchar/i
96
+ end
97
+
98
+ def default_function
99
+ @sqlserver_options[:default_function]
97
100
  end
98
101
 
99
102
  def table_name
@@ -170,10 +173,11 @@ module ActiveRecord
170
173
  class SQLServerAdapter < AbstractAdapter
171
174
 
172
175
  ADAPTER_NAME = 'SQLServer'.freeze
173
- VERSION = '2.3.8'.freeze
176
+ VERSION = '2.3.9'.freeze
174
177
  DATABASE_VERSION_REGEXP = /Microsoft SQL Server\s+(\d{4})/
175
178
  SUPPORTED_VERSIONS = [2000,2005,2008].freeze
176
- LIMITABLE_TYPES = ['string','integer','float','char','nchar','varchar','nvarchar'].freeze
179
+ LIMITABLE_TYPES = ['string','integer','float','char','nchar','varchar','nvarchar'].to_set.freeze
180
+ QUOTED_TRUE, QUOTED_FALSE = '1', '0'
177
181
  LOST_CONNECTION_EXCEPTIONS = {
178
182
  :odbc => ['ODBC::Error'],
179
183
  :adonet => ['TypeError','System::Data::SqlClient::SqlException']
@@ -183,6 +187,8 @@ module ActiveRecord
183
187
  :adonet => [/current state is closed/, /network-related/]
184
188
  }
185
189
 
190
+ attr_reader :database_version, :database_year,
191
+ :connection_supports_native_types
186
192
  cattr_accessor :native_text_database_type, :native_binary_database_type, :native_string_database_type,
187
193
  :log_info_schema_queries, :enable_default_unicode_types, :auto_connect
188
194
 
@@ -197,10 +203,13 @@ module ActiveRecord
197
203
  def initialize(logger,config)
198
204
  @connection_options = config
199
205
  connect
200
- super(raw_connection, logger)
206
+ super(@connection, logger)
207
+ @database_version = info_schema_query { select_value('SELECT @@version') }
208
+ @database_year = DATABASE_VERSION_REGEXP.match(@database_version)[1].to_i rescue 0
209
+ initialize_native_database_types
201
210
  initialize_sqlserver_caches
202
211
  use_database
203
- unless SUPPORTED_VERSIONS.include?(database_year)
212
+ unless SUPPORTED_VERSIONS.include?(@database_year)
204
213
  raise NotImplementedError, "Currently, only #{SUPPORTED_VERSIONS.to_sentence} are supported."
205
214
  end
206
215
  end
@@ -223,28 +232,20 @@ module ActiveRecord
223
232
  true
224
233
  end
225
234
 
226
- def database_version
227
- @database_version ||= info_schema_query { select_value('SELECT @@version') }
228
- end
229
-
230
- def database_year
231
- DATABASE_VERSION_REGEXP.match(database_version)[1].to_i
232
- end
233
-
234
235
  def sqlserver?
235
236
  true
236
237
  end
237
238
 
238
239
  def sqlserver_2000?
239
- database_year == 2000
240
+ @database_year == 2000
240
241
  end
241
242
 
242
243
  def sqlserver_2005?
243
- database_year == 2005
244
+ @database_year == 2005
244
245
  end
245
246
 
246
247
  def sqlserver_2008?
247
- database_year == 2008
248
+ @database_year == 2008
248
249
  end
249
250
 
250
251
  def version
@@ -252,7 +253,7 @@ module ActiveRecord
252
253
  end
253
254
 
254
255
  def inspect
255
- "#<#{self.class} version: #{version}, year: #{database_year}, connection_options: #{@connection_options.inspect}>"
256
+ "#<#{self.class} version: #{version}, year: #{@database_year}, connection_options: #{@connection_options.inspect}>"
256
257
  end
257
258
 
258
259
  def auto_connect
@@ -306,21 +307,21 @@ module ActiveRecord
306
307
  string.to_s.gsub(/\'/, "''")
307
308
  end
308
309
 
309
- def quote_column_name(column_name)
310
- column_name.to_s.split('.').map{ |name| name =~ /^\[.*\]$/ ? name : "[#{name}]" }.join('.')
310
+ def quote_column_name(name)
311
+ @sqlserver_quoted_column_and_table_names[name] ||=
312
+ name.to_s.split('.').map{ |n| n =~ /^\[.*\]$/ ? n : "[#{n}]" }.join('.')
311
313
  end
312
314
 
313
- def quote_table_name(table_name)
314
- return table_name if table_name =~ /^\[.*\]$/
315
- quote_column_name(table_name)
315
+ def quote_table_name(name)
316
+ quote_column_name(name)
316
317
  end
317
318
 
318
319
  def quoted_true
319
- '1'
320
+ QUOTED_TRUE
320
321
  end
321
322
 
322
323
  def quoted_false
323
- '0'
324
+ QUOTED_FALSE
324
325
  end
325
326
 
326
327
  def quoted_date(value)
@@ -360,11 +361,11 @@ module ActiveRecord
360
361
  end
361
362
 
362
363
  def disconnect!
363
- case connection_mode
364
+ case @connection_options[:mode]
364
365
  when :odbc
365
- raw_connection.disconnect rescue nil
366
+ @connection.disconnect rescue nil
366
367
  else :adonet
367
- raw_connection.close rescue nil
368
+ @connection.close rescue nil
368
369
  end
369
370
  end
370
371
 
@@ -394,8 +395,22 @@ module ActiveRecord
394
395
  end if block_given?
395
396
  end
396
397
 
398
+ def select_one(sql, name = nil)
399
+ result = raw_select sql, name, :fetch => :one
400
+ (result && result.first.present?) ? result.first : nil
401
+ end
402
+
403
+ def select_one_with_query_cache(*args)
404
+ if @query_cache_enabled
405
+ cache_sql(args.first) { select_one_without_query_cache(*args) }
406
+ else
407
+ select_one_without_query_cache(*args)
408
+ end
409
+ end
410
+ alias_method_chain :select_one, :query_cache
411
+
397
412
  def select_rows(sql, name = nil)
398
- raw_select(sql,name).first.last
413
+ raw_select sql, name, :fetch => :rows
399
414
  end
400
415
 
401
416
  def execute(sql, name = nil, skip_logging = false)
@@ -409,13 +424,21 @@ module ActiveRecord
409
424
  def execute_procedure(proc_name, *variables)
410
425
  vars = variables.map{ |v| quote(v) }.join(', ')
411
426
  sql = "EXEC #{proc_name} #{vars}".strip
412
- select(sql,'Execute Procedure',true).inject([]) do |results,row|
413
- if row.kind_of?(Array)
414
- results << row.inject([]) { |rs,r| rs << r.with_indifferent_access }
415
- else
416
- results << row.with_indifferent_access
427
+ results = []
428
+ log(sql,'Execute Procedure') do
429
+ raw_connection_run(sql) do |handle|
430
+ get_rows = lambda {
431
+ rows = handle_to_names_and_values handle, :fetch => :all
432
+ rows.each_with_index { |r,i| rows[i] = r.with_indifferent_access }
433
+ results << rows
434
+ }
435
+ get_rows.call
436
+ while handle_more_results?(handle)
437
+ get_rows.call
438
+ end
417
439
  end
418
440
  end
441
+ results.many? ? results : results.first
419
442
  end
420
443
 
421
444
  def use_database(database=nil)
@@ -537,30 +560,18 @@ module ActiveRecord
537
560
  "WHERE #{quoted_primary_key} IN (SELECT #{limit} #{quoted_primary_key} FROM #{quoted_table_name} #{where_sql})"
538
561
  end
539
562
 
563
+ def newid_function
564
+ select_value "SELECT NEWID()"
565
+ end
566
+
567
+ def newsequentialid_function
568
+ select_value "SELECT NEWSEQUENTIALID()"
569
+ end
570
+
540
571
  # SCHEMA STATEMENTS ========================================#
541
572
 
542
573
  def native_database_types
543
- {
544
- :primary_key => "int NOT NULL IDENTITY(1, 1) PRIMARY KEY",
545
- :string => { :name => native_string_database_type, :limit => 255 },
546
- :text => { :name => native_text_database_type },
547
- :integer => { :name => "int", :limit => 4 },
548
- :float => { :name => "float", :limit => 8 },
549
- :decimal => { :name => "decimal" },
550
- :datetime => { :name => "datetime" },
551
- :timestamp => { :name => "datetime" },
552
- :time => { :name => native_time_database_type },
553
- :date => { :name => native_date_database_type },
554
- :binary => { :name => native_binary_database_type },
555
- :boolean => { :name => "bit"},
556
- # These are custom types that may move somewhere else for good schema_dumper.rb hacking to output them.
557
- :char => { :name => 'char' },
558
- :varchar_max => { :name => 'varchar(max)' },
559
- :nchar => { :name => "nchar" },
560
- :nvarchar => { :name => "nvarchar", :limit => 255 },
561
- :nvarchar_max => { :name => "nvarchar(max)" },
562
- :ntext => { :name => "ntext" }
563
- }
574
+ ActiveRecord::ConnectionAdapters::SQLServerAdapter::NATIVE_DATABASE_TYPES
564
575
  end
565
576
 
566
577
  def table_alias_length
@@ -583,8 +594,9 @@ module ActiveRecord
583
594
  @sqlserver_view_information_cache[table_name] ||= begin
584
595
  view_info = info_schema_query { select_one("SELECT * FROM INFORMATION_SCHEMA.VIEWS WHERE TABLE_NAME = '#{table_name}'") }
585
596
  if view_info
586
- if view_info['VIEW_DEFINITION'].blank? || view_info['VIEW_DEFINITION'].length == 4000
587
- view_info['VIEW_DEFINITION'] = info_schema_query { select_values("EXEC sp_helptext #{table_name}").join }
597
+ view_info = view_info.with_indifferent_access
598
+ if view_info[:VIEW_DEFINITION].blank? || view_info[:VIEW_DEFINITION].length == 4000
599
+ view_info[:VIEW_DEFINITION] = info_schema_query { select_values("EXEC sp_helptext #{table_name}").join }
588
600
  end
589
601
  end
590
602
  view_info
@@ -603,12 +615,13 @@ module ActiveRecord
603
615
  def indexes(table_name, name = nil)
604
616
  unquoted_table_name = unqualify_table_name(table_name)
605
617
  select("EXEC sp_helpindex #{quote_table_name(unquoted_table_name)}",name).inject([]) do |indexes,index|
606
- if index['index_description'] =~ /primary key/
618
+ index = index.with_indifferent_access
619
+ if index[:index_description] =~ /primary key/
607
620
  indexes
608
621
  else
609
- name = index['index_name']
610
- unique = index['index_description'] =~ /unique/
611
- columns = index['index_keys'].split(',').map do |column|
622
+ name = index[:index_name]
623
+ unique = index[:index_description] =~ /unique/
624
+ columns = index[:index_keys].split(',').map do |column|
612
625
  column.strip!
613
626
  column.gsub! '(-)', '' if column.ends_with?('(-)')
614
627
  column
@@ -647,6 +660,7 @@ module ActiveRecord
647
660
  end
648
661
 
649
662
  def remove_column(table_name, *column_names)
663
+ raise ArgumentError.new("You must specify at least one column name. Example: remove_column(:people, :first_name)") if column_names.empty?
650
664
  column_names.flatten.each do |column_name|
651
665
  remove_check_constraints(table_name, column_name)
652
666
  remove_default_constraint(table_name, column_name)
@@ -798,9 +812,23 @@ module ActiveRecord
798
812
 
799
813
  def connect
800
814
  config = @connection_options
801
- @connection = case connection_mode
815
+ @connection = case @connection_options[:mode]
802
816
  when :odbc
803
- ODBC.connect config[:dsn], config[:username], config[:password]
817
+ if config[:dsn].include?(';')
818
+ driver = ODBC::Driver.new.tap do |d|
819
+ d.name = config[:dsn_name] || 'Driver1'
820
+ driver.attrs = dsn.split(';').map{ |atr| atr.split('=') }.reject{ |kv| kv.size != 2 }.inject({}){ |h,kv| k,v = kv ; h[k] = v ; h }
821
+ end
822
+ ODBC::Database.new.drvconnect(driver)
823
+ else
824
+ ODBC.connect config[:dsn], config[:username], config[:password]
825
+ end.tap do |c|
826
+ if c.respond_to?(:use_time)
827
+ c.use_time = true
828
+ c.use_utc = ActiveRecord::Base.default_timezone == :utc
829
+ @connection_supports_native_types = true
830
+ end
831
+ end
804
832
  when :adonet
805
833
  System::Data::SqlClient::SqlConnection.new.tap do |connection|
806
834
  connection.connection_string = System::Data::SqlClient::SqlConnectionStringBuilder.new.tap do |cs|
@@ -822,17 +850,13 @@ module ActiveRecord
822
850
  raise unless @auto_connecting
823
851
  end
824
852
 
825
- def connection_mode
826
- @connection_options[:mode]
827
- end
828
-
829
853
  def lost_connection_exceptions
830
- exceptions = LOST_CONNECTION_EXCEPTIONS[connection_mode]
854
+ exceptions = LOST_CONNECTION_EXCEPTIONS[@connection_options[:mode]]
831
855
  @lost_connection_exceptions ||= exceptions ? exceptions.map(&:constantize) : []
832
856
  end
833
857
 
834
858
  def lost_connection_messages
835
- LOST_CONNECTION_MESSAGES[connection_mode]
859
+ LOST_CONNECTION_MESSAGES[@connection_options[:mode]]
836
860
  end
837
861
 
838
862
  def with_auto_reconnect
@@ -864,26 +888,26 @@ module ActiveRecord
864
888
 
865
889
  def raw_connection_run(sql)
866
890
  with_auto_reconnect do
867
- case connection_mode
891
+ case @connection_options[:mode]
868
892
  when :odbc
869
- block_given? ? raw_connection.run_block(sql) { |handle| yield(handle) } : raw_connection.run(sql)
893
+ block_given? ? @connection.run_block(sql) { |handle| yield(handle) } : @connection.run(sql)
870
894
  else :adonet
871
- raw_connection.create_command.tap{ |cmd| cmd.command_text = sql }.execute_reader
895
+ @connection.create_command.tap{ |cmd| cmd.command_text = sql }.execute_reader
872
896
  end
873
897
  end
874
898
  end
875
899
 
876
900
  def raw_connection_do(sql)
877
- case connection_mode
901
+ case @connection_options[:mode]
878
902
  when :odbc
879
- raw_connection.do(sql)
903
+ @connection.do(sql)
880
904
  else :adonet
881
- raw_connection.create_command.tap{ |cmd| cmd.command_text = sql }.execute_non_query
905
+ @connection.create_command.tap{ |cmd| cmd.command_text = sql }.execute_non_query
882
906
  end
883
907
  end
884
908
 
885
909
  def finish_statement_handle(handle)
886
- case connection_mode
910
+ case @connection_options[:mode]
887
911
  when :odbc
888
912
  handle.drop if handle && handle.respond_to?(:drop) && !handle.finished?
889
913
  when :adonet
@@ -895,24 +919,8 @@ module ActiveRecord
895
919
 
896
920
  # DATABASE STATEMENTS ======================================
897
921
 
898
- def select(sql, name = nil, ignore_special_columns = false)
899
- repair_special_columns(sql) unless ignore_special_columns
900
- fields_and_row_sets = raw_select(sql,name)
901
- final_result_set = fields_and_row_sets.inject([]) do |rs,fields_and_rows|
902
- fields, rows = fields_and_rows
903
- rs << zip_fields_and_rows(fields,rows)
904
- end
905
- final_result_set.many? ? final_result_set : final_result_set.first
906
- end
907
-
908
- def zip_fields_and_rows(fields, rows)
909
- rows.inject([]) do |results,row|
910
- row_hash = {}
911
- fields.each_with_index do |f, i|
912
- row_hash[f] = row[i]
913
- end
914
- results << row_hash
915
- end
922
+ def select(sql, name = nil)
923
+ raw_select sql, name, :fetch => :all
916
924
  end
917
925
 
918
926
  def insert_sql(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil)
@@ -934,30 +942,19 @@ module ActiveRecord
934
942
  end
935
943
  end
936
944
 
937
- def raw_select(sql, name = nil)
938
- fields_and_row_sets = []
945
+ def raw_select(sql, name=nil, options={})
939
946
  log(sql,name) do
940
947
  begin
941
948
  handle = raw_connection_run(sql)
942
- loop do
943
- fields_and_rows = case connection_mode
944
- when :odbc
945
- handle_to_fields_and_rows_odbc(handle)
946
- when :adonet
947
- handle_to_fields_and_rows_adonet(handle)
948
- end
949
- fields_and_row_sets << fields_and_rows
950
- break unless handle_more_results?(handle)
951
- end
949
+ handle_to_names_and_values(handle, options)
952
950
  ensure
953
951
  finish_statement_handle(handle)
954
952
  end
955
953
  end
956
- fields_and_row_sets
957
954
  end
958
955
 
959
956
  def handle_more_results?(handle)
960
- case connection_mode
957
+ case @connection_options[:mode]
961
958
  when :odbc
962
959
  handle.more_results
963
960
  when :adonet
@@ -965,50 +962,109 @@ module ActiveRecord
965
962
  end
966
963
  end
967
964
 
968
- def handle_to_fields_and_rows_odbc(handle)
969
- fields = handle.columns(true).map { |c| c.name }
970
- results = handle.inject([]) do |rows,row|
971
- rows << row.inject([]) { |values,value| values << value }
965
+ def handle_to_names_and_values(handle, options={})
966
+ case @connection_options[:mode]
967
+ when :odbc
968
+ handle_to_names_and_values_odbc(handle, options)
969
+ when :adonet
970
+ handle_to_names_and_values_adonet(handle, options)
972
971
  end
973
- rows = results.inject([]) do |rows,row|
974
- row.each_with_index do |value, i|
975
- if value.is_a? ODBC::TimeStamp
976
- row[i] = value.to_sqlserver_string
972
+ end
973
+
974
+ def handle_to_names_and_values_odbc(handle, options={})
975
+ @connection.use_utc = ActiveRecord::Base.default_timezone == :utc if @connection_supports_native_types
976
+ case options[:fetch]
977
+ when :all, :one
978
+ if @connection_supports_native_types
979
+ if options[:fetch] == :all
980
+ handle.each_hash || []
981
+ else
982
+ row = handle.fetch_hash
983
+ rows = row ? [row] : [[]]
984
+ end
985
+ else
986
+ rows = if options[:fetch] == :all
987
+ handle.fetch_all || []
988
+ else
989
+ row = handle.fetch
990
+ row ? [row] : [[]]
991
+ end
992
+ names = handle.columns(true).map{ |c| c.name }
993
+ names_and_values = []
994
+ rows.each do |row|
995
+ h = {}
996
+ i = 0
997
+ while i < row.size
998
+ v = row[i]
999
+ h[names[i]] = v.respond_to?(:to_sqlserver_string) ? v.to_sqlserver_string : v
1000
+ i += 1
1001
+ end
1002
+ names_and_values << h
1003
+ end
1004
+ names_and_values
1005
+ end
1006
+ when :rows
1007
+ rows = handle.fetch_all || []
1008
+ return rows if @connection_supports_native_types
1009
+ rows.each do |row|
1010
+ i = 0
1011
+ while i < row.size
1012
+ v = row[i]
1013
+ row[i] = v.to_sqlserver_string if v.respond_to?(:to_sqlserver_string)
1014
+ i += 1
977
1015
  end
978
1016
  end
979
- rows << row
1017
+ rows
980
1018
  end
981
- [fields,rows]
982
1019
  end
983
-
984
- def handle_to_fields_and_rows_adonet(handle)
1020
+
1021
+ def handle_to_names_and_values_adonet(handle, options={})
985
1022
  if handle.has_rows
986
- fields = []
1023
+ names = []
987
1024
  rows = []
988
- fields_named = false
1025
+ fields_named = options[:fetch] == :rows
1026
+ one_row_only = options[:fetch] == :one
989
1027
  while handle.read
990
1028
  row = []
991
1029
  handle.visible_field_count.times do |row_index|
992
1030
  value = handle.get_value(row_index)
993
- value = if value.is_a? System::String
1031
+ value = case value
1032
+ when System::String
994
1033
  value.to_s
995
- elsif value.is_a? System::DBNull
1034
+ when System::DBNull
996
1035
  nil
997
- elsif value.is_a? System::DateTime
998
- value.to_string("yyyy-MM-dd HH:MM:ss.fff").to_s
1036
+ when System::DateTime
1037
+ value.to_string("yyyy-MM-dd HH:mm:ss.fff").to_s
1038
+ when @@array_of_bytes ||= System::Array[System::Byte]
1039
+ String.new(value)
999
1040
  else
1000
1041
  value
1001
1042
  end
1002
1043
  row << value
1003
- fields << handle.get_name(row_index).to_s unless fields_named
1044
+ names << handle.get_name(row_index).to_s unless fields_named
1045
+ break if one_row_only
1004
1046
  end
1005
1047
  rows << row
1006
1048
  fields_named = true
1007
1049
  end
1008
1050
  else
1009
- fields, rows = [], []
1051
+ rows = []
1052
+ end
1053
+ if options[:fetch] != :rows
1054
+ names_and_values = []
1055
+ rows.each do |row|
1056
+ h = {}
1057
+ i = 0
1058
+ while i < row.size
1059
+ h[names[i]] = row[i]
1060
+ i += 1
1061
+ end
1062
+ names_and_values << h
1063
+ end
1064
+ names_and_values
1065
+ else
1066
+ rows
1010
1067
  end
1011
- [fields,rows]
1012
1068
  end
1013
1069
 
1014
1070
  def add_limit_offset_for_association_limiting!(sql, options)
@@ -1129,7 +1185,7 @@ module ActiveRecord
1129
1185
  end
1130
1186
 
1131
1187
  def views_real_column_name(table_name,column_name)
1132
- view_definition = view_information(table_name)['VIEW_DEFINITION']
1188
+ view_definition = view_information(table_name)[:VIEW_DEFINITION]
1133
1189
  match_data = view_definition.match(/([\w-]*)\s+as\s+#{column_name}/im)
1134
1190
  match_data ? match_data[1] : column_name
1135
1191
  end
@@ -1158,6 +1214,32 @@ module ActiveRecord
1158
1214
  @sqlserver_columns_cache = {} if reset_columns
1159
1215
  @sqlserver_views_cache = nil
1160
1216
  @sqlserver_view_information_cache = {}
1217
+ @sqlserver_quoted_column_and_table_names = {}
1218
+ end
1219
+
1220
+ def initialize_native_database_types
1221
+ return if defined?(ActiveRecord::ConnectionAdapters::SQLServerAdapter::NATIVE_DATABASE_TYPES)
1222
+ ActiveRecord::ConnectionAdapters::SQLServerAdapter.const_set(:NATIVE_DATABASE_TYPES,{
1223
+ :primary_key => "int NOT NULL IDENTITY(1,1) PRIMARY KEY",
1224
+ :string => { :name => native_string_database_type, :limit => 255 },
1225
+ :text => { :name => native_text_database_type },
1226
+ :integer => { :name => "int", :limit => 4 },
1227
+ :float => { :name => "float", :limit => 8 },
1228
+ :decimal => { :name => "decimal" },
1229
+ :datetime => { :name => "datetime" },
1230
+ :timestamp => { :name => "datetime" },
1231
+ :time => { :name => native_time_database_type },
1232
+ :date => { :name => native_date_database_type },
1233
+ :binary => { :name => native_binary_database_type },
1234
+ :boolean => { :name => "bit"},
1235
+ # These are custom types that may move somewhere else for good schema_dumper.rb hacking to output them.
1236
+ :char => { :name => 'char' },
1237
+ :varchar_max => { :name => 'varchar(max)' },
1238
+ :nchar => { :name => "nchar" },
1239
+ :nvarchar => { :name => "nvarchar", :limit => 255 },
1240
+ :nvarchar_max => { :name => "nvarchar(max)" },
1241
+ :ntext => { :name => "ntext" }
1242
+ })
1161
1243
  end
1162
1244
 
1163
1245
  def column_definitions(table_name)
@@ -1179,7 +1261,7 @@ module ActiveRecord
1179
1261
  CASE
1180
1262
  WHEN columns.IS_NULLABLE = 'YES' THEN 1
1181
1263
  ELSE NULL
1182
- end as is_nullable,
1264
+ END as is_nullable,
1183
1265
  CASE
1184
1266
  WHEN COLUMNPROPERTY(OBJECT_ID(columns.TABLE_SCHEMA+'.'+columns.TABLE_NAME), columns.COLUMN_NAME, 'IsIdentity') = 0 THEN NULL
1185
1267
  ELSE 1
@@ -1188,9 +1270,9 @@ module ActiveRecord
1188
1270
  WHERE columns.TABLE_NAME = '#{table_name}'
1189
1271
  ORDER BY columns.ordinal_position
1190
1272
  }.gsub(/[ \t\r\n]+/,' ')
1191
- results = info_schema_query { select(sql,nil,true) }
1273
+ results = info_schema_query { select(sql,nil) }
1192
1274
  results.collect do |ci|
1193
- ci.symbolize_keys!
1275
+ ci = ci.symbolize_keys
1194
1276
  ci[:type] = case ci[:type]
1195
1277
  when /^bit|image|text|ntext|datetime$/
1196
1278
  ci[:type]
@@ -1210,6 +1292,9 @@ module ActiveRecord
1210
1292
  ci[:default_value] = case ci[:default_value]
1211
1293
  when nil, '(null)', '(NULL)'
1212
1294
  nil
1295
+ when /\A\((\w+\(\))\)\Z/
1296
+ ci[:default_function] = $1
1297
+ nil
1213
1298
  else
1214
1299
  match_data = ci[:default_value].match(/\A\(+N?'?(.*?)'?\)+\Z/m)
1215
1300
  match_data ? match_data[1] : nil
@@ -71,21 +71,6 @@ class AdapterTestSqlserver < ActiveRecord::TestCase
71
71
  assert_contains @supported_version, @connection.database_year
72
72
  end
73
73
 
74
- should 'return true to #sqlserver_2000?' do
75
- @connection.stubs(:database_version).returns(@sqlserver_2000_string)
76
- assert @connection.sqlserver_2000?
77
- end
78
-
79
- should 'return true to #sqlserver_2005?' do
80
- @connection.stubs(:database_version).returns(@sqlserver_2005_string)
81
- assert @connection.sqlserver_2005?
82
- end
83
-
84
- should 'return true to #sqlserver_2008?' do
85
- @connection.stubs(:database_version).returns(@sqlserver_2008_string)
86
- assert @connection.sqlserver_2008?
87
- end
88
-
89
74
  end
90
75
 
91
76
  context 'for #unqualify_table_name and #unqualify_db_name' do
@@ -303,13 +288,13 @@ class AdapterTestSqlserver < ActiveRecord::TestCase
303
288
 
304
289
  should 'find 003 millisecond in the DB with before and after casting' do
305
290
  existing_003 = SqlServerChronic.find_by_datetime!(@db_datetime_003)
306
- assert_equal @db_datetime_003, existing_003.datetime_before_type_cast
291
+ assert_equal @db_datetime_003, existing_003.datetime_before_type_cast if existing_003.datetime_before_type_cast.is_a?(String)
307
292
  assert_equal 3000, existing_003.datetime.usec, 'A 003 millisecond in SQL Server is 3000 microseconds'
308
293
  end
309
294
 
310
295
  should 'find 123 millisecond in the DB with before and after casting' do
311
296
  existing_123 = SqlServerChronic.find_by_datetime!(@db_datetime_123)
312
- assert_equal @db_datetime_123, existing_123.datetime_before_type_cast
297
+ assert_equal @db_datetime_123, existing_123.datetime_before_type_cast if existing_123.datetime_before_type_cast.is_a?(String)
313
298
  assert_equal 123000, existing_123.datetime.usec, 'A 123 millisecond in SQL Server is 123000 microseconds'
314
299
  end
315
300
 
@@ -320,14 +305,14 @@ class AdapterTestSqlserver < ActiveRecord::TestCase
320
305
  should 'truncate 123456 usec to just 123 in the DB cast back to 123000' do
321
306
  @time.stubs(:usec).returns(123456)
322
307
  saved = SqlServerChronic.create!(:datetime => @time).reload
323
- assert_equal '123', saved.datetime_before_type_cast.split('.')[1]
308
+ assert_equal '123', saved.datetime_before_type_cast.split('.')[1] if saved.datetime_before_type_cast.is_a?(String)
324
309
  assert_equal 123000, saved.datetime.usec
325
310
  end
326
311
 
327
312
  should 'truncate 3001 usec to just 003 in the DB cast back to 3000' do
328
313
  @time.stubs(:usec).returns(3001)
329
314
  saved = SqlServerChronic.create!(:datetime => @time).reload
330
- assert_equal '003', saved.datetime_before_type_cast.split('.')[1]
315
+ assert_equal '003', saved.datetime_before_type_cast.split('.')[1] if saved.datetime_before_type_cast.is_a?(String)
331
316
  assert_equal 3000, saved.datetime.usec
332
317
  end
333
318
 
@@ -14,7 +14,9 @@ class BasicsTest < ActiveRecord::TestCase
14
14
 
15
15
  def test_coerced_test_read_attributes_before_type_cast_on_datetime
16
16
  developer = Developer.find(:first)
17
- assert_equal developer.created_at.to_s(:db)+'.000' , developer.attributes_before_type_cast["created_at"]
17
+ if developer.created_at_before_type_cast.is_a?(String)
18
+ assert_equal developer.created_at.to_s(:db)+'.000' , developer.attributes_before_type_cast["created_at"]
19
+ end
18
20
  end
19
21
 
20
22
 
@@ -20,15 +20,6 @@ class ExecuteProcedureTestSqlserver < ActiveRecord::TestCase
20
20
  assert_equal 'TABLE', table_info[:TABLE_TYPE], "Table Info: #{table_info.inspect}"
21
21
  end
22
22
 
23
- should 'quote bind vars correctly' do
24
- assert_sql(/EXEC sp_tables '%sql_server%', NULL, NULL, NULL, 1/) do
25
- @klass.execute_procedure :sp_tables, '%sql_server%', nil, nil, nil, true
26
- end if sqlserver_2005? || sqlserver_2008?
27
- assert_sql(/EXEC sp_tables '%sql_server%', NULL, NULL, NULL/) do
28
- @klass.execute_procedure :sp_tables, '%sql_server%', nil, nil, nil
29
- end if sqlserver_2000?
30
- end
31
-
32
23
  should 'allow multiple result sets to be returned' do
33
24
  results1, results2 = @klass.execute_procedure('sp_helpconstraint','accounts')
34
25
  assert_instance_of Array, results1
@@ -84,40 +84,3 @@ class MigrationTest < ActiveRecord::TestCase
84
84
 
85
85
  end
86
86
 
87
- class ChangeTableMigrationsTest < ActiveRecord::TestCase
88
-
89
- COERCED_TESTS = [:test_string_creates_string_column]
90
-
91
- include SqlserverCoercedTest
92
-
93
- def setup
94
- @connection = Person.connection
95
- @connection.create_table :delete_me, :force => true do |t|
96
- end
97
- end
98
-
99
- def teardown
100
- @connection.drop_table :delete_me rescue nil
101
- end
102
-
103
- def test_coerced_string_creates_string_column
104
- with_sqlserver_change_table do |t|
105
- @connection.expects(:add_column).with(:delete_me, :foo, sqlserver_string_column, {})
106
- @connection.expects(:add_column).with(:delete_me, :bar, sqlserver_string_column, {})
107
- t.string :foo, :bar
108
- end
109
- end
110
-
111
- protected
112
-
113
- def with_sqlserver_change_table
114
- @connection.change_table :delete_me do |t|
115
- yield t
116
- end
117
- end
118
-
119
- def sqlserver_string_column
120
- "#{@connection.native_string_database_type}(255)"
121
- end
122
-
123
- end
@@ -1,7 +1,15 @@
1
1
  require 'cases/sqlserver_helper'
2
2
 
3
3
  class StringDefault < ActiveRecord::Base; end;
4
- class SqlServerEdgeSchema < ActiveRecord::Base; end;
4
+ class SqlServerEdgeSchema < ActiveRecord::Base
5
+ attr_accessor :new_id_setting
6
+ before_create :set_new_id
7
+ protected
8
+ def set_new_id
9
+ self[:guid_newid] ||= connection.newid_function if new_id_setting
10
+ true
11
+ end
12
+ end
5
13
 
6
14
  class SpecificSchemaTestSqlserver < ActiveRecord::TestCase
7
15
 
@@ -91,7 +99,47 @@ class SpecificSchemaTestSqlserver < ActiveRecord::TestCase
91
99
 
92
100
  end
93
101
 
102
+ context 'with uniqueidentifier column' do
103
+
104
+ setup do
105
+ @newid = ActiveRecord::Base.connection.newid_function
106
+ assert_guid @newid
107
+ end
108
+
109
+ should 'allow a simple insert and read of a column without a default function' do
110
+ obj = @edge_class.create! :guid => @newid
111
+ assert_equal @newid, @edge_class.find(obj.id).guid
112
+ end
113
+
114
+ should 'record the default function name in the column definition but still show a nil real default, will use one day for insert/update' do
115
+ newid_column = @edge_class.columns_hash['guid_newid']
116
+ assert newid_column.default_function.present?
117
+ assert_nil newid_column.default
118
+ assert_equal 'newid()', newid_column.default_function
119
+ unless ActiveRecord::Base.connection.sqlserver_2000?
120
+ newseqid_column = @edge_class.columns_hash['guid_newseqid']
121
+ assert newseqid_column.default_function.present?
122
+ assert_nil newseqid_column.default
123
+ assert_equal 'newsequentialid()', newseqid_column.default_function
124
+ end
125
+ end
126
+
127
+ should 'use model callback to set get a new guid' do
128
+ obj = @edge_class.new
129
+ obj.new_id_setting = true
130
+ obj.save!
131
+ assert_guid obj.guid_newid
132
+ end
133
+
134
+ end
135
+
94
136
  end
95
137
 
96
138
 
139
+ protected
140
+
141
+ def assert_guid(guid)
142
+ assert_match %r|\w{8}-\w{4}-\w{4}-\w{4}-\w{12}|, guid
143
+ end
144
+
97
145
  end
@@ -1,20 +1,26 @@
1
+
2
+ SQLSERVER_TEST_ROOT = File.expand_path(File.join(File.dirname(__FILE__),'..'))
3
+ SQLSERVER_ASSETS_ROOT = File.expand_path(File.join(SQLSERVER_TEST_ROOT,'assets'))
4
+ SQLSERVER_FIXTURES_ROOT = File.expand_path(File.join(SQLSERVER_TEST_ROOT,'fixtures'))
5
+ SQLSERVER_MIGRATIONS_ROOT = File.expand_path(File.join(SQLSERVER_TEST_ROOT,'migrations'))
6
+ SQLSERVER_SCHEMA_ROOT = File.expand_path(File.join(SQLSERVER_TEST_ROOT,'schema'))
7
+ ACTIVERECORD_TEST_ROOT = File.expand_path(File.join(ENV['RAILS_SOURCE'],'activerecord','test'))
8
+
1
9
  require 'rubygems'
10
+ require 'bundler'
11
+ Bundler.setup
2
12
  require 'shoulda'
3
13
  require 'mocha'
14
+ begin ; require 'ruby-debug' ; rescue LoadError ; end
4
15
  [ File.expand_path(File.join(File.dirname(__FILE__),'..','..','test')),
5
16
  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'))
17
+ File.expand_path(File.join(ENV['RAILS_SOURCE'],'activerecord','test'))
7
18
  ].each{ |lib| $:.unshift(lib) unless $:.include?(lib) } if ENV['TM_DIRECTORY']
8
19
  require 'cases/helper'
9
20
  require 'models/topic'
10
21
  require 'active_record/version'
11
22
 
12
- SQLSERVER_TEST_ROOT = File.expand_path(File.join(File.dirname(__FILE__),'..'))
13
- SQLSERVER_ASSETS_ROOT = SQLSERVER_TEST_ROOT + "/assets"
14
- SQLSERVER_FIXTURES_ROOT = SQLSERVER_TEST_ROOT + "/fixtures"
15
- SQLSERVER_MIGRATIONS_ROOT = SQLSERVER_TEST_ROOT + "/migrations"
16
- SQLSERVER_SCHEMA_ROOT = SQLSERVER_TEST_ROOT + "/schema"
17
- ACTIVERECORD_TEST_ROOT = File.expand_path(SQLSERVER_TEST_ROOT + "/../../../../rails/activerecord/test/")
23
+ GC.copy_on_write_friendly = true if GC.respond_to?(:copy_on_write_friendly?)
18
24
 
19
25
  ActiveRecord::Migration.verbose = false
20
26
 
@@ -63,7 +69,7 @@ end
63
69
 
64
70
  # Set weather to test unicode string defaults or not. Used from rake task.
65
71
 
66
- if ENV['ENABLE_DEFAULT_UNICODE_TYPES'] == 'true'
72
+ if ENV['ENABLE_DEFAULT_UNICODE_TYPES'] != 'false'
67
73
  puts "With enabled unicode string types"
68
74
  ActiveRecord::ConnectionAdapters::SQLServerAdapter.enable_default_unicode_types = true
69
75
  end
@@ -87,10 +93,10 @@ ActiveRecord::Base.connection.class.class_eval do
87
93
  end
88
94
 
89
95
  ActiveRecord::ConnectionAdapters::SQLServerAdapter.class_eval do
90
- def raw_select_with_query_record(sql, name = nil)
96
+ def raw_select_with_query_record(sql, name=nil, options={})
91
97
  $queries_executed ||= []
92
98
  $queries_executed << sql unless IGNORED_SQL.any? { |r| sql =~ r }
93
- raw_select_without_query_record(sql,name)
99
+ raw_select_without_query_record(sql,name,options)
94
100
  end
95
101
  alias_method_chain :raw_select, :query_record
96
102
  end
@@ -98,6 +104,7 @@ end
98
104
  module ActiveRecord
99
105
  class TestCase < ActiveSupport::TestCase
100
106
  class << self
107
+ def connection_mode_odbc? ; ActiveRecord::Base.connection.instance_variable_get(:@connection_options)[:mode] == :odbc ; end
101
108
  def sqlserver_2000? ; ActiveRecord::Base.connection.sqlserver_2000? ; end
102
109
  def sqlserver_2005? ; ActiveRecord::Base.connection.sqlserver_2005? ; end
103
110
  def sqlserver_2008? ; ActiveRecord::Base.connection.sqlserver_2008? ; end
@@ -67,7 +67,10 @@ ActiveRecord::Schema.define do
67
67
  t.string :description
68
68
  t.column :bigint, :bigint
69
69
  t.column :tinyint, :tinyint
70
+ t.column :guid, :uniqueidentifier
70
71
  end
72
+ execute %|ALTER TABLE [sql_server_edge_schemas] ADD [guid_newid] uniqueidentifier DEFAULT NEWID();|
73
+ execute %|ALTER TABLE [sql_server_edge_schemas] ADD [guid_newseqid] uniqueidentifier DEFAULT NEWSEQUENTIALID();| unless ActiveRecord::Base.connection.sqlserver_2000?
71
74
 
72
75
  execute "IF EXISTS (SELECT TABLE_NAME FROM INFORMATION_SCHEMA.VIEWS WHERE TABLE_NAME = 'customers_view') DROP VIEW customers_view"
73
76
  execute <<-CUSTOMERSVIEW
metadata CHANGED
@@ -1,12 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activerecord-sqlserver-adapter
3
3
  version: !ruby/object:Gem::Version
4
+ hash: 17
4
5
  prerelease: false
5
6
  segments:
6
7
  - 2
7
8
  - 3
8
- - 8
9
- version: 2.3.8
9
+ - 9
10
+ version: 2.3.9
10
11
  platform: ruby
11
12
  authors:
12
13
  - Ken Collins
@@ -18,10 +19,24 @@ autorequire:
18
19
  bindir: bin
19
20
  cert_chain: []
20
21
 
21
- date: 2010-06-07 00:00:00 -04:00
22
+ date: 2010-09-15 00:00:00 -04:00
22
23
  default_executable:
23
- dependencies: []
24
-
24
+ dependencies:
25
+ - !ruby/object:Gem::Dependency
26
+ name: activerecord
27
+ prerelease: false
28
+ requirement: &id001 !ruby/object:Gem::Requirement
29
+ none: false
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ hash: 5
34
+ segments:
35
+ - 2
36
+ - 3
37
+ version: "2.3"
38
+ type: :runtime
39
+ version_requirements: *id001
25
40
  description: SQL Server 2000, 2005 and 2008 Adapter For Rails.
26
41
  email: ken@metaskills.net
27
42
  executables: []
@@ -36,13 +51,37 @@ files:
36
51
  - Rakefile
37
52
  - README.rdoc
38
53
  - RUNNING_UNIT_TESTS
39
- - autotest/discover.rb
40
- - autotest/railssqlserver.rb
41
- - autotest/sqlserver.rb
42
54
  - lib/activerecord-sqlserver-adapter.rb
43
55
  - lib/active_record/connection_adapters/sqlserver_adapter.rb
44
56
  - lib/active_record/connection_adapters/sqlserver_adapter/core_ext/active_record.rb
45
57
  - lib/active_record/connection_adapters/sqlserver_adapter/core_ext/odbc.rb
58
+ - test/cases/aaaa_create_tables_test_sqlserver.rb
59
+ - test/cases/adapter_test_sqlserver.rb
60
+ - test/cases/attribute_methods_test_sqlserver.rb
61
+ - test/cases/basics_test_sqlserver.rb
62
+ - test/cases/calculations_test_sqlserver.rb
63
+ - test/cases/column_test_sqlserver.rb
64
+ - test/cases/connection_test_sqlserver.rb
65
+ - test/cases/eager_association_test_sqlserver.rb
66
+ - test/cases/execute_procedure_test_sqlserver.rb
67
+ - test/cases/inheritance_test_sqlserver.rb
68
+ - test/cases/method_scoping_test_sqlserver.rb
69
+ - test/cases/migration_test_sqlserver.rb
70
+ - test/cases/named_scope_test_sqlserver.rb
71
+ - test/cases/offset_and_limit_test_sqlserver.rb
72
+ - test/cases/pessimistic_locking_test_sqlserver.rb
73
+ - test/cases/query_cache_test_sqlserver.rb
74
+ - test/cases/schema_dumper_test_sqlserver.rb
75
+ - test/cases/specific_schema_test_sqlserver.rb
76
+ - test/cases/sqlserver_helper.rb
77
+ - test/cases/table_name_test_sqlserver.rb
78
+ - test/cases/transaction_test_sqlserver.rb
79
+ - test/cases/unicode_test_sqlserver.rb
80
+ - test/cases/validations_test_sqlserver.rb
81
+ - test/connections/native_sqlserver/connection.rb
82
+ - test/connections/native_sqlserver_odbc/connection.rb
83
+ - test/migrations/transaction_table/1_table_will_never_be_created.rb
84
+ - test/schema/sqlserver_specific_schema.rb
46
85
  has_rdoc: true
47
86
  homepage: http://github.com/rails-sqlserver
48
87
  licenses: []
@@ -56,23 +95,27 @@ rdoc_options:
56
95
  require_paths:
57
96
  - lib
58
97
  required_ruby_version: !ruby/object:Gem::Requirement
98
+ none: false
59
99
  requirements:
60
100
  - - ">="
61
101
  - !ruby/object:Gem::Version
102
+ hash: 3
62
103
  segments:
63
104
  - 0
64
105
  version: "0"
65
106
  required_rubygems_version: !ruby/object:Gem::Requirement
107
+ none: false
66
108
  requirements:
67
109
  - - ">="
68
110
  - !ruby/object:Gem::Version
111
+ hash: 3
69
112
  segments:
70
113
  - 0
71
114
  version: "0"
72
115
  requirements: []
73
116
 
74
117
  rubyforge_project:
75
- rubygems_version: 1.3.6
118
+ rubygems_version: 1.3.7
76
119
  signing_key:
77
120
  specification_version: 3
78
121
  summary: SQL Server 2000, 2005 and 2008 Adapter For Rails.
@@ -1,4 +0,0 @@
1
-
2
- Autotest.add_discovery do
3
- ARGV.first || 'railssqlserver'
4
- end
@@ -1,16 +0,0 @@
1
- require 'autotest/sqlserver'
2
-
3
- class Autotest::Railssqlserver < Autotest::Sqlserver
4
-
5
- def initialize
6
- super
7
- self.libs << "#{File::PATH_SEPARATOR}../../../rails/activerecord/test/"
8
- self.extra_files = ['../../../rails/activerecord/test/']
9
- self.add_mapping %r%../../../rails/activerecord/test/.*/.*_test.rb$% do |filename, _|
10
- filename
11
- end
12
- end
13
-
14
-
15
- end
16
-
@@ -1,54 +0,0 @@
1
- require 'autotest'
2
- require 'active_support'
3
-
4
- class Autotest::Sqlserver < Autotest
5
-
6
- def initialize
7
- super
8
-
9
- odbc_mode = true
10
-
11
- clear_mappings
12
-
13
- self.libs = [
14
- "lib",
15
- "test",
16
- "test/connections/native_sqlserver#{odbc_mode ? '_odbc' : ''}",
17
- "../../../rails/activerecord/test/"
18
- ].join(File::PATH_SEPARATOR)
19
-
20
- @test_sqlserver_file_match = %r%^test/cases/.*_test_sqlserver\.rb$%
21
-
22
- add_exception %r%^\./(?:autotest)%
23
- add_exception %r%^\./(.*LICENSE|debug.log|README.*|CHANGELOG.*)$%i
24
-
25
- # Any *_test_sqlserver file saved runs that file
26
- self.add_mapping @test_sqlserver_file_match do |filename, matchs|
27
- filename
28
- end
29
-
30
- # If any the adapter changes
31
- # the test directory, ofcourse having _test.rb at the end, will run that test.
32
- self.add_mapping(%r%^lib/(.*)\.rb$%) do |filename, matchs|
33
- files_matching @test_sqlserver_file_match
34
- end
35
-
36
- # If any core file like the test helper, connections, fixtures, migratinos,
37
- # and other support files, then run all matching *_test_sqlserver files.
38
- add_mapping %r%^test/(cases/(sqlserver_helper)\.rb|connections|fixtures|migrations|schema/.*)% do
39
- files_matching @test_sqlserver_file_match
40
- end
41
-
42
- end
43
-
44
- # Have to use a custom reorder method since the normal :alpha for Autotest would put the
45
- # files with ../ in the path before others.
46
- def reorder(files_to_test)
47
- ar_tests, sqlsvr_tests = files_to_test.partition { |k,v| k.starts_with?('../../../') }
48
- ar_tests.sort! { |a,b| a[0] <=> b[0] }
49
- sqlsvr_tests.sort! { |a,b| a[0] <=> b[0] }
50
- sqlsvr_tests + ar_tests
51
- end
52
-
53
- end
54
-