activerecord-sqlserver-adapter 5.2.1 → 6.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/.editorconfig +9 -0
- data/.github/issue_template.md +23 -0
- data/.gitignore +1 -0
- data/.rubocop.yml +29 -0
- data/.travis.yml +6 -8
- data/CHANGELOG.md +38 -24
- data/{Dockerfile → Dockerfile.ci} +1 -1
- data/Gemfile +48 -41
- data/Guardfile +9 -8
- data/README.md +9 -30
- data/RUNNING_UNIT_TESTS.md +3 -0
- data/Rakefile +14 -16
- data/VERSION +1 -1
- data/activerecord-sqlserver-adapter.gemspec +25 -14
- data/appveyor.yml +24 -17
- data/docker-compose.ci.yml +7 -5
- data/guides/RELEASING.md +11 -0
- data/lib/active_record/connection_adapters/sqlserver/core_ext/active_record.rb +2 -4
- data/lib/active_record/connection_adapters/sqlserver/core_ext/attribute_methods.rb +3 -4
- data/lib/active_record/connection_adapters/sqlserver/core_ext/calculations.rb +5 -4
- data/lib/active_record/connection_adapters/sqlserver/core_ext/explain.rb +3 -3
- data/lib/active_record/connection_adapters/sqlserver/core_ext/explain_subscriber.rb +2 -0
- data/lib/active_record/connection_adapters/sqlserver/core_ext/finder_methods.rb +8 -7
- data/lib/active_record/connection_adapters/sqlserver/core_ext/preloader.rb +36 -0
- data/lib/active_record/connection_adapters/sqlserver/core_ext/query_methods.rb +6 -4
- data/lib/active_record/connection_adapters/sqlserver/database_limits.rb +9 -0
- data/lib/active_record/connection_adapters/sqlserver/database_statements.rb +88 -44
- data/lib/active_record/connection_adapters/sqlserver/database_tasks.rb +9 -12
- data/lib/active_record/connection_adapters/sqlserver/errors.rb +2 -3
- data/lib/active_record/connection_adapters/sqlserver/quoting.rb +46 -8
- data/lib/active_record/connection_adapters/sqlserver/schema_creation.rb +16 -5
- data/lib/active_record/connection_adapters/sqlserver/schema_dumper.rb +9 -7
- data/lib/active_record/connection_adapters/sqlserver/schema_statements.rb +190 -164
- data/lib/active_record/connection_adapters/sqlserver/showplan/printer_table.rb +4 -2
- data/lib/active_record/connection_adapters/sqlserver/showplan/printer_xml.rb +3 -1
- data/lib/active_record/connection_adapters/sqlserver/showplan.rb +8 -8
- data/lib/active_record/connection_adapters/sqlserver/sql_type_metadata.rb +2 -2
- data/lib/active_record/connection_adapters/sqlserver/table_definition.rb +43 -44
- data/lib/active_record/connection_adapters/sqlserver/transaction.rb +7 -9
- data/lib/active_record/connection_adapters/sqlserver/type/big_integer.rb +3 -3
- data/lib/active_record/connection_adapters/sqlserver/type/binary.rb +5 -4
- data/lib/active_record/connection_adapters/sqlserver/type/boolean.rb +3 -3
- data/lib/active_record/connection_adapters/sqlserver/type/char.rb +7 -4
- data/lib/active_record/connection_adapters/sqlserver/type/data.rb +2 -2
- data/lib/active_record/connection_adapters/sqlserver/type/date.rb +4 -3
- data/lib/active_record/connection_adapters/sqlserver/type/datetime.rb +8 -8
- data/lib/active_record/connection_adapters/sqlserver/type/datetime2.rb +2 -2
- data/lib/active_record/connection_adapters/sqlserver/type/datetimeoffset.rb +2 -2
- data/lib/active_record/connection_adapters/sqlserver/type/decimal.rb +5 -4
- data/lib/active_record/connection_adapters/sqlserver/type/float.rb +3 -3
- data/lib/active_record/connection_adapters/sqlserver/type/integer.rb +3 -3
- data/lib/active_record/connection_adapters/sqlserver/type/json.rb +2 -1
- data/lib/active_record/connection_adapters/sqlserver/type/money.rb +4 -4
- data/lib/active_record/connection_adapters/sqlserver/type/real.rb +3 -3
- data/lib/active_record/connection_adapters/sqlserver/type/small_integer.rb +3 -3
- data/lib/active_record/connection_adapters/sqlserver/type/small_money.rb +4 -4
- data/lib/active_record/connection_adapters/sqlserver/type/smalldatetime.rb +3 -3
- data/lib/active_record/connection_adapters/sqlserver/type/string.rb +2 -2
- data/lib/active_record/connection_adapters/sqlserver/type/text.rb +3 -3
- data/lib/active_record/connection_adapters/sqlserver/type/time.rb +6 -6
- data/lib/active_record/connection_adapters/sqlserver/type/time_value_fractional.rb +8 -9
- data/lib/active_record/connection_adapters/sqlserver/type/timestamp.rb +3 -3
- data/lib/active_record/connection_adapters/sqlserver/type/tiny_integer.rb +3 -3
- data/lib/active_record/connection_adapters/sqlserver/type/unicode_char.rb +5 -4
- data/lib/active_record/connection_adapters/sqlserver/type/unicode_string.rb +2 -2
- data/lib/active_record/connection_adapters/sqlserver/type/unicode_text.rb +3 -3
- data/lib/active_record/connection_adapters/sqlserver/type/unicode_varchar.rb +6 -5
- data/lib/active_record/connection_adapters/sqlserver/type/unicode_varchar_max.rb +4 -4
- data/lib/active_record/connection_adapters/sqlserver/type/uuid.rb +4 -3
- data/lib/active_record/connection_adapters/sqlserver/type/varbinary.rb +6 -5
- data/lib/active_record/connection_adapters/sqlserver/type/varbinary_max.rb +4 -4
- data/lib/active_record/connection_adapters/sqlserver/type/varchar.rb +6 -5
- data/lib/active_record/connection_adapters/sqlserver/type/varchar_max.rb +4 -4
- data/lib/active_record/connection_adapters/sqlserver/type.rb +37 -35
- data/lib/active_record/connection_adapters/sqlserver/utils.rb +10 -11
- data/lib/active_record/connection_adapters/sqlserver/version.rb +2 -2
- data/lib/active_record/connection_adapters/sqlserver_adapter.rb +128 -92
- data/lib/active_record/connection_adapters/sqlserver_column.rb +9 -5
- data/lib/active_record/sqlserver_base.rb +9 -1
- data/lib/active_record/tasks/sqlserver_database_tasks.rb +28 -32
- data/lib/activerecord-sqlserver-adapter.rb +3 -1
- data/lib/arel/visitors/sqlserver.rb +58 -24
- data/lib/arel_sqlserver.rb +4 -2
- data/test/appveyor/dbsetup.ps1 +4 -4
- data/test/cases/adapter_test_sqlserver.rb +214 -171
- data/test/cases/change_column_null_test_sqlserver.rb +14 -12
- data/test/cases/coerced_tests.rb +631 -356
- data/test/cases/column_test_sqlserver.rb +283 -284
- data/test/cases/connection_test_sqlserver.rb +17 -20
- data/test/cases/execute_procedure_test_sqlserver.rb +20 -20
- data/test/cases/fetch_test_sqlserver.rb +16 -22
- data/test/cases/fully_qualified_identifier_test_sqlserver.rb +15 -19
- data/test/cases/helper_sqlserver.rb +15 -15
- data/test/cases/in_clause_test_sqlserver.rb +36 -0
- data/test/cases/index_test_sqlserver.rb +15 -15
- data/test/cases/json_test_sqlserver.rb +25 -25
- data/test/cases/migration_test_sqlserver.rb +25 -29
- data/test/cases/order_test_sqlserver.rb +53 -54
- data/test/cases/pessimistic_locking_test_sqlserver.rb +27 -33
- data/test/cases/rake_test_sqlserver.rb +33 -45
- data/test/cases/schema_dumper_test_sqlserver.rb +107 -109
- data/test/cases/schema_test_sqlserver.rb +20 -26
- data/test/cases/scratchpad_test_sqlserver.rb +4 -4
- data/test/cases/showplan_test_sqlserver.rb +28 -35
- data/test/cases/specific_schema_test_sqlserver.rb +68 -65
- data/test/cases/transaction_test_sqlserver.rb +18 -20
- data/test/cases/trigger_test_sqlserver.rb +14 -13
- data/test/cases/utils_test_sqlserver.rb +70 -70
- data/test/cases/uuid_test_sqlserver.rb +13 -14
- data/test/debug.rb +8 -6
- data/test/migrations/create_clients_and_change_column_null.rb +3 -1
- data/test/migrations/transaction_table/1_table_will_never_be_created.rb +4 -4
- data/test/models/sqlserver/booking.rb +3 -1
- data/test/models/sqlserver/customers_view.rb +3 -1
- data/test/models/sqlserver/datatype.rb +2 -0
- data/test/models/sqlserver/datatype_migration.rb +2 -0
- data/test/models/sqlserver/dollar_table_name.rb +3 -1
- data/test/models/sqlserver/edge_schema.rb +3 -3
- data/test/models/sqlserver/fk_has_fk.rb +3 -1
- data/test/models/sqlserver/fk_has_pk.rb +3 -1
- data/test/models/sqlserver/natural_pk_data.rb +4 -2
- data/test/models/sqlserver/natural_pk_int_data.rb +3 -1
- data/test/models/sqlserver/no_pk_data.rb +3 -1
- data/test/models/sqlserver/object_default.rb +3 -1
- data/test/models/sqlserver/quoted_table.rb +4 -2
- data/test/models/sqlserver/quoted_view_1.rb +3 -1
- data/test/models/sqlserver/quoted_view_2.rb +3 -1
- data/test/models/sqlserver/sst_memory.rb +3 -1
- data/test/models/sqlserver/string_default.rb +3 -1
- data/test/models/sqlserver/string_defaults_big_view.rb +3 -1
- data/test/models/sqlserver/string_defaults_view.rb +3 -1
- data/test/models/sqlserver/tinyint_pk.rb +3 -1
- data/test/models/sqlserver/trigger.rb +4 -2
- data/test/models/sqlserver/trigger_history.rb +3 -1
- data/test/models/sqlserver/upper.rb +3 -1
- data/test/models/sqlserver/uppered.rb +3 -1
- data/test/models/sqlserver/uuid.rb +3 -1
- data/test/schema/sqlserver_specific_schema.rb +22 -22
- data/test/support/coerceable_test_sqlserver.rb +15 -9
- data/test/support/connection_reflection.rb +3 -2
- data/test/support/core_ext/query_cache.rb +4 -1
- data/test/support/load_schema_sqlserver.rb +5 -5
- data/test/support/minitest_sqlserver.rb +3 -1
- data/test/support/paths_sqlserver.rb +11 -11
- data/test/support/rake_helpers.rb +13 -10
- data/test/support/sql_counter_sqlserver.rb +3 -4
- data/test/support/test_in_memory_oltp.rb +9 -7
- metadata +17 -7
|
@@ -1,19 +1,20 @@
|
|
|
1
|
-
|
|
2
|
-
require 'models/topic'
|
|
3
|
-
require 'models/task'
|
|
4
|
-
require 'models/post'
|
|
5
|
-
require 'models/subscriber'
|
|
6
|
-
require 'models/minimalistic'
|
|
1
|
+
# frozen_string_literal: true
|
|
7
2
|
|
|
8
|
-
|
|
3
|
+
require "cases/helper_sqlserver"
|
|
4
|
+
require "models/topic"
|
|
5
|
+
require "models/task"
|
|
6
|
+
require "models/post"
|
|
7
|
+
require "models/subscriber"
|
|
8
|
+
require "models/minimalistic"
|
|
9
9
|
|
|
10
|
+
class AdapterTestSQLServer < ActiveRecord::TestCase
|
|
10
11
|
fixtures :tasks
|
|
11
12
|
|
|
12
13
|
let(:basic_insert_sql) { "INSERT INTO [funny_jokes] ([name]) VALUES('Knock knock')" }
|
|
13
14
|
let(:basic_update_sql) { "UPDATE [customers] SET [address_street] = NULL WHERE [id] = 2" }
|
|
14
15
|
let(:basic_select_sql) { "SELECT * FROM [customers] WHERE ([customers].[id] = 1)" }
|
|
15
16
|
|
|
16
|
-
it
|
|
17
|
+
it "has basic and non-sensitive information in the adapters inspect method" do
|
|
17
18
|
string = connection.inspect
|
|
18
19
|
_(string).must_match %r{ActiveRecord::ConnectionAdapters::SQLServerAdapter}
|
|
19
20
|
_(string).must_match %r{version\: \d.\d}
|
|
@@ -25,48 +26,66 @@ class AdapterTestSQLServer < ActiveRecord::TestCase
|
|
|
25
26
|
_(string).wont_match %r{port}
|
|
26
27
|
end
|
|
27
28
|
|
|
28
|
-
it
|
|
29
|
+
it "has a 128 max #table_alias_length" do
|
|
29
30
|
assert connection.table_alias_length <= 128
|
|
30
31
|
end
|
|
31
32
|
|
|
32
|
-
it
|
|
33
|
+
it "raises invalid statement error for bad SQL" do
|
|
33
34
|
assert_raise(ActiveRecord::StatementInvalid) { Topic.connection.update("UPDATE XXX") }
|
|
34
35
|
end
|
|
35
36
|
|
|
36
|
-
it
|
|
37
|
-
assert_equal
|
|
37
|
+
it "is has our adapter_name" do
|
|
38
|
+
assert_equal "SQLServer", connection.adapter_name
|
|
38
39
|
end
|
|
39
40
|
|
|
40
|
-
it
|
|
41
|
+
it "support DDL in transactions" do
|
|
41
42
|
assert connection.supports_ddl_transactions?
|
|
42
43
|
end
|
|
43
44
|
|
|
44
|
-
it
|
|
45
|
+
it "allow owner table name prefixs like dbo to still allow table exists to return true" do
|
|
45
46
|
begin
|
|
46
|
-
assert_equal
|
|
47
|
+
assert_equal "topics", Topic.table_name
|
|
47
48
|
assert Topic.table_exists?
|
|
48
|
-
Topic.table_name =
|
|
49
|
-
assert Topic.table_exists?,
|
|
49
|
+
Topic.table_name = "dbo.topics"
|
|
50
|
+
assert Topic.table_exists?, "Tasks table name of dbo.topics should return true for exists."
|
|
50
51
|
ensure
|
|
51
|
-
Topic.table_name =
|
|
52
|
+
Topic.table_name = "topics"
|
|
52
53
|
end
|
|
53
54
|
end
|
|
54
55
|
|
|
55
|
-
it
|
|
56
|
-
assert connection.send(:insert_sql?,
|
|
56
|
+
it "return true to insert sql query for inserts only" do
|
|
57
|
+
assert connection.send(:insert_sql?, "INSERT...")
|
|
57
58
|
assert connection.send(:insert_sql?, "EXEC sp_executesql N'INSERT INTO [fk_test_has_fks] ([fk_id]) VALUES (@0); SELECT CAST(SCOPE_IDENTITY() AS bigint) AS Ident', N'@0 int', @0 = 0")
|
|
58
|
-
assert !connection.send(:insert_sql?,
|
|
59
|
-
assert !connection.send(:insert_sql?,
|
|
59
|
+
assert !connection.send(:insert_sql?, "UPDATE...")
|
|
60
|
+
assert !connection.send(:insert_sql?, "SELECT...")
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
it "return unquoted table name object from basic INSERT UPDATE and SELECT statements" do
|
|
64
|
+
assert_equal "funny_jokes", connection.send(:get_table_name, basic_insert_sql)
|
|
65
|
+
assert_equal "customers", connection.send(:get_table_name, basic_update_sql)
|
|
66
|
+
assert_equal "customers", connection.send(:get_table_name, basic_select_sql)
|
|
60
67
|
end
|
|
61
68
|
|
|
62
|
-
it
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
69
|
+
it "test bad connection" do
|
|
70
|
+
assert_raise ActiveRecord::NoDatabaseError do
|
|
71
|
+
config = ActiveRecord::Base.configurations["arunit"].merge(database: "inexistent_activerecord_unittest")
|
|
72
|
+
ActiveRecord::Base.sqlserver_connection config
|
|
73
|
+
end
|
|
66
74
|
end
|
|
67
75
|
|
|
68
|
-
|
|
76
|
+
it "test database exists returns false if database does not exist" do
|
|
77
|
+
config = ActiveRecord::Base.configurations["arunit"].merge(database: "inexistent_activerecord_unittest")
|
|
78
|
+
assert_not ActiveRecord::ConnectionAdapters::SQLServerAdapter.database_exists?(config),
|
|
79
|
+
"expected database to not exist"
|
|
80
|
+
end
|
|
69
81
|
|
|
82
|
+
it "test database exists returns true when the database exists" do
|
|
83
|
+
config = ActiveRecord::Base.configurations["arunit"]
|
|
84
|
+
assert ActiveRecord::ConnectionAdapters::SQLServerAdapter.database_exists?(config),
|
|
85
|
+
"expected database #{config[:database]} to exist"
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
describe "with different language" do
|
|
70
89
|
before do
|
|
71
90
|
@default_language = connection.user_options_language
|
|
72
91
|
end
|
|
@@ -76,18 +95,18 @@ class AdapterTestSQLServer < ActiveRecord::TestCase
|
|
|
76
95
|
connection.send :initialize_dateformatter
|
|
77
96
|
end
|
|
78
97
|
|
|
79
|
-
it
|
|
98
|
+
it "memos users dateformat" do
|
|
80
99
|
connection.execute("SET LANGUAGE us_english") rescue nil
|
|
81
100
|
dateformat = connection.instance_variable_get(:@database_dateformat)
|
|
82
|
-
assert_equal
|
|
101
|
+
assert_equal "mdy", dateformat
|
|
83
102
|
end
|
|
84
103
|
|
|
85
|
-
it
|
|
104
|
+
it "has a dateformatter" do
|
|
86
105
|
assert Date::DATE_FORMATS[:_sqlserver_dateformat]
|
|
87
106
|
assert Time::DATE_FORMATS[:_sqlserver_dateformat]
|
|
88
107
|
end
|
|
89
108
|
|
|
90
|
-
it
|
|
109
|
+
it "does a datetime insertion when language is german" do
|
|
91
110
|
connection.execute("SET LANGUAGE deutsch")
|
|
92
111
|
connection.send :initialize_dateformatter
|
|
93
112
|
assert_nothing_raised do
|
|
@@ -96,40 +115,36 @@ class AdapterTestSQLServer < ActiveRecord::TestCase
|
|
|
96
115
|
Task.create! starting: starting, ending: ending
|
|
97
116
|
end
|
|
98
117
|
end
|
|
99
|
-
|
|
100
118
|
end
|
|
101
119
|
|
|
102
|
-
describe
|
|
103
|
-
|
|
120
|
+
describe "testing #lowercase_schema_reflection" do
|
|
104
121
|
before do
|
|
105
122
|
SSTestUpper.delete_all
|
|
106
|
-
SSTestUpper.create COLUMN1:
|
|
107
|
-
SSTestUpper.create COLUMN1:
|
|
123
|
+
SSTestUpper.create COLUMN1: "Got a minute?", COLUMN2: 419
|
|
124
|
+
SSTestUpper.create COLUMN1: "Favorite number?", COLUMN2: 69
|
|
108
125
|
end
|
|
109
126
|
|
|
110
127
|
after do
|
|
111
128
|
connection.lowercase_schema_reflection = false
|
|
112
129
|
end
|
|
113
130
|
|
|
114
|
-
it
|
|
115
|
-
assert SSTestUpper.columns_hash[
|
|
116
|
-
assert_equal
|
|
117
|
-
assert_equal
|
|
118
|
-
assert SSTestUpper.columns_hash[
|
|
131
|
+
it "not lowercase schema reflection by default" do
|
|
132
|
+
assert SSTestUpper.columns_hash["COLUMN1"]
|
|
133
|
+
assert_equal "Got a minute?", SSTestUpper.first.COLUMN1
|
|
134
|
+
assert_equal "Favorite number?", SSTestUpper.last.COLUMN1
|
|
135
|
+
assert SSTestUpper.columns_hash["COLUMN2"]
|
|
119
136
|
end
|
|
120
137
|
|
|
121
|
-
it
|
|
138
|
+
it "lowercase schema reflection when set" do
|
|
122
139
|
connection.lowercase_schema_reflection = true
|
|
123
|
-
assert SSTestUppered.columns_hash[
|
|
124
|
-
assert_equal
|
|
125
|
-
assert_equal
|
|
126
|
-
assert SSTestUppered.columns_hash[
|
|
140
|
+
assert SSTestUppered.columns_hash["column1"]
|
|
141
|
+
assert_equal "Got a minute?", SSTestUppered.first.column1
|
|
142
|
+
assert_equal "Favorite number?", SSTestUppered.last.column1
|
|
143
|
+
assert SSTestUppered.columns_hash["column2"]
|
|
127
144
|
end
|
|
128
|
-
|
|
129
145
|
end
|
|
130
146
|
|
|
131
|
-
describe
|
|
132
|
-
|
|
147
|
+
describe "identity inserts" do
|
|
133
148
|
before do
|
|
134
149
|
@identity_insert_sql = "INSERT INTO [funny_jokes] ([id],[name]) VALUES(420,'Knock knock')"
|
|
135
150
|
@identity_insert_sql_unquoted = "INSERT INTO funny_jokes (id, name) VALUES(420, 'Knock knock')"
|
|
@@ -139,62 +154,60 @@ class AdapterTestSQLServer < ActiveRecord::TestCase
|
|
|
139
154
|
@identity_insert_sql_unordered_sp = "EXEC sp_executesql N'INSERT INTO [funny_jokes] ([name],[id]) VALUES (@0, @1)', N'@0 nvarchar(255), @1 int', @0 = N'Knock knock', @1 = 420"
|
|
140
155
|
end
|
|
141
156
|
|
|
142
|
-
it
|
|
143
|
-
assert_equal
|
|
144
|
-
assert_equal
|
|
145
|
-
assert_equal
|
|
146
|
-
assert_equal
|
|
147
|
-
assert_equal
|
|
148
|
-
assert_equal
|
|
157
|
+
it "return quoted table_name to #query_requires_identity_insert? when INSERT sql contains id column" do
|
|
158
|
+
assert_equal "funny_jokes", connection.send(:query_requires_identity_insert?, @identity_insert_sql)
|
|
159
|
+
assert_equal "funny_jokes", connection.send(:query_requires_identity_insert?, @identity_insert_sql_unquoted)
|
|
160
|
+
assert_equal "funny_jokes", connection.send(:query_requires_identity_insert?, @identity_insert_sql_unordered)
|
|
161
|
+
assert_equal "funny_jokes", connection.send(:query_requires_identity_insert?, @identity_insert_sql_sp)
|
|
162
|
+
assert_equal "funny_jokes", connection.send(:query_requires_identity_insert?, @identity_insert_sql_unquoted_sp)
|
|
163
|
+
assert_equal "funny_jokes", connection.send(:query_requires_identity_insert?, @identity_insert_sql_unordered_sp)
|
|
149
164
|
end
|
|
150
165
|
|
|
151
|
-
it
|
|
166
|
+
it "return false to #query_requires_identity_insert? for normal SQL" do
|
|
152
167
|
[basic_insert_sql, basic_update_sql, basic_select_sql].each do |sql|
|
|
153
|
-
assert !connection.send(:query_requires_identity_insert?,sql), "SQL was #{sql}"
|
|
168
|
+
assert !connection.send(:query_requires_identity_insert?, sql), "SQL was #{sql}"
|
|
154
169
|
end
|
|
155
170
|
end
|
|
156
171
|
|
|
157
|
-
it
|
|
158
|
-
task_id_column = Task.columns_hash[
|
|
172
|
+
it "find identity column using #identity_columns" do
|
|
173
|
+
task_id_column = Task.columns_hash["id"]
|
|
159
174
|
assert_equal task_id_column.name, connection.send(:identity_columns, Task.table_name).first.name
|
|
160
175
|
assert_equal task_id_column.sql_type, connection.send(:identity_columns, Task.table_name).first.sql_type
|
|
161
176
|
end
|
|
162
177
|
|
|
163
|
-
it
|
|
178
|
+
it "return an empty array when calling #identity_columns for a table_name with no identity" do
|
|
164
179
|
_(connection.send(:identity_columns, Subscriber.table_name)).must_equal []
|
|
165
180
|
end
|
|
166
|
-
|
|
167
181
|
end
|
|
168
182
|
|
|
169
|
-
describe
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
assert_equal '1', connection.quoted_true
|
|
183
|
+
describe "quoting" do
|
|
184
|
+
it "return 1 for #quoted_true" do
|
|
185
|
+
assert_equal "1", connection.quoted_true
|
|
173
186
|
end
|
|
174
187
|
|
|
175
|
-
it
|
|
176
|
-
assert_equal
|
|
188
|
+
it "return 0 for #quoted_false" do
|
|
189
|
+
assert_equal "0", connection.quoted_false
|
|
177
190
|
end
|
|
178
191
|
|
|
179
|
-
it
|
|
192
|
+
it "not escape backslash characters like abstract adapter" do
|
|
180
193
|
string_with_backslashs = "\\n"
|
|
181
194
|
assert_equal string_with_backslashs, connection.quote_string(string_with_backslashs)
|
|
182
195
|
end
|
|
183
196
|
|
|
184
|
-
it
|
|
185
|
-
assert_equal
|
|
186
|
-
assert_equal
|
|
187
|
-
assert_equal
|
|
197
|
+
it "quote column names with brackets" do
|
|
198
|
+
assert_equal "[foo]", connection.quote_column_name(:foo)
|
|
199
|
+
assert_equal "[foo]", connection.quote_column_name("foo")
|
|
200
|
+
assert_equal "[foo].[bar]", connection.quote_column_name("foo.bar")
|
|
188
201
|
end
|
|
189
202
|
|
|
190
|
-
it
|
|
191
|
-
assert_equal
|
|
192
|
-
assert_equal
|
|
203
|
+
it "not quote already quoted column names with brackets" do
|
|
204
|
+
assert_equal "[foo]", connection.quote_column_name("[foo]")
|
|
205
|
+
assert_equal "[foo].[bar]", connection.quote_column_name("[foo].[bar]")
|
|
193
206
|
end
|
|
194
207
|
|
|
195
|
-
it
|
|
196
|
-
assert_equal
|
|
197
|
-
assert_equal
|
|
208
|
+
it "quote table names like columns" do
|
|
209
|
+
assert_equal "[foo].[bar]", connection.quote_column_name("foo.bar")
|
|
210
|
+
assert_equal "[foo].[bar].[baz]", connection.quote_column_name("foo.bar.baz")
|
|
198
211
|
end
|
|
199
212
|
|
|
200
213
|
it "surround string with national prefix" do
|
|
@@ -204,44 +217,40 @@ class AdapterTestSQLServer < ActiveRecord::TestCase
|
|
|
204
217
|
it "escape all single quotes by repeating them" do
|
|
205
218
|
assert_equal "N'''quotation''s'''", connection.quote("'quotation's'")
|
|
206
219
|
end
|
|
207
|
-
|
|
208
220
|
end
|
|
209
221
|
|
|
210
|
-
describe
|
|
211
|
-
|
|
222
|
+
describe "disabling referential integrity" do
|
|
212
223
|
before do
|
|
213
224
|
connection.disable_referential_integrity { SSTestHasPk.delete_all; SSTestHasFk.delete_all }
|
|
214
225
|
@parent = SSTestHasPk.create!
|
|
215
226
|
@member = SSTestHasFk.create!(fk_id: @parent.id)
|
|
216
227
|
end
|
|
217
228
|
|
|
218
|
-
it
|
|
219
|
-
SSTestHasPk.connection.disable_referential_integrity {
|
|
229
|
+
it "NOT ALLOW by default the deletion of a referenced parent" do
|
|
230
|
+
SSTestHasPk.connection.disable_referential_integrity {}
|
|
220
231
|
assert_raise(ActiveRecord::StatementInvalid) { @parent.destroy }
|
|
221
232
|
end
|
|
222
233
|
|
|
223
|
-
it
|
|
234
|
+
it "ALLOW deletion of referenced parent using #disable_referential_integrity block" do
|
|
224
235
|
SSTestHasPk.connection.disable_referential_integrity { @parent.destroy }
|
|
225
236
|
end
|
|
226
237
|
|
|
227
|
-
it
|
|
238
|
+
it "again NOT ALLOW deletion of referenced parent after #disable_referential_integrity block" do
|
|
228
239
|
assert_raise(ActiveRecord::StatementInvalid) do
|
|
229
|
-
SSTestHasPk.connection.disable_referential_integrity {
|
|
240
|
+
SSTestHasPk.connection.disable_referential_integrity {}
|
|
230
241
|
@parent.destroy
|
|
231
242
|
end
|
|
232
243
|
end
|
|
233
244
|
|
|
234
|
-
it
|
|
245
|
+
it "not disable referential integrity for the same table twice" do
|
|
235
246
|
tables = SSTestHasPk.connection.tables_with_referential_integrity
|
|
236
247
|
assert_equal tables.size, tables.uniq.size
|
|
237
248
|
end
|
|
238
|
-
|
|
239
249
|
end
|
|
240
250
|
|
|
241
|
-
describe
|
|
242
|
-
|
|
251
|
+
describe "database statements" do
|
|
243
252
|
it "run the database consistency checker useroptions command" do
|
|
244
|
-
skip
|
|
253
|
+
skip "on azure" if connection_sqlserver_azure?
|
|
245
254
|
keys = [:textsize, :language, :isolation_level, :dateformat]
|
|
246
255
|
user_options = connection.user_options
|
|
247
256
|
keys.each do |key|
|
|
@@ -251,183 +260,217 @@ class AdapterTestSQLServer < ActiveRecord::TestCase
|
|
|
251
260
|
end
|
|
252
261
|
|
|
253
262
|
it "return a underscored key hash with indifferent access of the results" do
|
|
254
|
-
skip
|
|
263
|
+
skip "on azure" if connection_sqlserver_azure?
|
|
255
264
|
user_options = connection.user_options
|
|
256
|
-
assert_equal
|
|
257
|
-
assert_equal
|
|
265
|
+
assert_equal "read committed", user_options["isolation_level"]
|
|
266
|
+
assert_equal "read committed", user_options[:isolation_level]
|
|
258
267
|
end
|
|
259
|
-
|
|
260
268
|
end
|
|
261
269
|
|
|
262
|
-
describe
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
assert_equal 'integer', connection.type_to_sql(:integer)
|
|
270
|
+
describe "schema statements" do
|
|
271
|
+
it "create integers when no limit supplied" do
|
|
272
|
+
assert_equal "integer", connection.type_to_sql(:integer)
|
|
266
273
|
end
|
|
267
274
|
|
|
268
|
-
it
|
|
269
|
-
assert_equal
|
|
275
|
+
it "create integers when limit is 4" do
|
|
276
|
+
assert_equal "integer", connection.type_to_sql(:integer, limit: 4)
|
|
270
277
|
end
|
|
271
278
|
|
|
272
|
-
it
|
|
273
|
-
assert_equal
|
|
279
|
+
it "create integers when limit is 3" do
|
|
280
|
+
assert_equal "integer", connection.type_to_sql(:integer, limit: 3)
|
|
274
281
|
end
|
|
275
282
|
|
|
276
|
-
it
|
|
277
|
-
assert_equal
|
|
283
|
+
it "create smallints when limit is 2" do
|
|
284
|
+
assert_equal "smallint", connection.type_to_sql(:integer, limit: 2)
|
|
278
285
|
end
|
|
279
286
|
|
|
280
|
-
it
|
|
281
|
-
assert_equal
|
|
287
|
+
it "create tinyints when limit is 1" do
|
|
288
|
+
assert_equal "tinyint", connection.type_to_sql(:integer, limit: 1)
|
|
282
289
|
end
|
|
283
290
|
|
|
284
|
-
it
|
|
285
|
-
assert_equal
|
|
286
|
-
assert_equal
|
|
287
|
-
assert_equal
|
|
288
|
-
assert_equal
|
|
291
|
+
it "create bigints when limit is greateer than 4" do
|
|
292
|
+
assert_equal "bigint", connection.type_to_sql(:integer, limit: 5)
|
|
293
|
+
assert_equal "bigint", connection.type_to_sql(:integer, limit: 6)
|
|
294
|
+
assert_equal "bigint", connection.type_to_sql(:integer, limit: 7)
|
|
295
|
+
assert_equal "bigint", connection.type_to_sql(:integer, limit: 8)
|
|
289
296
|
end
|
|
290
297
|
|
|
291
|
-
it
|
|
292
|
-
assert_equal
|
|
298
|
+
it "create floats when no limit supplied" do
|
|
299
|
+
assert_equal "float", connection.type_to_sql(:float)
|
|
293
300
|
end
|
|
294
|
-
|
|
295
301
|
end
|
|
296
302
|
|
|
297
|
-
describe
|
|
298
|
-
|
|
303
|
+
describe "views" do
|
|
299
304
|
# Using connection.views
|
|
300
305
|
|
|
301
|
-
it
|
|
306
|
+
it "return an array" do
|
|
302
307
|
assert_instance_of Array, connection.views
|
|
303
308
|
end
|
|
304
309
|
|
|
305
|
-
it
|
|
306
|
-
_(connection.views).must_include
|
|
310
|
+
it "find SSTestCustomersView table name" do
|
|
311
|
+
_(connection.views).must_include "sst_customers_view"
|
|
307
312
|
end
|
|
308
313
|
|
|
309
|
-
it
|
|
310
|
-
name =
|
|
314
|
+
it "work with dynamic finders" do
|
|
315
|
+
name = "MetaSkills"
|
|
311
316
|
customer = SSTestCustomersView.create! name: name
|
|
312
317
|
assert_equal customer, SSTestCustomersView.find_by_name(name)
|
|
313
318
|
end
|
|
314
319
|
|
|
315
|
-
it
|
|
316
|
-
systables = [
|
|
320
|
+
it "not contain system views" do
|
|
321
|
+
systables = ["sysconstraints", "syssegments"]
|
|
317
322
|
systables.each do |systable|
|
|
318
323
|
assert !connection.views.include?(systable), "This systable #{systable} should not be in the views array."
|
|
319
324
|
end
|
|
320
325
|
end
|
|
321
326
|
|
|
322
|
-
it
|
|
323
|
-
view_info = connection.send(:view_information,
|
|
324
|
-
assert_equal(
|
|
325
|
-
assert_match(/CREATE VIEW sst_customers_view/, view_info[
|
|
327
|
+
it "allow the connection#view_information method to return meta data on the view" do
|
|
328
|
+
view_info = connection.send(:view_information, "sst_customers_view")
|
|
329
|
+
assert_equal("sst_customers_view", view_info["TABLE_NAME"])
|
|
330
|
+
assert_match(/CREATE VIEW sst_customers_view/, view_info["VIEW_DEFINITION"])
|
|
326
331
|
end
|
|
327
332
|
|
|
328
|
-
it
|
|
329
|
-
assert_equal
|
|
330
|
-
assert_equal
|
|
333
|
+
it "allow the connection#view_table_name method to return true table_name for the view" do
|
|
334
|
+
assert_equal "customers", connection.send(:view_table_name, "sst_customers_view")
|
|
335
|
+
assert_equal "topics", connection.send(:view_table_name, "topics"), "No view here, the same table name should come back."
|
|
331
336
|
end
|
|
332
337
|
|
|
333
338
|
# With same column names
|
|
334
339
|
|
|
335
|
-
it
|
|
336
|
-
columns = [
|
|
340
|
+
it "have matching column objects" do
|
|
341
|
+
columns = ["id", "name", "balance"]
|
|
337
342
|
assert !SSTestCustomersView.columns.blank?
|
|
338
343
|
assert_equal columns.size, SSTestCustomersView.columns.size
|
|
339
344
|
columns.each do |colname|
|
|
340
345
|
assert_instance_of ActiveRecord::ConnectionAdapters::SQLServerColumn,
|
|
341
|
-
|
|
342
|
-
|
|
346
|
+
SSTestCustomersView.columns_hash[colname],
|
|
347
|
+
"Column name #{colname.inspect} was not found in these columns #{SSTestCustomersView.columns.map(&:name).inspect}"
|
|
343
348
|
end
|
|
344
349
|
end
|
|
345
350
|
|
|
346
|
-
it
|
|
347
|
-
_(SSTestCustomersView.primary_key).must_equal
|
|
348
|
-
_(connection.primary_key(SSTestCustomersView.table_name)).must_equal
|
|
349
|
-
_(SSTestCustomersView.columns_hash[
|
|
351
|
+
it "find identity column" do
|
|
352
|
+
_(SSTestCustomersView.primary_key).must_equal "id"
|
|
353
|
+
_(connection.primary_key(SSTestCustomersView.table_name)).must_equal "id"
|
|
354
|
+
_(SSTestCustomersView.columns_hash["id"]).must_be :is_identity?
|
|
350
355
|
end
|
|
351
356
|
|
|
352
|
-
it
|
|
357
|
+
it "find default values" do
|
|
353
358
|
assert_equal 0, SSTestCustomersView.new.balance
|
|
354
359
|
end
|
|
355
360
|
|
|
356
|
-
it
|
|
361
|
+
it "respond true to data_source_exists?" do
|
|
357
362
|
assert SSTestCustomersView.connection.data_source_exists?(SSTestCustomersView.table_name)
|
|
358
363
|
end
|
|
359
364
|
|
|
360
365
|
# With aliased column names
|
|
361
366
|
|
|
362
|
-
it
|
|
363
|
-
columns = [
|
|
367
|
+
it "have matching column objects" do
|
|
368
|
+
columns = ["id", "pretend_null"]
|
|
364
369
|
assert !SSTestStringDefaultsView.columns.blank?
|
|
365
370
|
assert_equal columns.size, SSTestStringDefaultsView.columns.size
|
|
366
371
|
columns.each do |colname|
|
|
367
372
|
assert_instance_of ActiveRecord::ConnectionAdapters::SQLServerColumn,
|
|
368
|
-
|
|
369
|
-
|
|
373
|
+
SSTestStringDefaultsView.columns_hash[colname],
|
|
374
|
+
"Column name #{colname.inspect} was not found in these columns #{SSTestStringDefaultsView.columns.map(&:name).inspect}"
|
|
370
375
|
end
|
|
371
376
|
end
|
|
372
377
|
|
|
373
|
-
it
|
|
374
|
-
_(SSTestStringDefaultsView.primary_key).must_equal
|
|
375
|
-
_(connection.primary_key(SSTestStringDefaultsView.table_name)).must_equal
|
|
376
|
-
_(SSTestStringDefaultsView.columns_hash[
|
|
378
|
+
it "find identity column" do
|
|
379
|
+
_(SSTestStringDefaultsView.primary_key).must_equal "id"
|
|
380
|
+
_(connection.primary_key(SSTestStringDefaultsView.table_name)).must_equal "id"
|
|
381
|
+
_(SSTestStringDefaultsView.columns_hash["id"]).must_be :is_identity?
|
|
377
382
|
end
|
|
378
383
|
|
|
379
|
-
it
|
|
380
|
-
assert_equal
|
|
381
|
-
|
|
384
|
+
it "find default values" do
|
|
385
|
+
assert_equal "null", SSTestStringDefaultsView.new.pretend_null,
|
|
386
|
+
SSTestStringDefaultsView.columns_hash["pretend_null"].inspect
|
|
382
387
|
end
|
|
383
388
|
|
|
384
|
-
it
|
|
389
|
+
it "respond true to data_source_exists?" do
|
|
385
390
|
assert SSTestStringDefaultsView.connection.data_source_exists?(SSTestStringDefaultsView.table_name)
|
|
386
391
|
end
|
|
387
392
|
|
|
388
393
|
# That have more than 4000 chars for their defintion
|
|
389
394
|
|
|
390
|
-
it
|
|
395
|
+
it "cope with null returned for the defintion" do
|
|
391
396
|
assert_nothing_raised() { SSTestStringDefaultsBigView.columns }
|
|
392
397
|
end
|
|
393
398
|
|
|
394
|
-
it
|
|
395
|
-
assert_equal
|
|
396
|
-
|
|
399
|
+
it "using alternate view defintion still be able to find real default" do
|
|
400
|
+
assert_equal "null", SSTestStringDefaultsBigView.new.pretend_null,
|
|
401
|
+
SSTestStringDefaultsBigView.columns_hash["pretend_null"].inspect
|
|
397
402
|
end
|
|
398
|
-
|
|
399
403
|
end
|
|
400
404
|
|
|
401
|
-
describe
|
|
402
|
-
|
|
405
|
+
describe "database_prefix_remote_server?" do
|
|
403
406
|
after do
|
|
404
407
|
connection_options.delete(:database_prefix)
|
|
405
408
|
end
|
|
406
409
|
|
|
407
|
-
it
|
|
410
|
+
it "returns false if database_prefix is not configured" do
|
|
408
411
|
assert_equal false, connection.database_prefix_remote_server?
|
|
409
412
|
end
|
|
410
413
|
|
|
411
|
-
it
|
|
414
|
+
it "returns true if database_prefix has been set" do
|
|
412
415
|
connection_options[:database_prefix] = "server.database.schema."
|
|
413
416
|
assert_equal true, connection.database_prefix_remote_server?
|
|
414
417
|
end
|
|
415
418
|
|
|
416
|
-
it
|
|
419
|
+
it "returns false if database_prefix has been set incorrectly" do
|
|
417
420
|
connection_options[:database_prefix] = "server.database.schema"
|
|
418
421
|
assert_equal false, connection.database_prefix_remote_server?
|
|
419
422
|
end
|
|
420
|
-
|
|
421
423
|
end
|
|
422
424
|
|
|
423
|
-
it
|
|
424
|
-
if ENV[
|
|
425
|
-
_(SSTMemory.primary_key).must_equal
|
|
426
|
-
_(SSTMemory.columns_hash[
|
|
425
|
+
it "in_memory_oltp" do
|
|
426
|
+
if ENV["IN_MEMORY_OLTP"] && connection.supports_in_memory_oltp?
|
|
427
|
+
_(SSTMemory.primary_key).must_equal "id"
|
|
428
|
+
_(SSTMemory.columns_hash["id"]).must_be :is_identity?
|
|
427
429
|
else
|
|
428
|
-
skip
|
|
430
|
+
skip "supports_in_memory_oltp? => false"
|
|
429
431
|
end
|
|
430
432
|
end
|
|
431
433
|
|
|
432
|
-
|
|
434
|
+
describe "block writes to a database" do
|
|
435
|
+
def setup
|
|
436
|
+
@conn = ActiveRecord::Base.connection
|
|
437
|
+
@connection_handler = ActiveRecord::Base.connection_handler
|
|
438
|
+
end
|
|
433
439
|
|
|
440
|
+
def test_errors_when_an_insert_query_is_called_while_preventing_writes
|
|
441
|
+
assert_raises(ActiveRecord::ReadOnlyError) do
|
|
442
|
+
@connection_handler.while_preventing_writes do
|
|
443
|
+
@conn.insert("INSERT INTO [subscribers] ([nick]) VALUES ('aido')")
|
|
444
|
+
end
|
|
445
|
+
end
|
|
446
|
+
end
|
|
447
|
+
|
|
448
|
+
def test_errors_when_an_update_query_is_called_while_preventing_writes
|
|
449
|
+
@conn.insert("INSERT INTO [subscribers] ([nick]) VALUES ('aido')")
|
|
450
|
+
|
|
451
|
+
assert_raises(ActiveRecord::ReadOnlyError) do
|
|
452
|
+
@connection_handler.while_preventing_writes do
|
|
453
|
+
@conn.update("UPDATE [subscribers] SET [subscribers].[name] = 'Aidan' WHERE [subscribers].[nick] = 'aido'")
|
|
454
|
+
end
|
|
455
|
+
end
|
|
456
|
+
end
|
|
457
|
+
|
|
458
|
+
def test_errors_when_a_delete_query_is_called_while_preventing_writes
|
|
459
|
+
@conn.execute("INSERT INTO [subscribers] ([nick]) VALUES ('aido')")
|
|
460
|
+
|
|
461
|
+
assert_raises(ActiveRecord::ReadOnlyError) do
|
|
462
|
+
@connection_handler.while_preventing_writes do
|
|
463
|
+
@conn.execute("DELETE FROM [subscribers] WHERE [subscribers].[nick] = 'aido'")
|
|
464
|
+
end
|
|
465
|
+
end
|
|
466
|
+
end
|
|
467
|
+
|
|
468
|
+
def test_doesnt_error_when_a_select_query_is_called_while_preventing_writes
|
|
469
|
+
@conn.execute("INSERT INTO [subscribers] ([nick]) VALUES ('aido')")
|
|
470
|
+
|
|
471
|
+
@connection_handler.while_preventing_writes do
|
|
472
|
+
assert_equal 1, @conn.execute("SELECT * FROM [subscribers] WHERE [subscribers].[nick] = 'aido'")
|
|
473
|
+
end
|
|
474
|
+
end
|
|
475
|
+
end
|
|
476
|
+
end
|