activerecord-sqlserver-adapter 6.0.0.rc1 → 6.1.0.0.rc1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (149) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +26 -0
  3. data/.gitignore +1 -0
  4. data/.rubocop.yml +29 -0
  5. data/CHANGELOG.md +18 -23
  6. data/Gemfile +11 -5
  7. data/Guardfile +9 -8
  8. data/README.md +32 -3
  9. data/RUNNING_UNIT_TESTS.md +1 -1
  10. data/Rakefile +12 -16
  11. data/VERSION +1 -1
  12. data/activerecord-sqlserver-adapter.gemspec +4 -4
  13. data/lib/active_record/connection_adapters/sqlserver/core_ext/active_record.rb +0 -4
  14. data/lib/active_record/connection_adapters/sqlserver/core_ext/attribute_methods.rb +1 -4
  15. data/lib/active_record/connection_adapters/sqlserver/core_ext/calculations.rb +3 -13
  16. data/lib/active_record/connection_adapters/sqlserver/core_ext/explain.rb +8 -5
  17. data/lib/active_record/connection_adapters/sqlserver/core_ext/finder_methods.rb +2 -3
  18. data/lib/active_record/connection_adapters/sqlserver/core_ext/query_methods.rb +2 -3
  19. data/lib/active_record/connection_adapters/sqlserver/database_limits.rb +0 -4
  20. data/lib/active_record/connection_adapters/sqlserver/database_statements.rb +58 -43
  21. data/lib/active_record/connection_adapters/sqlserver/database_tasks.rb +7 -12
  22. data/lib/active_record/connection_adapters/sqlserver/errors.rb +0 -3
  23. data/lib/active_record/connection_adapters/sqlserver/quoting.rb +15 -15
  24. data/lib/active_record/connection_adapters/sqlserver/schema_creation.rb +22 -3
  25. data/lib/active_record/connection_adapters/sqlserver/schema_dumper.rb +16 -10
  26. data/lib/active_record/connection_adapters/sqlserver/schema_statements.rb +131 -105
  27. data/lib/active_record/connection_adapters/sqlserver/showplan.rb +6 -8
  28. data/lib/active_record/connection_adapters/sqlserver/showplan/printer_table.rb +2 -2
  29. data/lib/active_record/connection_adapters/sqlserver/showplan/printer_xml.rb +1 -1
  30. data/lib/active_record/connection_adapters/sqlserver/sql_type_metadata.rb +25 -7
  31. data/lib/active_record/connection_adapters/sqlserver/table_definition.rb +1 -5
  32. data/lib/active_record/connection_adapters/sqlserver/transaction.rb +6 -10
  33. data/lib/active_record/connection_adapters/sqlserver/type.rb +36 -35
  34. data/lib/active_record/connection_adapters/sqlserver/type/big_integer.rb +0 -2
  35. data/lib/active_record/connection_adapters/sqlserver/type/binary.rb +0 -2
  36. data/lib/active_record/connection_adapters/sqlserver/type/boolean.rb +0 -2
  37. data/lib/active_record/connection_adapters/sqlserver/type/char.rb +2 -2
  38. data/lib/active_record/connection_adapters/sqlserver/type/data.rb +0 -2
  39. data/lib/active_record/connection_adapters/sqlserver/type/date.rb +2 -3
  40. data/lib/active_record/connection_adapters/sqlserver/type/datetime.rb +2 -3
  41. data/lib/active_record/connection_adapters/sqlserver/type/datetime2.rb +0 -2
  42. data/lib/active_record/connection_adapters/sqlserver/type/datetimeoffset.rb +0 -2
  43. data/lib/active_record/connection_adapters/sqlserver/type/decimal.rb +0 -2
  44. data/lib/active_record/connection_adapters/sqlserver/type/decimal_without_scale.rb +22 -0
  45. data/lib/active_record/connection_adapters/sqlserver/type/float.rb +0 -2
  46. data/lib/active_record/connection_adapters/sqlserver/type/integer.rb +0 -2
  47. data/lib/active_record/connection_adapters/sqlserver/type/json.rb +0 -1
  48. data/lib/active_record/connection_adapters/sqlserver/type/money.rb +0 -2
  49. data/lib/active_record/connection_adapters/sqlserver/type/real.rb +0 -2
  50. data/lib/active_record/connection_adapters/sqlserver/type/small_integer.rb +0 -2
  51. data/lib/active_record/connection_adapters/sqlserver/type/small_money.rb +0 -2
  52. data/lib/active_record/connection_adapters/sqlserver/type/smalldatetime.rb +0 -2
  53. data/lib/active_record/connection_adapters/sqlserver/type/string.rb +0 -2
  54. data/lib/active_record/connection_adapters/sqlserver/type/text.rb +0 -2
  55. data/lib/active_record/connection_adapters/sqlserver/type/time.rb +2 -3
  56. data/lib/active_record/connection_adapters/sqlserver/type/time_value_fractional.rb +6 -9
  57. data/lib/active_record/connection_adapters/sqlserver/type/timestamp.rb +0 -2
  58. data/lib/active_record/connection_adapters/sqlserver/type/tiny_integer.rb +0 -2
  59. data/lib/active_record/connection_adapters/sqlserver/type/unicode_char.rb +1 -3
  60. data/lib/active_record/connection_adapters/sqlserver/type/unicode_string.rb +0 -2
  61. data/lib/active_record/connection_adapters/sqlserver/type/unicode_text.rb +0 -2
  62. data/lib/active_record/connection_adapters/sqlserver/type/unicode_varchar.rb +0 -2
  63. data/lib/active_record/connection_adapters/sqlserver/type/unicode_varchar_max.rb +0 -2
  64. data/lib/active_record/connection_adapters/sqlserver/type/uuid.rb +1 -2
  65. data/lib/active_record/connection_adapters/sqlserver/type/varbinary.rb +1 -3
  66. data/lib/active_record/connection_adapters/sqlserver/type/varbinary_max.rb +0 -2
  67. data/lib/active_record/connection_adapters/sqlserver/type/varchar.rb +1 -3
  68. data/lib/active_record/connection_adapters/sqlserver/type/varchar_max.rb +0 -2
  69. data/lib/active_record/connection_adapters/sqlserver/utils.rb +8 -11
  70. data/lib/active_record/connection_adapters/sqlserver/version.rb +0 -2
  71. data/lib/active_record/connection_adapters/sqlserver_adapter.rb +170 -136
  72. data/lib/active_record/connection_adapters/sqlserver_column.rb +16 -1
  73. data/lib/active_record/sqlserver_base.rb +9 -15
  74. data/lib/active_record/tasks/sqlserver_database_tasks.rb +36 -39
  75. data/lib/activerecord-sqlserver-adapter.rb +1 -1
  76. data/lib/arel/visitors/sqlserver.rb +126 -50
  77. data/lib/arel_sqlserver.rb +2 -2
  78. data/test/cases/adapter_test_sqlserver.rb +203 -190
  79. data/test/cases/change_column_collation_test_sqlserver.rb +33 -0
  80. data/test/cases/change_column_null_test_sqlserver.rb +12 -12
  81. data/test/cases/coerced_tests.rb +656 -318
  82. data/test/cases/column_test_sqlserver.rb +285 -284
  83. data/test/cases/connection_test_sqlserver.rb +15 -20
  84. data/test/cases/disconnected_test_sqlserver.rb +39 -0
  85. data/test/cases/execute_procedure_test_sqlserver.rb +26 -19
  86. data/test/cases/fetch_test_sqlserver.rb +14 -22
  87. data/test/cases/fully_qualified_identifier_test_sqlserver.rb +12 -18
  88. data/test/cases/helper_sqlserver.rb +13 -15
  89. data/test/cases/in_clause_test_sqlserver.rb +36 -9
  90. data/test/cases/index_test_sqlserver.rb +13 -15
  91. data/test/cases/json_test_sqlserver.rb +23 -25
  92. data/test/cases/lateral_test_sqlserver.rb +35 -0
  93. data/test/cases/migration_test_sqlserver.rb +71 -26
  94. data/test/cases/optimizer_hints_test_sqlserver.rb +72 -0
  95. data/test/cases/order_test_sqlserver.rb +57 -53
  96. data/test/cases/pessimistic_locking_test_sqlserver.rb +25 -33
  97. data/test/cases/primary_keys_test_sqlserver.rb +103 -0
  98. data/test/cases/rake_test_sqlserver.rb +33 -46
  99. data/test/cases/schema_dumper_test_sqlserver.rb +121 -108
  100. data/test/cases/schema_test_sqlserver.rb +18 -26
  101. data/test/cases/scratchpad_test_sqlserver.rb +2 -4
  102. data/test/cases/showplan_test_sqlserver.rb +24 -33
  103. data/test/cases/specific_schema_test_sqlserver.rb +66 -65
  104. data/test/cases/transaction_test_sqlserver.rb +16 -19
  105. data/test/cases/trigger_test_sqlserver.rb +12 -12
  106. data/test/cases/utils_test_sqlserver.rb +68 -70
  107. data/test/cases/uuid_test_sqlserver.rb +11 -13
  108. data/test/debug.rb +6 -6
  109. data/test/migrations/create_clients_and_change_column_collation.rb +19 -0
  110. data/test/migrations/create_clients_and_change_column_null.rb +1 -1
  111. data/test/migrations/transaction_table/1_table_will_never_be_created.rb +2 -4
  112. data/test/models/sqlserver/booking.rb +1 -1
  113. data/test/models/sqlserver/customers_view.rb +1 -1
  114. data/test/models/sqlserver/dollar_table_name.rb +1 -1
  115. data/test/models/sqlserver/edge_schema.rb +1 -3
  116. data/test/models/sqlserver/fk_has_fk.rb +1 -1
  117. data/test/models/sqlserver/fk_has_pk.rb +1 -1
  118. data/test/models/sqlserver/natural_pk_data.rb +2 -2
  119. data/test/models/sqlserver/natural_pk_int_data.rb +1 -1
  120. data/test/models/sqlserver/no_pk_data.rb +1 -1
  121. data/test/models/sqlserver/object_default.rb +1 -1
  122. data/test/models/sqlserver/quoted_table.rb +2 -2
  123. data/test/models/sqlserver/quoted_view_1.rb +1 -1
  124. data/test/models/sqlserver/quoted_view_2.rb +1 -1
  125. data/test/models/sqlserver/sst_memory.rb +1 -1
  126. data/test/models/sqlserver/sst_string_collation.rb +3 -0
  127. data/test/models/sqlserver/string_default.rb +1 -1
  128. data/test/models/sqlserver/string_defaults_big_view.rb +1 -1
  129. data/test/models/sqlserver/string_defaults_view.rb +1 -1
  130. data/test/models/sqlserver/tinyint_pk.rb +1 -1
  131. data/test/models/sqlserver/trigger.rb +2 -2
  132. data/test/models/sqlserver/trigger_history.rb +1 -1
  133. data/test/models/sqlserver/upper.rb +1 -1
  134. data/test/models/sqlserver/uppered.rb +1 -1
  135. data/test/models/sqlserver/uuid.rb +1 -1
  136. data/test/schema/sqlserver_specific_schema.rb +36 -21
  137. data/test/support/coerceable_test_sqlserver.rb +1 -4
  138. data/test/support/connection_reflection.rb +1 -2
  139. data/test/support/core_ext/query_cache.rb +1 -1
  140. data/test/support/load_schema_sqlserver.rb +3 -5
  141. data/test/support/marshal_compatibility_fixtures/SQLServer/rails_6_0_topic.dump +0 -0
  142. data/test/support/marshal_compatibility_fixtures/SQLServer/rails_6_0_topic_associations.dump +0 -0
  143. data/test/support/minitest_sqlserver.rb +1 -1
  144. data/test/support/paths_sqlserver.rb +9 -11
  145. data/test/support/rake_helpers.rb +12 -10
  146. data/test/support/sql_counter_sqlserver.rb +14 -16
  147. data/test/support/test_in_memory_oltp.rb +7 -7
  148. metadata +31 -11
  149. data/.travis.yml +0 -23
