activerecord-jdbcsqlserver-adapter 51.1.0 → 52.0.0
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/.travis.yml +1 -1
- data/CHANGELOG.md +22 -39
- data/{Dockerfile → Dockerfile.ci} +0 -0
- data/Gemfile +1 -3
- data/README.md +5 -8
- data/VERSION +1 -1
- data/activerecord-jdbcsqlserver-adapter.gemspec +2 -3
- data/docker-compose.ci.yml +7 -5
- data/lib/active_record/connection_adapters/sqlserver/core_ext/calculations.rb +25 -29
- data/lib/active_record/connection_adapters/sqlserver/core_ext/explain.rb +14 -18
- data/lib/active_record/connection_adapters/sqlserver/core_ext/finder_methods.rb +43 -0
- data/lib/active_record/connection_adapters/sqlserver/core_ext/query_methods.rb +26 -0
- data/lib/active_record/connection_adapters/sqlserver/database_limits.rb +13 -2
- data/lib/active_record/connection_adapters/sqlserver/database_statements.rb +53 -10
- data/lib/active_record/connection_adapters/sqlserver/database_tasks.rb +1 -0
- data/lib/active_record/connection_adapters/sqlserver/jdbc_overrides.rb +5 -13
- data/lib/active_record/connection_adapters/sqlserver/schema_creation.rb +2 -1
- data/lib/active_record/connection_adapters/sqlserver/schema_dumper.rb +2 -2
- data/lib/active_record/connection_adapters/sqlserver/schema_statements.rb +43 -27
- data/lib/active_record/connection_adapters/sqlserver/transaction.rb +3 -4
- data/lib/active_record/connection_adapters/sqlserver/type/json.rb +1 -1
- data/lib/active_record/connection_adapters/sqlserver/type/string.rb +7 -0
- data/lib/active_record/connection_adapters/sqlserver/type/time.rb +1 -0
- data/lib/active_record/connection_adapters/sqlserver_adapter.rb +20 -14
- data/lib/active_record/tasks/sqlserver_database_tasks.rb +3 -1
- data/lib/activerecord-jdbcsqlserver-adapter.rb +3 -0
- data/lib/arel/visitors/sqlserver.rb +1 -1
- data/lib/arel_sqlserver.rb +0 -1
- data/test/bin/install-freetds.sh +18 -0
- data/test/cases/adapter_test_sqlserver.rb +29 -21
- data/test/cases/change_column_null_test_sqlserver.rb +42 -0
- data/test/cases/coerced_tests.rb +304 -30
- data/test/cases/column_test_sqlserver.rb +496 -462
- data/test/cases/connection_test_sqlserver.rb +2 -2
- data/test/cases/fetch_test_sqlserver.rb +5 -5
- data/test/cases/helper_sqlserver.rb +6 -0
- data/test/cases/json_test_sqlserver.rb +6 -6
- data/test/cases/migration_test_sqlserver.rb +13 -3
- data/test/cases/order_test_sqlserver.rb +19 -19
- data/test/cases/pessimistic_locking_test_sqlserver.rb +9 -9
- data/test/cases/rake_test_sqlserver.rb +20 -20
- data/test/cases/schema_dumper_test_sqlserver.rb +34 -33
- data/test/cases/schema_test_sqlserver.rb +2 -2
- data/test/cases/showplan_test_sqlserver.rb +25 -10
- data/test/cases/specific_schema_test_sqlserver.rb +11 -11
- data/test/cases/transaction_test_sqlserver.rb +9 -9
- data/test/cases/trigger_test_sqlserver.rb +8 -8
- data/test/cases/utils_test_sqlserver.rb +36 -36
- data/test/cases/uuid_test_sqlserver.rb +8 -8
- data/test/migrations/create_clients_and_change_column_null.rb +23 -0
- data/test/schema/datatypes/2012.sql +1 -0
- data/test/schema/sqlserver_specific_schema.rb +9 -1
- data/test/support/core_ext/query_cache.rb +29 -0
- metadata +19 -10
- data/BACKERS.md +0 -32
@@ -5,7 +5,7 @@ class SchemaTestSQLServer < ActiveRecord::TestCase
|
|
5
5
|
describe 'When table is dbo schema' do
|
6
6
|
|
7
7
|
it 'find primary key for tables with odd schema' do
|
8
|
-
connection.primary_key('sst_natural_pk_data').must_equal 'legacy_id'
|
8
|
+
_(connection.primary_key('sst_natural_pk_data')).must_equal 'legacy_id'
|
9
9
|
end
|
10
10
|
|
11
11
|
end
|
@@ -18,7 +18,7 @@ class SchemaTestSQLServer < ActiveRecord::TestCase
|
|
18
18
|
end
|
19
19
|
|
20
20
|
it 'find primary key for tables with odd schema' do
|
21
|
-
connection.primary_key('test.sst_schema_natural_id').must_equal 'legacy_id'
|
21
|
+
_(connection.primary_key('test.sst_schema_natural_id')).must_equal 'legacy_id'
|
22
22
|
end
|
23
23
|
|
24
24
|
it "have only one identity column" do
|
@@ -5,25 +5,40 @@ class ShowplanTestSQLServer < ActiveRecord::TestCase
|
|
5
5
|
|
6
6
|
fixtures :cars
|
7
7
|
|
8
|
+
# For some reason the default max width truncates values that we are looking for in jruby
|
9
|
+
ActiveRecord::ConnectionAdapters::SQLServer::Showplan::PrinterTable.max_column_width = 500 if defined? JRUBY_VERSION
|
10
|
+
|
8
11
|
describe 'Unprepare previously prepared SQL' do
|
9
12
|
|
10
13
|
it 'from simple statement' do
|
11
14
|
plan = Car.where(id: 1).explain
|
12
|
-
plan.must_include "SELECT [cars].* FROM [cars] WHERE [cars].[id] = 1"
|
13
|
-
plan.must_include "Clustered Index Seek", 'make sure we do not showplan the sp_executesql'
|
15
|
+
_(plan).must_include "SELECT [cars].* FROM [cars] WHERE [cars].[id] = 1"
|
16
|
+
_(plan).must_include "Clustered Index Seek", 'make sure we do not showplan the sp_executesql'
|
14
17
|
end
|
15
18
|
|
16
19
|
it 'from multiline statement' do
|
17
20
|
plan = Car.where("\n id = 1 \n").explain
|
18
|
-
plan.must_include "SELECT [cars].* FROM [cars] WHERE (\n id = 1 \n)"
|
19
|
-
plan.must_include "Clustered Index Seek", 'make sure we do not showplan the sp_executesql'
|
21
|
+
_(plan).must_include "SELECT [cars].* FROM [cars] WHERE (\n id = 1 \n)"
|
22
|
+
_(plan).must_include "Clustered Index Seek", 'make sure we do not showplan the sp_executesql'
|
20
23
|
end
|
21
24
|
|
22
25
|
it 'from prepared statement' do
|
23
26
|
plan = Car.where(name: ',').limit(1).explain
|
24
|
-
plan.must_include " SELECT [cars].* FROM [cars] WHERE [cars].[name]"
|
25
|
-
plan.must_include "TOP EXPRESSION", 'make sure we do not showplan the sp_executesql'
|
26
|
-
plan.must_include "Clustered Index Scan", 'make sure we do not showplan the sp_executesql'
|
27
|
+
_(plan).must_include " SELECT [cars].* FROM [cars] WHERE [cars].[name]"
|
28
|
+
_(plan).must_include "TOP EXPRESSION", 'make sure we do not showplan the sp_executesql'
|
29
|
+
_(plan).must_include "Clustered Index Scan", 'make sure we do not showplan the sp_executesql'
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'from array condition using index' do
|
33
|
+
plan = Car.where(id: [1, 2]).explain
|
34
|
+
_(plan).must_include " SELECT [cars].* FROM [cars] WHERE [cars].[id] IN (1, 2)"
|
35
|
+
_(plan).must_include "Clustered Index Seek", 'make sure we do not showplan the sp_executesql'
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'from array condition' do
|
39
|
+
plan = Car.where(name: ['honda', 'zyke']).explain
|
40
|
+
_(plan).must_include " SELECT [cars].* FROM [cars] WHERE [cars].[name] IN (N'honda', N'zyke')"
|
41
|
+
_(plan).must_include "Clustered Index Scan", 'make sure we do not showplan the sp_executesql'
|
27
42
|
end
|
28
43
|
|
29
44
|
end
|
@@ -33,8 +48,8 @@ class ShowplanTestSQLServer < ActiveRecord::TestCase
|
|
33
48
|
it 'use simple table printer' do
|
34
49
|
with_showplan_option('SHOWPLAN_TEXT') do
|
35
50
|
plan = Car.where(id: 1).explain
|
36
|
-
plan.must_include "SELECT [cars].* FROM [cars] WHERE [cars].[id]"
|
37
|
-
plan.must_include "Clustered Index Seek", 'make sure we do not showplan the sp_executesql'
|
51
|
+
_(plan).must_include "SELECT [cars].* FROM [cars] WHERE [cars].[id]"
|
52
|
+
_(plan).must_include "Clustered Index Seek", 'make sure we do not showplan the sp_executesql'
|
38
53
|
end
|
39
54
|
end
|
40
55
|
|
@@ -45,7 +60,7 @@ class ShowplanTestSQLServer < ActiveRecord::TestCase
|
|
45
60
|
it 'show formatted xml' do
|
46
61
|
with_showplan_option('SHOWPLAN_XML') do
|
47
62
|
plan = Car.where(id: 1).explain
|
48
|
-
plan.must_include 'ShowPlanXML'
|
63
|
+
_(plan).must_include 'ShowPlanXML'
|
49
64
|
end
|
50
65
|
end
|
51
66
|
|
@@ -11,8 +11,8 @@ class SpecificSchemaTestSQLServer < ActiveRecord::TestCase
|
|
11
11
|
|
12
12
|
it 'models can use tinyint pk tables' do
|
13
13
|
obj = SSTestTinyintPk.create! name: '1'
|
14
|
-
['Fixnum', 'Integer'].must_include obj.id.class.name
|
15
|
-
SSTestTinyintPk.find(obj.id).must_equal obj
|
14
|
+
_(['Fixnum', 'Integer']).must_include obj.id.class.name
|
15
|
+
_(SSTestTinyintPk.find(obj.id)).must_equal obj
|
16
16
|
end
|
17
17
|
|
18
18
|
it 'be able to complex count tables with no primary key' do
|
@@ -58,17 +58,17 @@ class SpecificSchemaTestSQLServer < ActiveRecord::TestCase
|
|
58
58
|
|
59
59
|
it 'default objects work' do
|
60
60
|
obj = SSTestObjectDefault.create! name: 'MetaSkills'
|
61
|
-
obj.date.must_be_nil 'since this is set on insert'
|
62
|
-
obj.reload.date.must_be_instance_of Date
|
61
|
+
_(obj.date).must_be_nil 'since this is set on insert'
|
62
|
+
_(obj.reload.date).must_be_instance_of Date
|
63
63
|
end
|
64
64
|
|
65
65
|
it 'allows datetime2 as timestamps' do
|
66
|
-
SSTestBooking.columns_hash['created_at'].sql_type.must_equal 'datetime2(7)'
|
67
|
-
SSTestBooking.columns_hash['updated_at'].sql_type.must_equal 'datetime2(7)'
|
66
|
+
_(SSTestBooking.columns_hash['created_at'].sql_type).must_equal 'datetime2(7)'
|
67
|
+
_(SSTestBooking.columns_hash['updated_at'].sql_type).must_equal 'datetime2(7)'
|
68
68
|
obj1 = SSTestBooking.new name: 'test1'
|
69
69
|
obj1.save!
|
70
|
-
obj1.created_at.must_be_instance_of Time
|
71
|
-
obj1.updated_at.must_be_instance_of Time
|
70
|
+
_(obj1.created_at).must_be_instance_of Time
|
71
|
+
_(obj1.updated_at).must_be_instance_of Time
|
72
72
|
end
|
73
73
|
|
74
74
|
# Natural primary keys.
|
@@ -128,10 +128,10 @@ class SpecificSchemaTestSQLServer < ActiveRecord::TestCase
|
|
128
128
|
o = SSTestDatatypeMigration.create!
|
129
129
|
o.varchar_col = "O'Reilly"
|
130
130
|
o.save!
|
131
|
-
o.reload.varchar_col.must_equal "O'Reilly"
|
131
|
+
_(o.reload.varchar_col).must_equal "O'Reilly"
|
132
132
|
o.varchar_col = nil
|
133
133
|
o.save!
|
134
|
-
o.reload.varchar_col.must_be_nil
|
134
|
+
_(o.reload.varchar_col).must_be_nil
|
135
135
|
end
|
136
136
|
|
137
137
|
# With column names that have spaces
|
@@ -160,7 +160,7 @@ class SpecificSchemaTestSQLServer < ActiveRecord::TestCase
|
|
160
160
|
it 'returns a new id via connection newid_function' do
|
161
161
|
acceptable_uuid = ActiveRecord::ConnectionAdapters::SQLServer::Type::Uuid::ACCEPTABLE_UUID
|
162
162
|
db_uuid = ActiveRecord::Base.connection.newid_function
|
163
|
-
db_uuid.must_match(acceptable_uuid)
|
163
|
+
_(db_uuid).must_match(acceptable_uuid)
|
164
164
|
end
|
165
165
|
|
166
166
|
# with similar table definition in two schemas
|
@@ -34,22 +34,22 @@ class TransactionTestSQLServer < ActiveRecord::TestCase
|
|
34
34
|
it 'can use an isolation level and reverts back to starting isolation level' do
|
35
35
|
in_level = nil
|
36
36
|
begin_level = connection.user_options_isolation_level
|
37
|
-
begin_level.must_match %r{read committed}i
|
37
|
+
_(begin_level).must_match %r{read committed}i
|
38
38
|
Ship.transaction(isolation: :serializable) do
|
39
39
|
Ship.create! name: 'Black Pearl'
|
40
40
|
in_level = connection.user_options_isolation_level
|
41
41
|
end
|
42
42
|
after_level = connection.user_options_isolation_level
|
43
|
-
in_level.must_match %r{serializable}i
|
44
|
-
after_level.must_match %r{read committed}i
|
43
|
+
_(in_level).must_match %r{serializable}i
|
44
|
+
_(after_level).must_match %r{read committed}i
|
45
45
|
end
|
46
46
|
|
47
47
|
it 'can use an isolation level and reverts back to starting isolation level under exceptions' do
|
48
|
-
connection.user_options_isolation_level.must_match %r{read committed}i
|
49
|
-
lambda {
|
48
|
+
_(connection.user_options_isolation_level).must_match %r{read committed}i
|
49
|
+
_(lambda {
|
50
50
|
Ship.transaction(isolation: :serializable) { Ship.create! }
|
51
|
-
}.must_raise(ActiveRecord::RecordInvalid)
|
52
|
-
connection.user_options_isolation_level.must_match %r{read committed}i
|
51
|
+
}).must_raise(ActiveRecord::RecordInvalid)
|
52
|
+
_(connection.user_options_isolation_level).must_match %r{read committed}i
|
53
53
|
end
|
54
54
|
|
55
55
|
describe 'when READ_COMMITTED_SNAPSHOT is set' do
|
@@ -64,7 +64,7 @@ class TransactionTestSQLServer < ActiveRecord::TestCase
|
|
64
64
|
end
|
65
65
|
|
66
66
|
it 'should use READ COMMITTED as an isolation level' do
|
67
|
-
connection.user_options_isolation_level.must_match "read committed snapshot"
|
67
|
+
_(connection.user_options_isolation_level).must_match "read committed snapshot"
|
68
68
|
|
69
69
|
Ship.transaction(isolation: :serializable) do
|
70
70
|
Ship.create! name: 'Black Pearl'
|
@@ -73,7 +73,7 @@ class TransactionTestSQLServer < ActiveRecord::TestCase
|
|
73
73
|
# We're actually testing that the isolation level was correctly reset to
|
74
74
|
# "READ COMMITTED", and that no exception was raised (it's reported back
|
75
75
|
# by SQL Server as "read committed snapshot").
|
76
|
-
connection.user_options_isolation_level.must_match "read committed snapshot"
|
76
|
+
_(connection.user_options_isolation_level).must_match "read committed snapshot"
|
77
77
|
end
|
78
78
|
end
|
79
79
|
|
@@ -12,10 +12,10 @@ class SQLServerTriggerTest < ActiveRecord::TestCase
|
|
12
12
|
exclude_output_inserted_table_names['sst_table_with_trigger'] = true
|
13
13
|
assert SSTestTriggerHistory.all.empty?
|
14
14
|
obj = SSTestTrigger.create! event_name: 'test trigger'
|
15
|
-
['Fixnum', 'Integer'].must_include obj.id.class.name
|
16
|
-
obj.event_name.must_equal 'test trigger'
|
17
|
-
obj.id.must_be :present?
|
18
|
-
obj.id.to_s.must_equal SSTestTriggerHistory.first.id_source
|
15
|
+
_(['Fixnum', 'Integer']).must_include obj.id.class.name
|
16
|
+
_(obj.event_name).must_equal 'test trigger'
|
17
|
+
_(obj.id).must_be :present?
|
18
|
+
_(obj.id.to_s).must_equal SSTestTriggerHistory.first.id_source
|
19
19
|
end
|
20
20
|
|
21
21
|
it 'can insert into a table with output inserted - with a uniqueidentifier value' do
|
@@ -23,9 +23,9 @@ class SQLServerTriggerTest < ActiveRecord::TestCase
|
|
23
23
|
exclude_output_inserted_table_names['sst_table_with_uuid_trigger'] = 'uniqueidentifier'
|
24
24
|
assert SSTestTriggerHistory.all.empty?
|
25
25
|
obj = SSTestTriggerUuid.create! event_name: 'test uuid trigger'
|
26
|
-
obj.id.class.name.must_equal 'String'
|
27
|
-
obj.event_name.must_equal 'test uuid trigger'
|
28
|
-
obj.id.must_be :present?
|
29
|
-
obj.id.to_s.must_equal SSTestTriggerHistory.first.id_source
|
26
|
+
_(obj.id.class.name).must_equal 'String'
|
27
|
+
_(obj.event_name).must_equal 'test uuid trigger'
|
28
|
+
_(obj.id).must_be :present?
|
29
|
+
_(obj.id.to_s).must_equal SSTestTriggerHistory.first.id_source
|
30
30
|
end
|
31
31
|
end
|
@@ -3,15 +3,15 @@ require 'cases/helper_sqlserver'
|
|
3
3
|
class UtilsTestSQLServer < ActiveRecord::TestCase
|
4
4
|
|
5
5
|
it '.quote_string' do
|
6
|
-
SQLServer::Utils.quote_string("I'll store this in C:\\Users").must_equal "I''ll store this in C:\\Users"
|
6
|
+
_(SQLServer::Utils.quote_string("I'll store this in C:\\Users")).must_equal "I''ll store this in C:\\Users"
|
7
7
|
end
|
8
8
|
|
9
9
|
it '.unquote_string' do
|
10
|
-
SQLServer::Utils.unquote_string("I''ll store this in C:\\Users").must_equal "I'll store this in C:\\Users"
|
10
|
+
_(SQLServer::Utils.unquote_string("I''ll store this in C:\\Users")).must_equal "I'll store this in C:\\Users"
|
11
11
|
end
|
12
12
|
|
13
13
|
it '.quoted_raw' do
|
14
|
-
SQLServer::Utils.quoted_raw("some.Name").must_equal "[some.Name]"
|
14
|
+
_(SQLServer::Utils.quoted_raw("some.Name")).must_equal "[some.Name]"
|
15
15
|
end
|
16
16
|
|
17
17
|
describe '.extract_identifiers constructor and thus SQLServer::Utils::Name value object' do
|
@@ -47,8 +47,8 @@ class UtilsTestSQLServer < ActiveRecord::TestCase
|
|
47
47
|
it 'extracts and returns #object identifier unquoted by default or quoted as needed' do
|
48
48
|
valid_names.each do |n|
|
49
49
|
name = extract_identifiers(n)
|
50
|
-
name.object.must_equal 'object', "With #{n.inspect} for #object"
|
51
|
-
name.object_quoted.must_equal '[object]', "With #{n.inspect} for #object_quoted"
|
50
|
+
_(name.object).must_equal 'object', "With #{n.inspect} for #object"
|
51
|
+
_(name.object_quoted).must_equal '[object]', "With #{n.inspect} for #object_quoted"
|
52
52
|
end
|
53
53
|
end
|
54
54
|
|
@@ -58,64 +58,64 @@ class UtilsTestSQLServer < ActiveRecord::TestCase
|
|
58
58
|
present, blank = send(:"#{part}_names")
|
59
59
|
present.each do |n|
|
60
60
|
name = extract_identifiers(n)
|
61
|
-
name.send(:"#{part}").must_equal "#{part}", "With #{n.inspect} for ##{part} method"
|
62
|
-
name.send(:"#{part}_quoted").must_equal "[#{part}]", "With #{n.inspect} for ##{part}_quoted method"
|
61
|
+
_(name.send(:"#{part}")).must_equal "#{part}", "With #{n.inspect} for ##{part} method"
|
62
|
+
_(name.send(:"#{part}_quoted")).must_equal "[#{part}]", "With #{n.inspect} for ##{part}_quoted method"
|
63
63
|
end
|
64
64
|
blank.each do |n|
|
65
65
|
name = extract_identifiers(n)
|
66
|
-
name.send(:"#{part}").must_be_nil "With #{n.inspect} for ##{part} method"
|
67
|
-
name.send(:"#{part}_quoted").must_be_nil "With #{n.inspect} for ##{part}_quoted method"
|
66
|
+
_(name.send(:"#{part}")).must_be_nil "With #{n.inspect} for ##{part} method"
|
67
|
+
_(name.send(:"#{part}_quoted")).must_be_nil "With #{n.inspect} for ##{part}_quoted method"
|
68
68
|
end
|
69
69
|
end
|
70
70
|
|
71
71
|
end
|
72
72
|
|
73
73
|
it 'does not blow up on nil or blank string name' do
|
74
|
-
extract_identifiers(nil).object.must_be_nil
|
75
|
-
extract_identifiers(' ').object.must_be_nil
|
74
|
+
_(extract_identifiers(nil).object).must_be_nil
|
75
|
+
_(extract_identifiers(' ').object).must_be_nil
|
76
76
|
end
|
77
77
|
|
78
78
|
it 'has a #quoted that returns a fully quoted name with all identifiers as orginially passed in' do
|
79
|
-
extract_identifiers('object').quoted.must_equal '[object]'
|
80
|
-
extract_identifiers('server.database..object').quoted.must_equal '[server].[database]..[object]'
|
81
|
-
extract_identifiers('[server]...[object]').quoted.must_equal '[server]...[object]'
|
79
|
+
_(extract_identifiers('object').quoted).must_equal '[object]'
|
80
|
+
_(extract_identifiers('server.database..object').quoted).must_equal '[server].[database]..[object]'
|
81
|
+
_(extract_identifiers('[server]...[object]').quoted).must_equal '[server]...[object]'
|
82
82
|
end
|
83
83
|
|
84
84
|
it 'can take a symbol argument' do
|
85
|
-
extract_identifiers(:object).object.must_equal 'object'
|
85
|
+
_(extract_identifiers(:object).object).must_equal 'object'
|
86
86
|
end
|
87
87
|
|
88
88
|
it 'allows identifiers with periods to work' do
|
89
|
-
extract_identifiers('[obj.name]').quoted.must_equal '[obj.name]'
|
90
|
-
extract_identifiers('[obj.name].[foo]').quoted.must_equal '[obj.name].[foo]'
|
89
|
+
_(extract_identifiers('[obj.name]').quoted).must_equal '[obj.name]'
|
90
|
+
_(extract_identifiers('[obj.name].[foo]').quoted).must_equal '[obj.name].[foo]'
|
91
91
|
end
|
92
92
|
|
93
93
|
it 'should indicate if a name is fully qualitified' do
|
94
|
-
extract_identifiers('object').fully_qualified
|
95
|
-
extract_identifiers('schema.object').fully_qualified
|
96
|
-
extract_identifiers('database.schema.object').fully_qualified
|
97
|
-
extract_identifiers('database.object').fully_qualified
|
98
|
-
extract_identifiers('server...object').fully_qualified
|
99
|
-
extract_identifiers('server.database..object').fully_qualified
|
100
|
-
extract_identifiers('server.database.schema.object').fully_qualified
|
101
|
-
extract_identifiers('server.database.schema.').fully_qualified
|
102
|
-
extract_identifiers('[obj.name]').fully_qualified
|
103
|
-
extract_identifiers('[schema].[obj.name]').fully_qualified
|
104
|
-
extract_identifiers('[database].[schema].[obj.name]').fully_qualified
|
105
|
-
extract_identifiers('[database].[obj.name]').fully_qualified
|
106
|
-
extract_identifiers('[server.name]...[obj.name]').fully_qualified
|
107
|
-
extract_identifiers('[server.name].[database]..[obj.name]').fully_qualified
|
108
|
-
extract_identifiers('[server.name].[database].[schema].[obj.name]').fully_qualified
|
109
|
-
extract_identifiers('[server.name].[database].[schema].').fully_qualified
|
94
|
+
_(extract_identifiers('object').fully_qualified?).must_equal false
|
95
|
+
_(extract_identifiers('schema.object').fully_qualified?).must_equal false
|
96
|
+
_(extract_identifiers('database.schema.object').fully_qualified?).must_equal false
|
97
|
+
_(extract_identifiers('database.object').fully_qualified?).must_equal false
|
98
|
+
_(extract_identifiers('server...object').fully_qualified?).must_equal false
|
99
|
+
_(extract_identifiers('server.database..object').fully_qualified?).must_equal false
|
100
|
+
_(extract_identifiers('server.database.schema.object').fully_qualified?).must_equal true
|
101
|
+
_(extract_identifiers('server.database.schema.').fully_qualified?).must_equal true
|
102
|
+
_(extract_identifiers('[obj.name]').fully_qualified?).must_equal false
|
103
|
+
_(extract_identifiers('[schema].[obj.name]').fully_qualified?).must_equal false
|
104
|
+
_(extract_identifiers('[database].[schema].[obj.name]').fully_qualified?).must_equal false
|
105
|
+
_(extract_identifiers('[database].[obj.name]').fully_qualified?).must_equal false
|
106
|
+
_(extract_identifiers('[server.name]...[obj.name]').fully_qualified?).must_equal false
|
107
|
+
_(extract_identifiers('[server.name].[database]..[obj.name]').fully_qualified?).must_equal false
|
108
|
+
_(extract_identifiers('[server.name].[database].[schema].[obj.name]').fully_qualified?).must_equal true
|
109
|
+
_(extract_identifiers('[server.name].[database].[schema].').fully_qualified?).must_equal true
|
110
110
|
end
|
111
111
|
|
112
112
|
it 'can return fully qualified quoted table name' do
|
113
113
|
name = extract_identifiers('[my.server].db.schema.')
|
114
|
-
name.fully_qualified_database_quoted.must_equal '[my.server].[db]'
|
114
|
+
_(name.fully_qualified_database_quoted).must_equal '[my.server].[db]'
|
115
115
|
name = extract_identifiers('[server.name].[database].[schema].[object]')
|
116
|
-
name.fully_qualified_database_quoted.must_equal '[server.name].[database]'
|
116
|
+
_(name.fully_qualified_database_quoted).must_equal '[server.name].[database]'
|
117
117
|
name = extract_identifiers('server.database.schema.object')
|
118
|
-
name.fully_qualified_database_quoted.must_equal '[server].[database]'
|
118
|
+
_(name.fully_qualified_database_quoted).must_equal '[server].[database]'
|
119
119
|
end
|
120
120
|
|
121
121
|
end
|
@@ -6,26 +6,26 @@ class SQLServerUuidTest < ActiveRecord::TestCase
|
|
6
6
|
let(:acceptable_uuid) { ActiveRecord::ConnectionAdapters::SQLServer::Type::Uuid::ACCEPTABLE_UUID }
|
7
7
|
|
8
8
|
it 'has a uuid primary key' do
|
9
|
-
SSTestUuid.columns_hash['id'].type.must_equal :uuid
|
9
|
+
_(SSTestUuid.columns_hash['id'].type).must_equal :uuid
|
10
10
|
assert SSTestUuid.primary_key
|
11
11
|
end
|
12
12
|
|
13
13
|
it 'can create with a new pk' do
|
14
14
|
skip 'We do not support uuid autogenerated primary keys at this time' if defined? JRUBY_VERSION
|
15
15
|
obj = SSTestUuid.create!
|
16
|
-
obj.id.must_be :present?
|
17
|
-
obj.id.must_match acceptable_uuid
|
16
|
+
_(obj.id).must_be :present?
|
17
|
+
_(obj.id).must_match acceptable_uuid
|
18
18
|
end
|
19
19
|
|
20
20
|
it 'can create other uuid column on reload' do
|
21
21
|
skip 'We do not support uuid autogenerated primary keys at this time' if defined? JRUBY_VERSION
|
22
22
|
obj = SSTestUuid.create!
|
23
23
|
obj.reload
|
24
|
-
obj.other_uuid.must_match acceptable_uuid
|
24
|
+
_(obj.other_uuid).must_match acceptable_uuid
|
25
25
|
end
|
26
26
|
|
27
27
|
it 'can find uuid pk via connection' do
|
28
|
-
connection.primary_key(SSTestUuid.table_name).must_equal 'id'
|
28
|
+
_(connection.primary_key(SSTestUuid.table_name)).must_equal 'id'
|
29
29
|
end
|
30
30
|
|
31
31
|
it 'changing column default' do
|
@@ -33,17 +33,17 @@ class SQLServerUuidTest < ActiveRecord::TestCase
|
|
33
33
|
connection.add_column table_name, :thingy, :uuid, null: false, default: "NEWSEQUENTIALID()"
|
34
34
|
SSTestUuid.reset_column_information
|
35
35
|
column = SSTestUuid.columns_hash['thingy']
|
36
|
-
column.default_function.must_equal "newsequentialid()"
|
36
|
+
_(column.default_function).must_equal "newsequentialid()"
|
37
37
|
# Now to a different function.
|
38
38
|
connection.change_column table_name, :thingy, :uuid, null: false, default: "NEWID()"
|
39
39
|
SSTestUuid.reset_column_information
|
40
40
|
column = SSTestUuid.columns_hash['thingy']
|
41
|
-
column.default_function.must_equal "newid()"
|
41
|
+
_(column.default_function).must_equal "newid()"
|
42
42
|
end
|
43
43
|
|
44
44
|
it 'can insert even when use_output_inserted to false ' do
|
45
45
|
obj = with_use_output_inserted_disabled { SSTestUuid.create!(name: "😢") }
|
46
|
-
obj.id.must_be :nil?
|
46
|
+
_(obj.id).must_be :nil?
|
47
47
|
end
|
48
48
|
|
49
49
|
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
class CreateClientsAndChangeColumnNull < ActiveRecord::Migration[5.2]
|
2
|
+
def up
|
3
|
+
create_table :clients do |t|
|
4
|
+
t.string :name
|
5
|
+
t.string :code
|
6
|
+
t.decimal :value
|
7
|
+
|
8
|
+
t.timestamps
|
9
|
+
end
|
10
|
+
|
11
|
+
change_column :clients, :name, :string, limit: 15
|
12
|
+
change_column :clients, :code, :string, default: 'n/a'
|
13
|
+
change_column :clients, :value, :decimal, precision: 32, scale: 8
|
14
|
+
|
15
|
+
change_column_null :clients, :name, false
|
16
|
+
change_column_null :clients, :code, false
|
17
|
+
change_column_null :clients, :value, false
|
18
|
+
end
|
19
|
+
|
20
|
+
def down
|
21
|
+
drop_table :clients
|
22
|
+
end
|
23
|
+
end
|
@@ -35,6 +35,7 @@ CREATE TABLE [sst_datatypes] (
|
|
35
35
|
[smalldatetime] [smalldatetime] NULL DEFAULT '1901-01-01T15:45:00.000Z',
|
36
36
|
[time_7] [time](7) NULL DEFAULT '04:20:00.2883215',
|
37
37
|
[time_2] [time](2) NULL,
|
38
|
+
[time_default] [time] NULL DEFAULT '15:03:42.0621978',
|
38
39
|
-- Character Strings
|
39
40
|
[char_10] [char](10) NULL DEFAULT '1234567890',
|
40
41
|
[varchar_50] [varchar](50) NULL DEFAULT 'test varchar_50',
|
@@ -144,12 +144,20 @@ ActiveRecord::Schema.define do
|
|
144
144
|
|
145
145
|
# Constraints
|
146
146
|
|
147
|
-
create_table(:sst_has_fks, force: true)
|
147
|
+
create_table(:sst_has_fks, force: true) do |t|
|
148
|
+
t.column(:fk_id, :bigint, null: false)
|
149
|
+
t.column(:fk_id2, :bigint)
|
150
|
+
end
|
151
|
+
|
148
152
|
create_table(:sst_has_pks, force: true) { }
|
149
153
|
execute <<-ADDFKSQL
|
150
154
|
ALTER TABLE sst_has_fks
|
151
155
|
ADD CONSTRAINT FK__sst_has_fks_id
|
152
156
|
FOREIGN KEY ([fk_id])
|
157
|
+
REFERENCES [sst_has_pks] ([id]),
|
158
|
+
|
159
|
+
CONSTRAINT FK__sst_has_fks_id2
|
160
|
+
FOREIGN KEY ([fk_id2])
|
153
161
|
REFERENCES [sst_has_pks] ([id])
|
154
162
|
ADDFKSQL
|
155
163
|
|