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.
- checksums.yaml +4 -4
- data/.github/workflows/ci.yml +26 -0
- data/.gitignore +1 -0
- data/.rubocop.yml +29 -0
- data/CHANGELOG.md +18 -23
- data/Gemfile +11 -5
- data/Guardfile +9 -8
- data/README.md +32 -3
- data/RUNNING_UNIT_TESTS.md +1 -1
- data/Rakefile +12 -16
- data/VERSION +1 -1
- data/activerecord-sqlserver-adapter.gemspec +4 -4
- data/lib/active_record/connection_adapters/sqlserver/core_ext/active_record.rb +0 -4
- data/lib/active_record/connection_adapters/sqlserver/core_ext/attribute_methods.rb +1 -4
- data/lib/active_record/connection_adapters/sqlserver/core_ext/calculations.rb +3 -13
- data/lib/active_record/connection_adapters/sqlserver/core_ext/explain.rb +8 -5
- data/lib/active_record/connection_adapters/sqlserver/core_ext/finder_methods.rb +2 -3
- data/lib/active_record/connection_adapters/sqlserver/core_ext/query_methods.rb +2 -3
- data/lib/active_record/connection_adapters/sqlserver/database_limits.rb +0 -4
- data/lib/active_record/connection_adapters/sqlserver/database_statements.rb +58 -43
- data/lib/active_record/connection_adapters/sqlserver/database_tasks.rb +7 -12
- data/lib/active_record/connection_adapters/sqlserver/errors.rb +0 -3
- data/lib/active_record/connection_adapters/sqlserver/quoting.rb +15 -15
- data/lib/active_record/connection_adapters/sqlserver/schema_creation.rb +22 -3
- data/lib/active_record/connection_adapters/sqlserver/schema_dumper.rb +16 -10
- data/lib/active_record/connection_adapters/sqlserver/schema_statements.rb +131 -105
- data/lib/active_record/connection_adapters/sqlserver/showplan.rb +6 -8
- data/lib/active_record/connection_adapters/sqlserver/showplan/printer_table.rb +2 -2
- data/lib/active_record/connection_adapters/sqlserver/showplan/printer_xml.rb +1 -1
- data/lib/active_record/connection_adapters/sqlserver/sql_type_metadata.rb +25 -7
- data/lib/active_record/connection_adapters/sqlserver/table_definition.rb +1 -5
- data/lib/active_record/connection_adapters/sqlserver/transaction.rb +6 -10
- data/lib/active_record/connection_adapters/sqlserver/type.rb +36 -35
- data/lib/active_record/connection_adapters/sqlserver/type/big_integer.rb +0 -2
- data/lib/active_record/connection_adapters/sqlserver/type/binary.rb +0 -2
- data/lib/active_record/connection_adapters/sqlserver/type/boolean.rb +0 -2
- data/lib/active_record/connection_adapters/sqlserver/type/char.rb +2 -2
- data/lib/active_record/connection_adapters/sqlserver/type/data.rb +0 -2
- data/lib/active_record/connection_adapters/sqlserver/type/date.rb +2 -3
- data/lib/active_record/connection_adapters/sqlserver/type/datetime.rb +2 -3
- data/lib/active_record/connection_adapters/sqlserver/type/datetime2.rb +0 -2
- data/lib/active_record/connection_adapters/sqlserver/type/datetimeoffset.rb +0 -2
- data/lib/active_record/connection_adapters/sqlserver/type/decimal.rb +0 -2
- data/lib/active_record/connection_adapters/sqlserver/type/decimal_without_scale.rb +22 -0
- data/lib/active_record/connection_adapters/sqlserver/type/float.rb +0 -2
- data/lib/active_record/connection_adapters/sqlserver/type/integer.rb +0 -2
- data/lib/active_record/connection_adapters/sqlserver/type/json.rb +0 -1
- data/lib/active_record/connection_adapters/sqlserver/type/money.rb +0 -2
- data/lib/active_record/connection_adapters/sqlserver/type/real.rb +0 -2
- data/lib/active_record/connection_adapters/sqlserver/type/small_integer.rb +0 -2
- data/lib/active_record/connection_adapters/sqlserver/type/small_money.rb +0 -2
- data/lib/active_record/connection_adapters/sqlserver/type/smalldatetime.rb +0 -2
- data/lib/active_record/connection_adapters/sqlserver/type/string.rb +0 -2
- data/lib/active_record/connection_adapters/sqlserver/type/text.rb +0 -2
- data/lib/active_record/connection_adapters/sqlserver/type/time.rb +2 -3
- data/lib/active_record/connection_adapters/sqlserver/type/time_value_fractional.rb +6 -9
- data/lib/active_record/connection_adapters/sqlserver/type/timestamp.rb +0 -2
- data/lib/active_record/connection_adapters/sqlserver/type/tiny_integer.rb +0 -2
- data/lib/active_record/connection_adapters/sqlserver/type/unicode_char.rb +1 -3
- data/lib/active_record/connection_adapters/sqlserver/type/unicode_string.rb +0 -2
- data/lib/active_record/connection_adapters/sqlserver/type/unicode_text.rb +0 -2
- data/lib/active_record/connection_adapters/sqlserver/type/unicode_varchar.rb +0 -2
- data/lib/active_record/connection_adapters/sqlserver/type/unicode_varchar_max.rb +0 -2
- data/lib/active_record/connection_adapters/sqlserver/type/uuid.rb +1 -2
- data/lib/active_record/connection_adapters/sqlserver/type/varbinary.rb +1 -3
- data/lib/active_record/connection_adapters/sqlserver/type/varbinary_max.rb +0 -2
- data/lib/active_record/connection_adapters/sqlserver/type/varchar.rb +1 -3
- data/lib/active_record/connection_adapters/sqlserver/type/varchar_max.rb +0 -2
- data/lib/active_record/connection_adapters/sqlserver/utils.rb +8 -11
- data/lib/active_record/connection_adapters/sqlserver/version.rb +0 -2
- data/lib/active_record/connection_adapters/sqlserver_adapter.rb +170 -136
- data/lib/active_record/connection_adapters/sqlserver_column.rb +16 -1
- data/lib/active_record/sqlserver_base.rb +9 -15
- data/lib/active_record/tasks/sqlserver_database_tasks.rb +36 -39
- data/lib/activerecord-sqlserver-adapter.rb +1 -1
- data/lib/arel/visitors/sqlserver.rb +126 -50
- data/lib/arel_sqlserver.rb +2 -2
- data/test/cases/adapter_test_sqlserver.rb +203 -190
- data/test/cases/change_column_collation_test_sqlserver.rb +33 -0
- data/test/cases/change_column_null_test_sqlserver.rb +12 -12
- data/test/cases/coerced_tests.rb +656 -318
- data/test/cases/column_test_sqlserver.rb +285 -284
- data/test/cases/connection_test_sqlserver.rb +15 -20
- data/test/cases/disconnected_test_sqlserver.rb +39 -0
- data/test/cases/execute_procedure_test_sqlserver.rb +26 -19
- data/test/cases/fetch_test_sqlserver.rb +14 -22
- data/test/cases/fully_qualified_identifier_test_sqlserver.rb +12 -18
- data/test/cases/helper_sqlserver.rb +13 -15
- data/test/cases/in_clause_test_sqlserver.rb +36 -9
- data/test/cases/index_test_sqlserver.rb +13 -15
- data/test/cases/json_test_sqlserver.rb +23 -25
- data/test/cases/lateral_test_sqlserver.rb +35 -0
- data/test/cases/migration_test_sqlserver.rb +71 -26
- data/test/cases/optimizer_hints_test_sqlserver.rb +72 -0
- data/test/cases/order_test_sqlserver.rb +57 -53
- data/test/cases/pessimistic_locking_test_sqlserver.rb +25 -33
- data/test/cases/primary_keys_test_sqlserver.rb +103 -0
- data/test/cases/rake_test_sqlserver.rb +33 -46
- data/test/cases/schema_dumper_test_sqlserver.rb +121 -108
- data/test/cases/schema_test_sqlserver.rb +18 -26
- data/test/cases/scratchpad_test_sqlserver.rb +2 -4
- data/test/cases/showplan_test_sqlserver.rb +24 -33
- data/test/cases/specific_schema_test_sqlserver.rb +66 -65
- data/test/cases/transaction_test_sqlserver.rb +16 -19
- data/test/cases/trigger_test_sqlserver.rb +12 -12
- data/test/cases/utils_test_sqlserver.rb +68 -70
- data/test/cases/uuid_test_sqlserver.rb +11 -13
- data/test/debug.rb +6 -6
- data/test/migrations/create_clients_and_change_column_collation.rb +19 -0
- data/test/migrations/create_clients_and_change_column_null.rb +1 -1
- data/test/migrations/transaction_table/1_table_will_never_be_created.rb +2 -4
- data/test/models/sqlserver/booking.rb +1 -1
- data/test/models/sqlserver/customers_view.rb +1 -1
- data/test/models/sqlserver/dollar_table_name.rb +1 -1
- data/test/models/sqlserver/edge_schema.rb +1 -3
- data/test/models/sqlserver/fk_has_fk.rb +1 -1
- data/test/models/sqlserver/fk_has_pk.rb +1 -1
- data/test/models/sqlserver/natural_pk_data.rb +2 -2
- data/test/models/sqlserver/natural_pk_int_data.rb +1 -1
- data/test/models/sqlserver/no_pk_data.rb +1 -1
- data/test/models/sqlserver/object_default.rb +1 -1
- data/test/models/sqlserver/quoted_table.rb +2 -2
- data/test/models/sqlserver/quoted_view_1.rb +1 -1
- data/test/models/sqlserver/quoted_view_2.rb +1 -1
- data/test/models/sqlserver/sst_memory.rb +1 -1
- data/test/models/sqlserver/sst_string_collation.rb +3 -0
- data/test/models/sqlserver/string_default.rb +1 -1
- data/test/models/sqlserver/string_defaults_big_view.rb +1 -1
- data/test/models/sqlserver/string_defaults_view.rb +1 -1
- data/test/models/sqlserver/tinyint_pk.rb +1 -1
- data/test/models/sqlserver/trigger.rb +2 -2
- data/test/models/sqlserver/trigger_history.rb +1 -1
- data/test/models/sqlserver/upper.rb +1 -1
- data/test/models/sqlserver/uppered.rb +1 -1
- data/test/models/sqlserver/uuid.rb +1 -1
- data/test/schema/sqlserver_specific_schema.rb +36 -21
- data/test/support/coerceable_test_sqlserver.rb +1 -4
- data/test/support/connection_reflection.rb +1 -2
- data/test/support/core_ext/query_cache.rb +1 -1
- data/test/support/load_schema_sqlserver.rb +3 -5
- data/test/support/marshal_compatibility_fixtures/SQLServer/rails_6_0_topic.dump +0 -0
- data/test/support/marshal_compatibility_fixtures/SQLServer/rails_6_0_topic_associations.dump +0 -0
- data/test/support/minitest_sqlserver.rb +1 -1
- data/test/support/paths_sqlserver.rb +9 -11
- data/test/support/rake_helpers.rb +12 -10
- data/test/support/sql_counter_sqlserver.rb +14 -16
- data/test/support/test_in_memory_oltp.rb +7 -7
- metadata +31 -11
- data/.travis.yml +0 -23
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require
|
|
4
|
-
require
|
|
5
|
-
require
|
|
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
|
|
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
|
|
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
|
|
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
|
|
43
|
-
|
|
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
|
|
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(
|
|
51
|
+
Person.lock("WITH(HOLDLOCK, ROWLOCK)").load
|
|
54
52
|
end
|
|
55
53
|
end
|
|
56
54
|
|
|
57
|
-
describe
|
|
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
|
|
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(
|
|
64
|
+
Person.lock("WITH(NOLOCK)").joins(:readers).load
|
|
68
65
|
end
|
|
69
66
|
end
|
|
70
67
|
|
|
71
|
-
it
|
|
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
|
|
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(
|
|
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
|
|
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
|
|
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
|
|
100
|
-
_(people[1].first_name).must_equal
|
|
101
|
-
_(people[2].first_name).must_equal
|
|
102
|
-
_(people[3].first_name).must_equal
|
|
103
|
-
_(people[4].first_name).must_equal
|
|
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
|
|
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) {
|
|
14
|
-
let(:default_configuration) { ARTest.
|
|
15
|
-
let(:configuration) { default_configuration.merge(
|
|
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
|
|
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(
|
|
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
|
|
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
|
|
49
|
+
it "creates database with default collation" do
|
|
52
50
|
quietly { db_tasks.create configuration }
|
|
53
|
-
_(connection.collation).must_equal
|
|
51
|
+
_(connection.collation).must_equal "SQL_Latin1_General_CP1_CI_AS"
|
|
54
52
|
end
|
|
55
53
|
|
|
56
|
-
it
|
|
57
|
-
quietly { db_tasks.create configuration.merge(
|
|
58
|
-
_(connection.collation).must_equal
|
|
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
|
|
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
|
|
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
|
|
74
|
+
_(connection.current_database).must_equal "master"
|
|
79
75
|
end
|
|
80
76
|
|
|
81
|
-
it
|
|
82
|
-
message = capture(:stderr) { db_tasks.drop configuration.merge(
|
|
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
|
|
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
|
|
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
|
|
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
|
|
115
|
-
_(db_tasks.charset(configuration)).must_equal
|
|
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
|
|
127
|
-
_(db_tasks.collation(configuration)).must_equal
|
|
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
|
|
152
|
-
skip
|
|
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
|
|
162
|
-
skip
|
|
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
|
|
167
|
-
db_tasks.load_schema
|
|
168
|
-
_(connection.tables).must_include
|
|
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
|
|
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
|
|
13
|
-
generate_schema_for_table
|
|
14
|
-
assert_line :bigint, type:
|
|
15
|
-
assert_line :int, type:
|
|
16
|
-
assert_line :smallint, type:
|
|
17
|
-
assert_line :tinyint, type:
|
|
18
|
-
assert_line :bit, type:
|
|
19
|
-
assert_line :decimal_9_2, type:
|
|
20
|
-
assert_line :numeric_18_0, type:
|
|
21
|
-
assert_line :numeric_36_2, type:
|
|
22
|
-
assert_line :money, type:
|
|
23
|
-
assert_line :smallmoney, type:
|
|
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:
|
|
26
|
-
assert_line :real, type:
|
|
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:
|
|
29
|
-
assert_line :datetime, type:
|
|
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
|
-
|
|
32
|
-
|
|
33
|
-
|
|
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,
|
|
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
|
-
|
|
38
|
-
|
|
39
|
-
|
|
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:
|
|
43
|
-
assert_line :varchar_50, type:
|
|
44
|
-
assert_line :varchar_max, type:
|
|
45
|
-
assert_line :text, type:
|
|
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:
|
|
48
|
-
assert_line :nvarchar_50, type:
|
|
49
|
-
assert_line :nvarchar_max, type:
|
|
50
|
-
assert_line :ntext, type:
|
|
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:
|
|
53
|
-
assert_line :varbinary_49, type:
|
|
54
|
-
assert_line :varbinary_max, type:
|
|
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:
|
|
57
|
-
assert_line :timestamp, type:
|
|
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
|
|
59
|
+
it "sst_datatypes_migration" do
|
|
61
60
|
columns = SSTestDatatypeMigration.columns_hash
|
|
62
|
-
generate_schema_for_table
|
|
61
|
+
generate_schema_for_table "sst_datatypes_migration"
|
|
63
62
|
# Simple Rails conventions
|
|
64
|
-
_(columns[
|
|
65
|
-
_(columns[
|
|
66
|
-
_(columns[
|
|
67
|
-
_(columns[
|
|
68
|
-
_(columns[
|
|
69
|
-
_(columns[
|
|
70
|
-
_(columns[
|
|
71
|
-
_(columns[
|
|
72
|
-
_(columns[
|
|
73
|
-
_(columns[
|
|
74
|
-
_(columns[
|
|
75
|
-
_(columns[
|
|
76
|
-
assert_line :integer_col, type:
|
|
77
|
-
assert_line :bigint_col, type:
|
|
78
|
-
assert_line :boolean_col, type:
|
|
79
|
-
assert_line :decimal_col, type:
|
|
80
|
-
assert_line :float_col, type:
|
|
81
|
-
assert_line :string_col, type:
|
|
82
|
-
assert_line :text_col, type:
|
|
83
|
-
assert_line :datetime_col, type:
|
|
84
|
-
assert_line :timestamp_col, type:
|
|
85
|
-
assert_line :time_col, type:
|
|
86
|
-
assert_line :date_col, type:
|
|
87
|
-
assert_line :binary_col, type:
|
|
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[
|
|
90
|
-
_(columns[
|
|
91
|
-
_(columns[
|
|
92
|
-
_(columns[
|
|
93
|
-
_(columns[
|
|
94
|
-
_(columns[
|
|
95
|
-
_(columns[
|
|
96
|
-
_(columns[
|
|
97
|
-
_(columns[
|
|
98
|
-
_(columns[
|
|
99
|
-
_(columns[
|
|
100
|
-
_(columns[
|
|
101
|
-
_(columns[
|
|
102
|
-
_(columns[
|
|
103
|
-
_(columns[
|
|
104
|
-
_(columns[
|
|
105
|
-
assert_line :real_col, type:
|
|
106
|
-
assert_line :money_col, type:
|
|
107
|
-
assert_line :smalldatetime_col, type:
|
|
108
|
-
assert_line :datetime2_col, type:
|
|
109
|
-
assert_line :datetimeoffset, type:
|
|
110
|
-
assert_line :smallmoney_col, type:
|
|
111
|
-
assert_line :char_col, type:
|
|
112
|
-
assert_line :varchar_col, type:
|
|
113
|
-
assert_line :text_basic_col, type:
|
|
114
|
-
assert_line :nchar_col, type:
|
|
115
|
-
assert_line :ntext_col, type:
|
|
116
|
-
assert_line :binary_basic_col, type:
|
|
117
|
-
assert_line :varbinary_col, type:
|
|
118
|
-
assert_line :uuid_col, type:
|
|
119
|
-
assert_line :sstimestamp_col, type:
|
|
120
|
-
assert_line :json_col, type:
|
|
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
|
|
126
|
-
generate_schema_for_table(
|
|
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
|
|
134
|
-
output = generate_schema_for_table
|
|
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:
|
|
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
|
|
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, "
|
|
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
|
-
|