@@ -1,11 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'cases/helper_sqlserver'
4
- require 'models/person'
5
- require 'models/reader'
3
+ require "cases/helper_sqlserver"
4
+ require "models/person"
5
+ require "models/reader"
6
6
 
7
7
  class PessimisticLockingTestSQLServer < ActiveRecord::TestCase
8
-
9
8
  fixtures :people, :readers
10
9
 
11
10
  before do
@@ -13,15 +12,14 @@ class PessimisticLockingTestSQLServer < ActiveRecord::TestCase
13
12
  Reader.columns
14
13
  end
15
14
 
16
- it 'uses with updlock by default' do
15
+ it "uses with updlock by default" do
17
16
  assert_sql %r|SELECT \[people\]\.\* FROM \[people\] WITH\(UPDLOCK\)| do
18
17
  _(Person.lock(true).to_a).must_equal Person.all.to_a
19
18
  end
20
19
  end
21
20
 
22
- describe 'For simple finds with default lock option' do
23
-
24
- it 'lock with simple find' do
21
+ describe "For simple finds with default lock option" do
22
+ it "lock with simple find" do
25
23
  assert_nothing_raised do
26
24
  Person.transaction do
27
25
  _(Person.lock(true).find(1)).must_equal Person.find(1)
@@ -29,7 +27,7 @@ class PessimisticLockingTestSQLServer < ActiveRecord::TestCase
29
27
  end
30
28
  end
31
29
 
32
- it 'lock with scoped find' do
30
+ it "lock with scoped find" do
33
31
  assert_nothing_raised do
34
32
  Person.transaction do
35
33
  Person.lock(true).scoping do
@@ -39,8 +37,8 @@ class PessimisticLockingTestSQLServer < ActiveRecord::TestCase
39
37
  end
40
38
  end
41
39
 
42
- it 'lock with eager find' do
43
- assert_nothing_raised do
40
+ it "lock with eager find" do
41
+ assert_nothing_raised do
44
42
  Person.transaction do
45
43
  person = Person.lock(true).includes(:readers).find(1)
46
44
  _(person).must_equal Person.find(1)
@@ -48,62 +46,56 @@ class PessimisticLockingTestSQLServer < ActiveRecord::TestCase
48
46
  end
49
47
  end
50
48
 
51
- it 'can add a custom lock directive' do
49
+ it "can add a custom lock directive" do
52
50
  assert_sql %r|SELECT \[people\]\.\* FROM \[people\] WITH\(HOLDLOCK, ROWLOCK\)| do
53
- Person.lock('WITH(HOLDLOCK, ROWLOCK)').load
51
+ Person.lock("WITH(HOLDLOCK, ROWLOCK)").load
54
52
  end
55
53
  end
56
54
 
57
- describe 'joining tables' do
58
-
59
- it 'joined tables use updlock by default' do
55
+ describe "joining tables" do
56
+ it "joined tables use updlock by default" do
60
57
  assert_sql %r|SELECT \[people\]\.\* FROM \[people\] WITH\(UPDLOCK\) INNER JOIN \[readers\] WITH\(UPDLOCK\)\s+ON \[readers\]\.\[person_id\] = \[people\]\.\[id\]| do
61
58
  Person.lock(true).joins(:readers).load
62
59
  end
63
60
  end
64
61
 
65
- it 'joined tables can use custom lock directive' do
62
+ it "joined tables can use custom lock directive" do
66
63
  assert_sql %r|SELECT \[people\]\.\* FROM \[people\] WITH\(NOLOCK\) INNER JOIN \[readers\] WITH\(NOLOCK\)\s+ON \[readers\]\.\[person_id\] = \[people\]\.\[id\]| do
67
- Person.lock('WITH(NOLOCK)').joins(:readers).load
64
+ Person.lock("WITH(NOLOCK)").joins(:readers).load
68
65
  end
69
66
  end
70
67
 
71
- it 'left joined tables use updlock by default' do
68
+ it "left joined tables use updlock by default" do
72
69
  assert_sql %r|SELECT \[people\]\.\* FROM \[people\] WITH\(UPDLOCK\) LEFT OUTER JOIN \[readers\] WITH\(UPDLOCK\)\s+ON \[readers\]\.\[person_id\] = \[people\]\.\[id\]| do
73
70
  Person.lock(true).left_joins(:readers).load
74
71
  end
75
72
  end
76
73
 
77
- it 'left joined tables can use custom lock directive' do
74
+ it "left joined tables can use custom lock directive" do
78
75
  assert_sql %r|SELECT \[people\]\.\* FROM \[people\] WITH\(NOLOCK\) LEFT OUTER JOIN \[readers\] WITH\(NOLOCK\)\s+ON \[readers\]\.\[person_id\] = \[people\]\.\[id\]| do
79
- Person.lock('WITH(NOLOCK)').left_joins(:readers).load
76
+ Person.lock("WITH(NOLOCK)").left_joins(:readers).load
80
77
  end
81
78
  end
82
-
83
79
  end
84
-
85
80
  end
86
81
 
87
- describe 'For paginated finds' do
88
-
82
+ describe "For paginated finds" do
89
83
  before do
90
84
  Person.delete_all
91
85
  20.times { |n| Person.create!(first_name: "Thing_#{n}") }
92
86
  end
93
87
 
94
- it 'copes with eager loading un-locked paginated' do
88
+ it "copes with eager loading un-locked paginated" do
95
89
  eager_ids_sql = /SELECT\s+DISTINCT \[people\].\[id\] FROM \[people\] WITH\(UPDLOCK\) LEFT OUTER JOIN \[readers\] WITH\(UPDLOCK\)\s+ON \[readers\].\[person_id\] = \[people\].\[id\]\s+ORDER BY \[people\].\[id\] ASC OFFSET @0 ROWS FETCH NEXT @1 ROWS ONLY/
96
90
  loader_sql = /SELECT.*FROM \[people\] WITH\(UPDLOCK\).*WHERE \[people\]\.\[id\] IN/
97
91
  assert_sql(eager_ids_sql, loader_sql) do
98
92
  people = Person.lock(true).limit(5).offset(10).includes(:readers).references(:readers).to_a
99
- _(people[0].first_name).must_equal 'Thing_10'
100
- _(people[1].first_name).must_equal 'Thing_11'
101
- _(people[2].first_name).must_equal 'Thing_12'
102
- _(people[3].first_name).must_equal 'Thing_13'
103
- _(people[4].first_name).must_equal 'Thing_14'
93
+ _(people[0].first_name).must_equal "Thing_10"
94
+ _(people[1].first_name).must_equal "Thing_11"
95
+ _(people[2].first_name).must_equal "Thing_12"
96
+ _(people[3].first_name).must_equal "Thing_13"
97
+ _(people[4].first_name).must_equal "Thing_14"
104
98
  end
105
99
  end
106
-
107
100
  end
108
-
109
101
  end
@@ -0,0 +1,103 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "cases/helper_sqlserver"
4
+ require "support/schema_dumping_helper"
5
+
6
+ class PrimaryKeyUuidTypeTest < ActiveRecord::TestCase
7
+ include SchemaDumpingHelper
8
+
9
+ self.use_transactional_tests = false
10
+
11
+ class Barcode < ActiveRecord::Base
12
+ end
13
+
14
+ setup do
15
+ @connection = ActiveRecord::Base.connection
16
+ @connection.create_table(:barcodes, primary_key: "code", id: :uuid, force: true)
17
+ end
18
+
19
+ teardown do
20
+ @connection.drop_table(:barcodes, if_exists: true)
21
+ end
22
+
23
+ def test_any_type_primary_key
24
+ assert_equal "code", Barcode.primary_key
25
+
26
+ column = Barcode.column_for_attribute(Barcode.primary_key)
27
+ assert_not column.null
28
+ assert_equal :uuid, column.type
29
+ assert_not_predicate column, :is_identity?
30
+ assert_predicate column, :is_primary?
31
+ ensure
32
+ Barcode.reset_column_information
33
+ end
34
+
35
+ test "schema dump primary key includes default" do
36
+ schema = dump_table_schema "barcodes"
37
+ assert_match %r/create_table "barcodes", primary_key: "code", id: :uuid, default: -> { "newid\(\)" }/, schema
38
+ end
39
+ end
40
+
41
+ class PrimaryKeyIntegerTest < ActiveRecord::TestCase
42
+ include SchemaDumpingHelper
43
+
44
+ self.use_transactional_tests = false
45
+
46
+ class Barcode < ActiveRecord::Base
47
+ end
48
+
49
+ class Widget < ActiveRecord::Base
50
+ end
51
+
52
+ setup do
53
+ @connection = ActiveRecord::Base.connection
54
+ end
55
+
56
+ teardown do
57
+ @connection.drop_table :barcodes, if_exists: true
58
+ @connection.drop_table :widgets, if_exists: true
59
+ end
60
+
61
+ test "integer primary key without default" do
62
+ @connection.create_table(:widgets, id: :integer, force: true)
63
+ column = @connection.columns(:widgets).find { |c| c.name == "id" }
64
+ assert_predicate column, :is_primary?
65
+ assert_predicate column, :is_identity?
66
+ assert_equal :integer, column.type
67
+ assert_not_predicate column, :bigint?
68
+
69
+ schema = dump_table_schema "widgets"
70
+ assert_match %r/create_table "widgets", id: :integer, force: :cascade do/, schema
71
+ end
72
+
73
+ test "bigint primary key without default" do
74
+ @connection.create_table(:widgets, id: :bigint, force: true)
75
+ column = @connection.columns(:widgets).find { |c| c.name == "id" }
76
+ assert_predicate column, :is_primary?
77
+ assert_predicate column, :is_identity?
78
+ assert_equal :integer, column.type
79
+ assert_predicate column, :bigint?
80
+
81
+ schema = dump_table_schema "widgets"
82
+ assert_match %r/create_table "widgets", force: :cascade do/, schema
83
+ end
84
+
85
+ test "don't set identity to integer and bigint when there is a default" do
86
+ @connection.create_table(:barcodes, id: :integer, default: nil, force: true)
87
+ @connection.create_table(:widgets, id: :bigint, default: nil, force: true)
88
+
89
+ column = @connection.columns(:widgets).find { |c| c.name == "id" }
90
+ assert_predicate column, :is_primary?
91
+ assert_not_predicate column, :is_identity?
92
+
93
+ schema = dump_table_schema "widgets"
94
+ assert_match %r/create_table "widgets", id: :bigint, default: nil, force: :cascade do/, schema
95
+
96
+ column = @connection.columns(:barcodes).find { |c| c.name == "id" }
97
+ assert_predicate column, :is_primary?
98
+ assert_not_predicate column, :is_identity?
99
+
100
+ schema = dump_table_schema "barcodes"
101
+ assert_match %r/create_table "barcodes", id: :integer, default: nil, force: :cascade do/, schema
102
+ end
103
+ end
@@ -1,20 +1,20 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'cases/helper_sqlserver'
3
+ require "cases/helper_sqlserver"
4
4
 
5
5
  class SQLServerRakeTest < ActiveRecord::TestCase
6
-
7
6
  self.use_transactional_tests = false
8
7
 
9
8
  cattr_accessor :azure_skip
10
9
  self.azure_skip = connection_sqlserver_azure?
11
10
 
12
11
  let(:db_tasks) { ActiveRecord::Tasks::DatabaseTasks }
13
- let(:new_database) { 'activerecord_unittest_tasks' }
14
- let(:default_configuration) { ARTest.connection_config['arunit'] }
15
- let(:configuration) { default_configuration.merge('database' => new_database) }
12
+ let(:new_database) { "activerecord_unittest_tasks" }
13
+ let(:default_configuration) { ARTest.test_configuration_hashes["arunit"] }
14
+ let(:configuration) { default_configuration.merge("database" => new_database) }
15
+ let(:db_config) { ActiveRecord::Base.configurations.resolve(configuration) }
16
16
 
17
- before { skip 'on azure' if azure_skip }
17
+ before { skip "on azure" if azure_skip }
18
18
  before { disconnect! unless azure_skip }
19
19
  after { reconnect unless azure_skip }
20
20
 
@@ -27,7 +27,7 @@ class SQLServerRakeTest < ActiveRecord::TestCase
27
27
  def reconnect
28
28
  config = default_configuration
29
29
  if connection_sqlserver_azure?
30
- ActiveRecord::Base.establish_connection(config.merge('database' => 'master'))
30
+ ActiveRecord::Base.establish_connection(config.merge("database" => "master"))
31
31
  connection.drop_database(new_database) rescue nil
32
32
  disconnect!
33
33
  ActiveRecord::Base.establish_connection(config)
@@ -36,57 +36,51 @@ class SQLServerRakeTest < ActiveRecord::TestCase
36
36
  connection.drop_database(new_database) rescue nil
37
37
  end
38
38
  end
39
-
40
39
  end
41
40
 
42
41
  class SQLServerRakeCreateTest < SQLServerRakeTest
43
-
44
42
  self.azure_skip = false
45
43
 
46
- it 'establishes connection to database after create ' do
44
+ it "establishes connection to database after create " do
47
45
  quietly { db_tasks.create configuration }
48
46
  _(connection.current_database).must_equal(new_database)
49
47
  end
50
48
 
51
- it 'creates database with default collation' do
49
+ it "creates database with default collation" do
52
50
  quietly { db_tasks.create configuration }
53
- _(connection.collation).must_equal 'SQL_Latin1_General_CP1_CI_AS'
51
+ _(connection.collation).must_equal "SQL_Latin1_General_CP1_CI_AS"
54
52
  end
55
53
 
56
- it 'creates database with given collation' do
57
- quietly { db_tasks.create configuration.merge('collation' => 'Latin1_General_CI_AS') }
58
- _(connection.collation).must_equal 'Latin1_General_CI_AS'
54
+ it "creates database with given collation" do
55
+ quietly { db_tasks.create configuration.merge("collation" => "Latin1_General_CI_AS") }
56
+ _(connection.collation).must_equal "Latin1_General_CI_AS"
59
57
  end
60
58
 
61
- it 'prints error message when database exists' do
59
+ it "prints error message when database exists" do
62
60
  quietly { db_tasks.create configuration }
63
61
  message = capture(:stderr) { db_tasks.create configuration }
64
62
  _(message).must_match %r{activerecord_unittest_tasks.*already exists}
65
63
  end
66
-
67
64
  end
68
65
 
69
66
  class SQLServerRakeDropTest < SQLServerRakeTest
70
-
71
67
  self.azure_skip = false
72
68
 
73
- it 'drops database and uses master' do
69
+ it "drops database and uses master" do
74
70
  quietly do
75
71
  db_tasks.create configuration
76
72
  db_tasks.drop configuration
77
73
  end
78
- _(connection.current_database).must_equal 'master'
74
+ _(connection.current_database).must_equal "master"
79
75
  end
80
76
 
81
- it 'prints error message when database does not exist' do
82
- message = capture(:stderr) { db_tasks.drop configuration.merge('database' => 'doesnotexist') }
77
+ it "prints error message when database does not exist" do
78
+ message = capture(:stderr) { db_tasks.drop configuration.merge("database" => "doesnotexist") }
83
79
  _(message).must_match %r{'doesnotexist' does not exist}
84
80
  end
85
-
86
81
  end
87
82
 
88
83
  class SQLServerRakePurgeTest < SQLServerRakeTest
89
-
90
84
  before do
91
85
  quietly { db_tasks.create(configuration) }
92
86
  connection.create_table :users, force: true do |t|
@@ -95,43 +89,37 @@ class SQLServerRakePurgeTest < SQLServerRakeTest
95
89
  end
96
90
  end
97
91
 
98
- it 'clears active connections, drops database, and recreates with established connection' do
92
+ it "clears active connections, drops database, and recreates with established connection" do
99
93
  _(connection.current_database).must_equal(new_database)
100
- _(connection.tables).must_include 'users'
94
+ _(connection.tables).must_include "users"
101
95
  quietly { db_tasks.purge(configuration) }
102
96
  _(connection.current_database).must_equal(new_database)
103
- _(connection.tables).wont_include 'users'
97
+ _(connection.tables).wont_include "users"
104
98
  end
105
-
106
99
  end
107
100
 
108
101
  class SQLServerRakeCharsetTest < SQLServerRakeTest
109
-
110
102
  before do
111
103
  quietly { db_tasks.create(configuration) }
112
104
  end
113
105
 
114
- it 'retrieves charset' do
115
- _(db_tasks.charset(configuration)).must_equal 'iso_1'
106
+ it "retrieves charset" do
107
+ _(db_tasks.charset(configuration)).must_equal "iso_1"
116
108
  end
117
-
118
109
  end
119
110
 
120
111
  class SQLServerRakeCollationTest < SQLServerRakeTest
121
-
122
112
  before do
123
113
  quietly { db_tasks.create(configuration) }
124
114
  end
125
115
 
126
- it 'retrieves collation' do
127
- _(db_tasks.collation(configuration)).must_equal 'SQL_Latin1_General_CP1_CI_AS'
116
+ it "retrieves collation" do
117
+ _(db_tasks.collation(configuration)).must_equal "SQL_Latin1_General_CP1_CI_AS"
128
118
  end
129
-
130
119
  end
131
120
 
132
121
  class SQLServerRakeStructureDumpLoadTest < SQLServerRakeTest
133
-
134
- let(:filename) { File.join ARTest::SQLServer.migrations_root, 'structure.sql' }
122
+ let(:filename) { File.join ARTest::SQLServer.migrations_root, "structure.sql" }
135
123
  let(:filedata) { File.read(filename) }
136
124
 
137
125
  before do
@@ -148,8 +136,8 @@ class SQLServerRakeStructureDumpLoadTest < SQLServerRakeTest
148
136
  FileUtils.rm_rf(filename)
149
137
  end
150
138
 
151
- it 'dumps structure and accounts for defncopy oddities' do
152
- skip 'debug defncopy on windows later' if host_windows?
139
+ it "dumps structure and accounts for defncopy oddities" do
140
+ skip "debug defncopy on windows later" if host_windows?
153
141
  quietly { db_tasks.structure_dump configuration, filename }
154
142
  _(filedata).wont_match %r{\AUSE.*\z}
155
143
  _(filedata).wont_match %r{\AGO.*\z}
@@ -158,14 +146,13 @@ class SQLServerRakeStructureDumpLoadTest < SQLServerRakeTest
158
146
  _(filedata).must_match %r{background2\s+text\s+}
159
147
  end
160
148
 
161
- it 'can load dumped structure' do
162
- skip 'debug defncopy on windows later' if host_windows?
149
+ it "can load dumped structure" do
150
+ skip "debug defncopy on windows later" if host_windows?
163
151
  quietly { db_tasks.structure_dump configuration, filename }
164
152
  _(filedata).must_match %r{CREATE TABLE dbo\.users}
165
153
  db_tasks.purge(configuration)
166
- _(connection.tables).wont_include 'users'
167
- db_tasks.load_schema configuration, :sql, filename
168
- _(connection.tables).must_include 'users'
154
+ _(connection.tables).wont_include "users"
155
+ db_tasks.load_schema db_config, :sql, filename
156
+ _(connection.tables).must_include "users"
169
157
  end
170
-
171
158
  end
@@ -1,146 +1,159 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'cases/helper_sqlserver'
3
+ require "cases/helper_sqlserver"
4
4
 
5
5
  class SchemaDumperTestSQLServer < ActiveRecord::TestCase
6
-
7
6
  before { all_tables }
8
7
 
9
8
  let(:all_tables) { ActiveRecord::Base.connection.tables }
10
9
  let(:schema) { @generated_schema }
11
10
 
12
- it 'sst_datatypes' do
13
- generate_schema_for_table 'sst_datatypes'
14
- assert_line :bigint, type: 'bigint', limit: nil, precision: nil, scale: nil, default: 42
15
- assert_line :int, type: 'integer', limit: nil, precision: nil, scale: nil, default: 42
16
- assert_line :smallint, type: 'integer', limit: 2, precision: nil, scale: nil, default: 42
17
- assert_line :tinyint, type: 'integer', limit: 1, precision: nil, scale: nil, default: 42
18
- assert_line :bit, type: 'boolean', limit: nil, precision: nil, scale: nil, default: true
19
- assert_line :decimal_9_2, type: 'decimal', limit: nil, precision: 9, scale: 2, default: 12345.01
20
- assert_line :numeric_18_0, type: 'decimal', limit: nil, precision: 18, scale: 0, default: 191.0
21
- assert_line :numeric_36_2, type: 'decimal', limit: nil, precision: 36, scale: 2, default: 12345678901234567890.01
22
- assert_line :money, type: 'money', limit: nil, precision: 19, scale: 4, default: 4.2
23
- assert_line :smallmoney, type: 'smallmoney', limit: nil, precision: 10, scale: 4, default: 4.2
11
+ it "sst_datatypes" do
12
+ generate_schema_for_table "sst_datatypes"
13
+ assert_line :bigint, type: "bigint", limit: nil, precision: nil, scale: nil, default: 42
14
+ assert_line :int, type: "integer", limit: nil, precision: nil, scale: nil, default: 42
15
+ assert_line :smallint, type: "integer", limit: 2, precision: nil, scale: nil, default: 42
16
+ assert_line :tinyint, type: "integer", limit: 1, precision: nil, scale: nil, default: 42
17
+ assert_line :bit, type: "boolean", limit: nil, precision: nil, scale: nil, default: true
18
+ assert_line :decimal_9_2, type: "decimal", limit: nil, precision: 9, scale: 2, default: 12345.01
19
+ assert_line :numeric_18_0, type: "decimal", limit: nil, precision: 18, scale: nil, default: 191
20
+ assert_line :numeric_36_2, type: "decimal", limit: nil, precision: 36, scale: 2, default: 12345678901234567890.01
21
+ assert_line :money, type: "money", limit: nil, precision: 19, scale: 4, default: 4.2
22
+ assert_line :smallmoney, type: "smallmoney", limit: nil, precision: 10, scale: 4, default: 4.2
24
23
  # Approximate Numerics
25
- assert_line :float, type: 'float', limit: nil, precision: nil, scale: nil, default: 123.00000001
26
- assert_line :real, type: 'real', limit: nil, precision: nil, scale: nil, default: 123.45
24
+ assert_line :float, type: "float", limit: nil, precision: nil, scale: nil, default: 123.00000001
25
+ assert_line :real, type: "real", limit: nil, precision: nil, scale: nil, default: 123.45
27
26
  # Date and Time
28
- assert_line :date, type: 'date', limit: nil, precision: nil, scale: nil, default: "01-01-0001"
29
- assert_line :datetime, type: 'datetime', limit: nil, precision: nil, scale: nil, default: "01-01-1753 00:00:00.123"
27
+ assert_line :date, type: "date", limit: nil, precision: nil, scale: nil, default: "01-01-0001"
28
+ assert_line :datetime, type: "datetime", limit: nil, precision: nil, scale: nil, default: "01-01-1753 00:00:00.123"
30
29
  if connection_dblib_73?
31
- assert_line :datetime2_7, type: 'datetime', limit: nil, precision: 7, scale: nil, default: "12-31-9999 23:59:59.9999999"
32
- assert_line :datetime2_3, type: 'datetime', limit: nil, precision: 3, scale: nil, default: nil
33
- assert_line :datetime2_1, type: 'datetime', limit: nil, precision: 1, scale: nil, default: nil
30
+ assert_line :datetime2_7, type: "datetime", limit: nil, precision: 7, scale: nil, default: "12-31-9999 23:59:59.9999999"
31
+ assert_line :datetime2_3, type: "datetime", limit: nil, precision: 3, scale: nil, default: nil
32
+ assert_line :datetime2_1, type: "datetime", limit: nil, precision: 1, scale: nil, default: nil
34
33
  end
35
- assert_line :smalldatetime, type: 'smalldatetime',limit: nil, precision: nil, scale: nil, default: "01-01-1901 15:45:00.0"
34
+ assert_line :smalldatetime, type: "smalldatetime", limit: nil, precision: nil, scale: nil, default: "01-01-1901 15:45:00.0"
36
35
  if connection_dblib_73?
37
- assert_line :time_7, type: 'time', limit: nil, precision: 7, scale: nil, default: "04:20:00.2883215"
38
- assert_line :time_2, type: 'time', limit: nil, precision: 2, scale: nil, default: nil
39
- assert_line :time_default, type: 'time', limit: nil, precision: 7, scale: nil, default: "15:03:42.0621978"
36
+ assert_line :time_7, type: "time", limit: nil, precision: 7, scale: nil, default: "04:20:00.2883215"
37
+ assert_line :time_2, type: "time", limit: nil, precision: 2, scale: nil, default: nil
38
+ assert_line :time_default, type: "time", limit: nil, precision: 7, scale: nil, default: "15:03:42.0621978"
40
39
  end
41
40
  # Character Strings
42
- assert_line :char_10, type: 'char', limit: 10, precision: nil, scale: nil, default: "1234567890", collation: nil
43
- assert_line :varchar_50, type: 'varchar', limit: 50, precision: nil, scale: nil, default: "test varchar_50", collation: nil
44
- assert_line :varchar_max, type: 'varchar_max', limit: nil, precision: nil, scale: nil, default: "test varchar_max", collation: nil
45
- assert_line :text, type: 'text_basic', limit: nil, precision: nil, scale: nil, default: "test text", collation: nil
41
+ assert_line :char_10, type: "char", limit: 10, precision: nil, scale: nil, default: "1234567890", collation: nil
42
+ assert_line :varchar_50, type: "varchar", limit: 50, precision: nil, scale: nil, default: "test varchar_50", collation: nil
43
+ assert_line :varchar_max, type: "varchar_max", limit: nil, precision: nil, scale: nil, default: "test varchar_max", collation: nil
44
+ assert_line :text, type: "text_basic", limit: nil, precision: nil, scale: nil, default: "test text", collation: nil
46
45
  # Unicode Character Strings
47
- assert_line :nchar_10, type: 'nchar', limit: 10, precision: nil, scale: nil, default: "12345678åå", collation: nil
48
- assert_line :nvarchar_50, type: 'string', limit: 50, precision: nil, scale: nil, default: "test nvarchar_50 åå", collation: nil
49
- assert_line :nvarchar_max, type: 'text', limit: nil, precision: nil, scale: nil, default: "test nvarchar_max åå", collation: nil
50
- assert_line :ntext, type: 'ntext', limit: nil, precision: nil, scale: nil, default: "test ntext åå", collation: nil
46
+ assert_line :nchar_10, type: "nchar", limit: 10, precision: nil, scale: nil, default: "12345678åå", collation: nil
47
+ assert_line :nvarchar_50, type: "string", limit: 50, precision: nil, scale: nil, default: "test nvarchar_50 åå", collation: nil
48
+ assert_line :nvarchar_max, type: "text", limit: nil, precision: nil, scale: nil, default: "test nvarchar_max åå", collation: nil
49
+ assert_line :ntext, type: "ntext", limit: nil, precision: nil, scale: nil, default: "test ntext åå", collation: nil
51
50
  # Binary Strings
52
- assert_line :binary_49, type: 'binary_basic', limit: 49, precision: nil, scale: nil, default: nil
53
- assert_line :varbinary_49, type: 'varbinary', limit: 49, precision: nil, scale: nil, default: nil
54
- assert_line :varbinary_max, type: 'binary', limit: nil, precision: nil, scale: nil, default: nil
51
+ assert_line :binary_49, type: "binary_basic", limit: 49, precision: nil, scale: nil, default: nil
52
+ assert_line :varbinary_49, type: "varbinary", limit: 49, precision: nil, scale: nil, default: nil
53
+ assert_line :varbinary_max, type: "binary", limit: nil, precision: nil, scale: nil, default: nil
55
54
  # Other Data Types
56
- assert_line :uniqueidentifier, type: 'uuid', limit: nil, precision: nil, scale: nil, default: -> { "newid()" }
57
- assert_line :timestamp, type: 'ss_timestamp', limit: nil, precision: nil, scale: nil, default: nil
55
+ assert_line :uniqueidentifier, type: "uuid", limit: nil, precision: nil, scale: nil, default: -> { "newid()" }
56
+ assert_line :timestamp, type: "ss_timestamp", limit: nil, precision: nil, scale: nil, default: nil
58
57
  end
59
58
 
60
- it 'sst_datatypes_migration' do
59
+ it "sst_datatypes_migration" do
61
60
  columns = SSTestDatatypeMigration.columns_hash
62
- generate_schema_for_table 'sst_datatypes_migration'
61
+ generate_schema_for_table "sst_datatypes_migration"
63
62
  # Simple Rails conventions
64
- _(columns['integer_col'].sql_type).must_equal 'int(4)'
65
- _(columns['bigint_col'].sql_type).must_equal 'bigint(8)'
66
- _(columns['boolean_col'].sql_type).must_equal 'bit'
67
- _(columns['decimal_col'].sql_type).must_equal 'decimal(18,0)'
68
- _(columns['float_col'].sql_type).must_equal 'float'
69
- _(columns['string_col'].sql_type).must_equal 'nvarchar(4000)'
70
- _(columns['text_col'].sql_type).must_equal 'nvarchar(max)'
71
- _(columns['datetime_col'].sql_type).must_equal 'datetime'
72
- _(columns['timestamp_col'].sql_type).must_equal 'datetime'
73
- _(columns['time_col'].sql_type).must_equal 'time(7)'
74
- _(columns['date_col'].sql_type).must_equal 'date'
75
- _(columns['binary_col'].sql_type).must_equal 'varbinary(max)'
76
- assert_line :integer_col, type: 'integer', limit: nil, precision: nil, scale: nil, default: nil
77
- assert_line :bigint_col, type: 'bigint', limit: nil, precision: nil, scale: nil, default: nil
78
- assert_line :boolean_col, type: 'boolean', limit: nil, precision: nil, scale: nil, default: nil
79
- assert_line :decimal_col, type: 'decimal', limit: nil, precision: 18, scale: 0, default: nil
80
- assert_line :float_col, type: 'float', limit: nil, precision: nil, scale: nil, default: nil
81
- assert_line :string_col, type: 'string', limit: nil, precision: nil, scale: nil, default: nil
82
- assert_line :text_col, type: 'text', limit: nil, precision: nil, scale: nil, default: nil
83
- assert_line :datetime_col, type: 'datetime', limit: nil, precision: nil, scale: nil, default: nil
84
- assert_line :timestamp_col, type: 'datetime', limit: nil, precision: nil, scale: nil, default: nil
85
- assert_line :time_col, type: 'time', limit: nil, precision: 7, scale: nil, default: nil
86
- assert_line :date_col, type: 'date', limit: nil, precision: nil, scale: nil, default: nil
87
- assert_line :binary_col, type: 'binary', limit: nil, precision: nil, scale: nil, default: nil
63
+ _(columns["integer_col"].sql_type).must_equal "int(4)"
64
+ _(columns["bigint_col"].sql_type).must_equal "bigint(8)"
65
+ _(columns["boolean_col"].sql_type).must_equal "bit"
66
+ _(columns["decimal_col"].sql_type).must_equal "decimal(18,0)"
67
+ _(columns["float_col"].sql_type).must_equal "float"
68
+ _(columns["string_col"].sql_type).must_equal "nvarchar(4000)"
69
+ _(columns["text_col"].sql_type).must_equal "nvarchar(max)"
70
+ _(columns["datetime_col"].sql_type).must_equal "datetime"
71
+ _(columns["timestamp_col"].sql_type).must_equal "datetime"
72
+ _(columns["time_col"].sql_type).must_equal "time(7)"
73
+ _(columns["date_col"].sql_type).must_equal "date"
74
+ _(columns["binary_col"].sql_type).must_equal "varbinary(max)"
75
+ assert_line :integer_col, type: "integer", limit: nil, precision: nil, scale: nil, default: nil
76
+ assert_line :bigint_col, type: "bigint", limit: nil, precision: nil, scale: nil, default: nil
77
+ assert_line :boolean_col, type: "boolean", limit: nil, precision: nil, scale: nil, default: nil
78
+ assert_line :decimal_col, type: "decimal", limit: nil, precision: 18, scale: nil, default: nil
79
+ assert_line :float_col, type: "float", limit: nil, precision: nil, scale: nil, default: nil
80
+ assert_line :string_col, type: "string", limit: nil, precision: nil, scale: nil, default: nil
81
+ assert_line :text_col, type: "text", limit: nil, precision: nil, scale: nil, default: nil
82
+ assert_line :datetime_col, type: "datetime", limit: nil, precision: nil, scale: nil, default: nil
83
+ assert_line :timestamp_col, type: "datetime", limit: nil, precision: nil, scale: nil, default: nil
84
+ assert_line :time_col, type: "time", limit: nil, precision: 7, scale: nil, default: nil
85
+ assert_line :date_col, type: "date", limit: nil, precision: nil, scale: nil, default: nil
86
+ assert_line :binary_col, type: "binary", limit: nil, precision: nil, scale: nil, default: nil
88
87
  # Our type methods.
89
- _(columns['real_col'].sql_type).must_equal 'real'
90
- _(columns['money_col'].sql_type).must_equal 'money'
91
- _(columns['smalldatetime_col'].sql_type).must_equal 'smalldatetime'
92
- _(columns['datetime2_col'].sql_type).must_equal 'datetime2(7)'
93
- _(columns['datetimeoffset'].sql_type).must_equal 'datetimeoffset(7)'
94
- _(columns['smallmoney_col'].sql_type).must_equal 'smallmoney'
95
- _(columns['char_col'].sql_type).must_equal 'char(1)'
96
- _(columns['varchar_col'].sql_type).must_equal 'varchar(8000)'
97
- _(columns['text_basic_col'].sql_type).must_equal 'text'
98
- _(columns['nchar_col'].sql_type).must_equal 'nchar(1)'
99
- _(columns['ntext_col'].sql_type).must_equal 'ntext'
100
- _(columns['binary_basic_col'].sql_type).must_equal 'binary(1)'
101
- _(columns['varbinary_col'].sql_type).must_equal 'varbinary(8000)'
102
- _(columns['uuid_col'].sql_type).must_equal 'uniqueidentifier'
103
- _(columns['sstimestamp_col'].sql_type).must_equal 'timestamp'
104
- _(columns['json_col'].sql_type).must_equal 'nvarchar(max)'
105
- assert_line :real_col, type: 'real', limit: nil, precision: nil, scale: nil, default: nil
106
- assert_line :money_col, type: 'money', limit: nil, precision: 19, scale: 4, default: nil
107
- assert_line :smalldatetime_col, type: 'smalldatetime', limit: nil, precision: nil, scale: nil, default: nil
108
- assert_line :datetime2_col, type: 'datetime', limit: nil, precision: 7, scale: nil, default: nil
109
- assert_line :datetimeoffset, type: 'datetimeoffset', limit: nil, precision: 7, scale: nil, default: nil
110
- assert_line :smallmoney_col, type: 'smallmoney', limit: nil, precision: 10, scale: 4, default: nil
111
- assert_line :char_col, type: 'char', limit: 1, precision: nil, scale: nil, default: nil
112
- assert_line :varchar_col, type: 'varchar', limit: nil, precision: nil, scale: nil, default: nil
113
- assert_line :text_basic_col, type: 'text_basic', limit: nil, precision: nil, scale: nil, default: nil
114
- assert_line :nchar_col, type: 'nchar', limit: 1, precision: nil, scale: nil, default: nil
115
- assert_line :ntext_col, type: 'ntext', limit: nil, precision: nil, scale: nil, default: nil
116
- assert_line :binary_basic_col, type: 'binary_basic', limit: 1, precision: nil, scale: nil, default: nil
117
- assert_line :varbinary_col, type: 'varbinary', limit: nil, precision: nil, scale: nil, default: nil
118
- assert_line :uuid_col, type: 'uuid', limit: nil, precision: nil, scale: nil, default: nil
119
- assert_line :sstimestamp_col, type: 'ss_timestamp', limit: nil, precision: nil, scale: nil, default: nil
120
- assert_line :json_col, type: 'text', limit: nil, precision: nil, scale: nil, default: nil
88
+ _(columns["real_col"].sql_type).must_equal "real"
89
+ _(columns["money_col"].sql_type).must_equal "money"
90
+ _(columns["smalldatetime_col"].sql_type).must_equal "smalldatetime"
91
+ _(columns["datetime2_col"].sql_type).must_equal "datetime2(7)"
92
+ _(columns["datetimeoffset"].sql_type).must_equal "datetimeoffset(7)"
93
+ _(columns["smallmoney_col"].sql_type).must_equal "smallmoney"
94
+ _(columns["char_col"].sql_type).must_equal "char(1)"
95
+ _(columns["varchar_col"].sql_type).must_equal "varchar(8000)"
96
+ _(columns["text_basic_col"].sql_type).must_equal "text"
97
+ _(columns["nchar_col"].sql_type).must_equal "nchar(1)"
98
+ _(columns["ntext_col"].sql_type).must_equal "ntext"
99
+ _(columns["binary_basic_col"].sql_type).must_equal "binary(1)"
100
+ _(columns["varbinary_col"].sql_type).must_equal "varbinary(8000)"
101
+ _(columns["uuid_col"].sql_type).must_equal "uniqueidentifier"
102
+ _(columns["sstimestamp_col"].sql_type).must_equal "timestamp"
103
+ _(columns["json_col"].sql_type).must_equal "nvarchar(max)"
104
+ assert_line :real_col, type: "real", limit: nil, precision: nil, scale: nil, default: nil
105
+ assert_line :money_col, type: "money", limit: nil, precision: 19, scale: 4, default: nil
106
+ assert_line :smalldatetime_col, type: "smalldatetime", limit: nil, precision: nil, scale: nil, default: nil
107
+ assert_line :datetime2_col, type: "datetime", limit: nil, precision: 7, scale: nil, default: nil
108
+ assert_line :datetimeoffset, type: "datetimeoffset", limit: nil, precision: 7, scale: nil, default: nil
109
+ assert_line :smallmoney_col, type: "smallmoney", limit: nil, precision: 10, scale: 4, default: nil
110
+ assert_line :char_col, type: "char", limit: 1, precision: nil, scale: nil, default: nil
111
+ assert_line :varchar_col, type: "varchar", limit: nil, precision: nil, scale: nil, default: nil
112
+ assert_line :text_basic_col, type: "text_basic", limit: nil, precision: nil, scale: nil, default: nil
113
+ assert_line :nchar_col, type: "nchar", limit: 1, precision: nil, scale: nil, default: nil
114
+ assert_line :ntext_col, type: "ntext", limit: nil, precision: nil, scale: nil, default: nil
115
+ assert_line :binary_basic_col, type: "binary_basic", limit: 1, precision: nil, scale: nil, default: nil
116
+ assert_line :varbinary_col, type: "varbinary", limit: nil, precision: nil, scale: nil, default: nil
117
+ assert_line :uuid_col, type: "uuid", limit: nil, precision: nil, scale: nil, default: nil
118
+ assert_line :sstimestamp_col, type: "ss_timestamp", limit: nil, precision: nil, scale: nil, default: nil
119
+ assert_line :json_col, type: "text", limit: nil, precision: nil, scale: nil, default: nil
120
+ end
121
+
122
+ it "dump column collation" do
123
+ generate_schema_for_table('sst_string_collation')
124
+
125
+ assert_line :string_without_collation, type: "string", limit: nil, default: nil, collation: nil
126
+ assert_line :string_default_collation, type: "varchar", limit: nil, default: nil, collation: nil
127
+ assert_line :string_with_collation, type: "varchar", limit: nil, default: nil, collation: "SQL_Latin1_General_CP1_CS_AS"
128
+ assert_line :varchar_with_collation, type: "varchar", limit: nil, default: nil, collation: "SQL_Latin1_General_CP1_CS_AS"
121
129
  end
122
130
 
123
131
  # Special Cases
124
132
 
125
- it 'honor nonstandard primary keys' do
126
- generate_schema_for_table('movies') do |output|
133
+ it "honor nonstandard primary keys" do
134
+ generate_schema_for_table("movies") do |output|
127
135
  match = output.match(%r{create_table "movies"(.*)do})
128
136
  assert_not_nil(match, "nonstandardpk table not found")
129
137
  assert_match %r(primary_key: "movieid"), match[1], "non-standard primary key not preserved"
130
138
  end
131
139
  end
132
140
 
133
- it 'no id with model driven primary key' do
134
- output = generate_schema_for_table 'sst_no_pk_data'
141
+ it "no id with model driven primary key" do
142
+ output = generate_schema_for_table "sst_no_pk_data"
135
143
  _(output).must_match %r{create_table "sst_no_pk_data".*id:\sfalse.*do}
136
- assert_line :name, type: 'string', limit: nil, default: nil, collation: nil
144
+ assert_line :name, type: "string", limit: nil, default: nil, collation: nil
137
145
  end
138
146
 
147
+ it "dumps field with unique key constraints only once" do
148
+ output = generate_schema_for_table "unique_key_dumped_table"
149
+
150
+ _(output.scan('t.integer "unique_field"').length).must_equal(1)
151
+ end
139
152
 
140
153
  private
141
154
 
142
155
  def generate_schema_for_table(*table_names)
143
- require 'stringio'
156
+ require "stringio"
144
157
  stream = StringIO.new
145
158
  ActiveRecord::SchemaDumper.ignore_tables = all_tables - table_names
146
159
  ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, stream)
@@ -150,6 +163,7 @@ class SchemaDumperTestSQLServer < ActiveRecord::TestCase
150
163
  type_matcher = /\A\s+t\.\w+\s+"(.*?)"[,\n]/
151
164
  @generated_schema.each_line do |line|
152
165
  next unless line =~ type_matcher
166
+
153
167
  @schema_lines[Regexp.last_match[1]] = SchemaLine.new(line)
154
168
  end
155
169
  @generated_schema
@@ -159,14 +173,17 @@ class SchemaDumperTestSQLServer < ActiveRecord::TestCase
159
173
  @schema_lines[column_name.to_s]
160
174
  end
161
175
 
162
- def assert_line(column_name, options={})
176
+ def assert_line(column_name, options = {})
163
177
  line = line(column_name)
164
- assert line, "Count not find line with column name: #{column_name.inspect} in schema:\n#{schema}"
178
+ assert line, "Could not find line with column name: #{column_name.inspect} in schema:\n#{schema}"
179
+
165
180
  [:type, :limit, :precision, :scale, :collation, :default].each do |key|
166
181
  next unless options.key?(key)
182
+
167
183
  actual = key == :type ? line.send(:type_method) : line.send(key)
168
184
  expected = options[key]
169
185
  message = "#{key.to_s.titleize} of #{expected.inspect} not found in:\n#{line}"
186
+
170
187
  if expected.nil?
171
188
  _(actual).must_be_nil message
172
189
  elsif expected.is_a?(Array)
@@ -182,7 +199,6 @@ class SchemaDumperTestSQLServer < ActiveRecord::TestCase
182
199
  end
183
200
 
184
201
  class SchemaLine
185
-
186
202
  LINE_PARSER = %r{t\.(\w+)\s+"(.*?)"[,\s+](.*)}
187
203
 
188
204
  attr_reader :line,
@@ -230,8 +246,5 @@ class SchemaDumperTestSQLServer < ActiveRecord::TestCase
230
246
  rescue SyntaxError
231
247
  {}
232
248
  end
233
-
234
249
  end
235
-
236
250
  end
237
-