activerecord-jdbcsqlserver-adapter 50.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (148) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +15 -0
  3. data/.travis.yml +27 -0
  4. data/CHANGELOG.md +124 -0
  5. data/CODE_OF_CONDUCT.md +31 -0
  6. data/Dockerfile +20 -0
  7. data/Gemfile +77 -0
  8. data/Guardfile +29 -0
  9. data/MIT-LICENSE +20 -0
  10. data/RAILS5-TODO.md +5 -0
  11. data/README.md +93 -0
  12. data/RUNNING_UNIT_TESTS.md +96 -0
  13. data/Rakefile +46 -0
  14. data/VERSION +1 -0
  15. data/activerecord-jdbcsqlserver-adapter.gemspec +21 -0
  16. data/appveyor.yml +39 -0
  17. data/docker-compose.ci.yml +11 -0
  18. data/lib/active_record/connection_adapters/sqlserver/core_ext/active_record.rb +27 -0
  19. data/lib/active_record/connection_adapters/sqlserver/core_ext/attribute_methods.rb +25 -0
  20. data/lib/active_record/connection_adapters/sqlserver/core_ext/date_time.rb +58 -0
  21. data/lib/active_record/connection_adapters/sqlserver/core_ext/explain.rb +47 -0
  22. data/lib/active_record/connection_adapters/sqlserver/core_ext/explain_subscriber.rb +4 -0
  23. data/lib/active_record/connection_adapters/sqlserver/database_limits.rb +49 -0
  24. data/lib/active_record/connection_adapters/sqlserver/database_statements.rb +362 -0
  25. data/lib/active_record/connection_adapters/sqlserver/database_tasks.rb +67 -0
  26. data/lib/active_record/connection_adapters/sqlserver/errors.rb +7 -0
  27. data/lib/active_record/connection_adapters/sqlserver/jdbc_overrides.rb +192 -0
  28. data/lib/active_record/connection_adapters/sqlserver/quoting.rb +99 -0
  29. data/lib/active_record/connection_adapters/sqlserver/schema_creation.rb +34 -0
  30. data/lib/active_record/connection_adapters/sqlserver/schema_dumper.rb +16 -0
  31. data/lib/active_record/connection_adapters/sqlserver/schema_statements.rb +517 -0
  32. data/lib/active_record/connection_adapters/sqlserver/showplan.rb +66 -0
  33. data/lib/active_record/connection_adapters/sqlserver/showplan/printer_table.rb +66 -0
  34. data/lib/active_record/connection_adapters/sqlserver/showplan/printer_xml.rb +22 -0
  35. data/lib/active_record/connection_adapters/sqlserver/sql_type_metadata.rb +20 -0
  36. data/lib/active_record/connection_adapters/sqlserver/table_definition.rb +112 -0
  37. data/lib/active_record/connection_adapters/sqlserver/transaction.rb +64 -0
  38. data/lib/active_record/connection_adapters/sqlserver/type.rb +49 -0
  39. data/lib/active_record/connection_adapters/sqlserver/type/big_integer.rb +19 -0
  40. data/lib/active_record/connection_adapters/sqlserver/type/binary.rb +21 -0
  41. data/lib/active_record/connection_adapters/sqlserver/type/boolean.rb +15 -0
  42. data/lib/active_record/connection_adapters/sqlserver/type/char.rb +32 -0
  43. data/lib/active_record/connection_adapters/sqlserver/type/data.rb +30 -0
  44. data/lib/active_record/connection_adapters/sqlserver/type/date.rb +61 -0
  45. data/lib/active_record/connection_adapters/sqlserver/type/datetime.rb +71 -0
  46. data/lib/active_record/connection_adapters/sqlserver/type/datetime2.rb +17 -0
  47. data/lib/active_record/connection_adapters/sqlserver/type/datetimeoffset.rb +23 -0
  48. data/lib/active_record/connection_adapters/sqlserver/type/decimal.rb +21 -0
  49. data/lib/active_record/connection_adapters/sqlserver/type/float.rb +19 -0
  50. data/lib/active_record/connection_adapters/sqlserver/type/integer.rb +15 -0
  51. data/lib/active_record/connection_adapters/sqlserver/type/json.rb +11 -0
  52. data/lib/active_record/connection_adapters/sqlserver/type/money.rb +25 -0
  53. data/lib/active_record/connection_adapters/sqlserver/type/real.rb +19 -0
  54. data/lib/active_record/connection_adapters/sqlserver/type/small_integer.rb +15 -0
  55. data/lib/active_record/connection_adapters/sqlserver/type/small_money.rb +25 -0
  56. data/lib/active_record/connection_adapters/sqlserver/type/smalldatetime.rb +29 -0
  57. data/lib/active_record/connection_adapters/sqlserver/type/string.rb +12 -0
  58. data/lib/active_record/connection_adapters/sqlserver/type/text.rb +19 -0
  59. data/lib/active_record/connection_adapters/sqlserver/type/time.rb +68 -0
  60. data/lib/active_record/connection_adapters/sqlserver/type/time_value_fractional.rb +93 -0
  61. data/lib/active_record/connection_adapters/sqlserver/type/timestamp.rb +19 -0
  62. data/lib/active_record/connection_adapters/sqlserver/type/tiny_integer.rb +25 -0
  63. data/lib/active_record/connection_adapters/sqlserver/type/unicode_char.rb +21 -0
  64. data/lib/active_record/connection_adapters/sqlserver/type/unicode_string.rb +12 -0
  65. data/lib/active_record/connection_adapters/sqlserver/type/unicode_text.rb +19 -0
  66. data/lib/active_record/connection_adapters/sqlserver/type/unicode_varchar.rb +26 -0
  67. data/lib/active_record/connection_adapters/sqlserver/type/unicode_varchar_max.rb +24 -0
  68. data/lib/active_record/connection_adapters/sqlserver/type/uuid.rb +36 -0
  69. data/lib/active_record/connection_adapters/sqlserver/type/varbinary.rb +26 -0
  70. data/lib/active_record/connection_adapters/sqlserver/type/varbinary_max.rb +24 -0
  71. data/lib/active_record/connection_adapters/sqlserver/type/varchar.rb +26 -0
  72. data/lib/active_record/connection_adapters/sqlserver/type/varchar_max.rb +24 -0
  73. data/lib/active_record/connection_adapters/sqlserver/utils.rb +146 -0
  74. data/lib/active_record/connection_adapters/sqlserver/version.rb +11 -0
  75. data/lib/active_record/connection_adapters/sqlserver_adapter.rb +445 -0
  76. data/lib/active_record/connection_adapters/sqlserver_column.rb +28 -0
  77. data/lib/active_record/jdbc_sqlserver_connection_methods.rb +31 -0
  78. data/lib/active_record/sqlserver_base.rb +16 -0
  79. data/lib/active_record/tasks/sqlserver_database_tasks.rb +131 -0
  80. data/lib/activerecord-jdbcsqlserver-adapter.rb +24 -0
  81. data/lib/activerecord-sqlserver-adapter.rb +1 -0
  82. data/lib/arel/visitors/sqlserver.rb +205 -0
  83. data/lib/arel_sqlserver.rb +3 -0
  84. data/test/appveyor/dbsetup.ps1 +27 -0
  85. data/test/appveyor/dbsetup.sql +11 -0
  86. data/test/bin/wait-for.sh +79 -0
  87. data/test/cases/adapter_test_sqlserver.rb +430 -0
  88. data/test/cases/coerced_tests.rb +845 -0
  89. data/test/cases/column_test_sqlserver.rb +812 -0
  90. data/test/cases/connection_test_sqlserver.rb +71 -0
  91. data/test/cases/execute_procedure_test_sqlserver.rb +45 -0
  92. data/test/cases/fetch_test_sqlserver.rb +57 -0
  93. data/test/cases/fully_qualified_identifier_test_sqlserver.rb +76 -0
  94. data/test/cases/helper_sqlserver.rb +44 -0
  95. data/test/cases/index_test_sqlserver.rb +47 -0
  96. data/test/cases/json_test_sqlserver.rb +32 -0
  97. data/test/cases/migration_test_sqlserver.rb +61 -0
  98. data/test/cases/order_test_sqlserver.rb +147 -0
  99. data/test/cases/pessimistic_locking_test_sqlserver.rb +94 -0
  100. data/test/cases/rake_test_sqlserver.rb +169 -0
  101. data/test/cases/schema_dumper_test_sqlserver.rb +234 -0
  102. data/test/cases/schema_test_sqlserver.rb +54 -0
  103. data/test/cases/scratchpad_test_sqlserver.rb +8 -0
  104. data/test/cases/showplan_test_sqlserver.rb +65 -0
  105. data/test/cases/specific_schema_test_sqlserver.rb +180 -0
  106. data/test/cases/transaction_test_sqlserver.rb +91 -0
  107. data/test/cases/utils_test_sqlserver.rb +129 -0
  108. data/test/cases/uuid_test_sqlserver.rb +49 -0
  109. data/test/config.yml +38 -0
  110. data/test/debug.rb +14 -0
  111. data/test/fixtures/1px.gif +0 -0
  112. data/test/migrations/transaction_table/1_table_will_never_be_created.rb +11 -0
  113. data/test/models/sqlserver/booking.rb +3 -0
  114. data/test/models/sqlserver/customers_view.rb +3 -0
  115. data/test/models/sqlserver/datatype.rb +3 -0
  116. data/test/models/sqlserver/datatype_migration.rb +8 -0
  117. data/test/models/sqlserver/dollar_table_name.rb +3 -0
  118. data/test/models/sqlserver/dot_table_name.rb +3 -0
  119. data/test/models/sqlserver/edge_schema.rb +13 -0
  120. data/test/models/sqlserver/fk_has_fk.rb +3 -0
  121. data/test/models/sqlserver/fk_has_pk.rb +3 -0
  122. data/test/models/sqlserver/natural_pk_data.rb +4 -0
  123. data/test/models/sqlserver/natural_pk_int_data.rb +3 -0
  124. data/test/models/sqlserver/no_pk_data.rb +3 -0
  125. data/test/models/sqlserver/object_default.rb +3 -0
  126. data/test/models/sqlserver/quoted_table.rb +7 -0
  127. data/test/models/sqlserver/quoted_view_1.rb +3 -0
  128. data/test/models/sqlserver/quoted_view_2.rb +3 -0
  129. data/test/models/sqlserver/sst_memory.rb +3 -0
  130. data/test/models/sqlserver/string_default.rb +3 -0
  131. data/test/models/sqlserver/string_defaults_big_view.rb +3 -0
  132. data/test/models/sqlserver/string_defaults_view.rb +3 -0
  133. data/test/models/sqlserver/tinyint_pk.rb +3 -0
  134. data/test/models/sqlserver/upper.rb +3 -0
  135. data/test/models/sqlserver/uppered.rb +3 -0
  136. data/test/models/sqlserver/uuid.rb +3 -0
  137. data/test/schema/datatypes/2012.sql +55 -0
  138. data/test/schema/enable-in-memory-oltp.sql +81 -0
  139. data/test/schema/sqlserver_specific_schema.rb +238 -0
  140. data/test/support/coerceable_test_sqlserver.rb +49 -0
  141. data/test/support/connection_reflection.rb +34 -0
  142. data/test/support/load_schema_sqlserver.rb +29 -0
  143. data/test/support/minitest_sqlserver.rb +1 -0
  144. data/test/support/paths_sqlserver.rb +50 -0
  145. data/test/support/rake_helpers.rb +41 -0
  146. data/test/support/sql_counter_sqlserver.rb +28 -0
  147. data/test/support/test_in_memory_oltp.rb +15 -0
  148. metadata +310 -0
@@ -0,0 +1,27 @@
1
+
2
+ Write-Output "Setting up..."
3
+ [reflection.assembly]::LoadWithPartialName("Microsoft.SqlServer.Smo") | Out-Null
4
+ [reflection.assembly]::LoadWithPartialName("Microsoft.SqlServer.SqlWmiManagement") | Out-Null
5
+
6
+ Write-Output "Setting variables..."
7
+ $serverName = $env:COMPUTERNAME
8
+ $instances = @('SQL2012SP1', 'SQL2014')
9
+ $smo = 'Microsoft.SqlServer.Management.Smo.'
10
+ $wmi = new-object ($smo + 'Wmi.ManagedComputer')
11
+
12
+ Write-Output "Configure Instances..."
13
+ foreach ($instance in $instances) {
14
+ Write-Output "Instance $instance ..."
15
+ Write-Output "Enable TCP/IP and port 1433..."
16
+ $uri = "ManagedComputer[@Name='$serverName']/ServerInstance[@Name='$instance']/ServerProtocol[@Name='Tcp']"
17
+ $tcp = $wmi.GetSmoObject($uri)
18
+ $tcp.IsEnabled = $true
19
+ foreach ($ipAddress in $Tcp.IPAddresses) {
20
+ $ipAddress.IPAddressProperties["TcpDynamicPorts"].Value = ""
21
+ $ipAddress.IPAddressProperties["TcpPort"].Value = "1433"
22
+ }
23
+ $tcp.Alter()
24
+ }
25
+
26
+ Set-Service SQLBrowser -StartupType Manual
27
+ Start-Service SQLBrowser
@@ -0,0 +1,11 @@
1
+ CREATE DATABASE [activerecord_unittest];
2
+ CREATE DATABASE [activerecord_unittest2];
3
+ GO
4
+ CREATE LOGIN [rails] WITH PASSWORD = '', CHECK_POLICY = OFF, DEFAULT_DATABASE = [activerecord_unittest];
5
+ GO
6
+ USE [activerecord_unittest];
7
+ CREATE USER [rails] FOR LOGIN [rails];
8
+ GO
9
+ EXEC sp_addrolemember N'db_owner', N'rails';
10
+ EXEC master..sp_addsrvrolemember @loginame = N'rails', @rolename = N'sysadmin'
11
+ GO
@@ -0,0 +1,79 @@
1
+ #!/bin/sh
2
+
3
+ TIMEOUT=15
4
+ QUIET=0
5
+
6
+ echoerr() {
7
+ if [ "$QUIET" -ne 1 ]; then printf "%s\n" "$*" 1>&2; fi
8
+ }
9
+
10
+ usage() {
11
+ exitcode="$1"
12
+ cat << USAGE >&2
13
+ Usage:
14
+ $cmdname host:port [-t timeout] [-- command args]
15
+ -q | --quiet Do not output any status messages
16
+ -t TIMEOUT | --timeout=timeout Timeout in seconds, zero for no timeout
17
+ -- COMMAND ARGS Execute command with args after the test finishes
18
+ USAGE
19
+ exit "$exitcode"
20
+ }
21
+
22
+ wait_for() {
23
+ for i in `seq $TIMEOUT` ; do
24
+ nc -z "$HOST" "$PORT" > /dev/null 2>&1
25
+
26
+ result=$?
27
+ if [ $result -eq 0 ] ; then
28
+ if [ $# -gt 0 ] ; then
29
+ exec "$@"
30
+ fi
31
+ exit 0
32
+ fi
33
+ sleep 1
34
+ done
35
+ echo "Operation timed out" >&2
36
+ exit 1
37
+ }
38
+
39
+ while [ $# -gt 0 ]
40
+ do
41
+ case "$1" in
42
+ *:* )
43
+ HOST=$(printf "%s\n" "$1"| cut -d : -f 1)
44
+ PORT=$(printf "%s\n" "$1"| cut -d : -f 2)
45
+ shift 1
46
+ ;;
47
+ -q | --quiet)
48
+ QUIET=1
49
+ shift 1
50
+ ;;
51
+ -t)
52
+ TIMEOUT="$2"
53
+ if [ "$TIMEOUT" = "" ]; then break; fi
54
+ shift 2
55
+ ;;
56
+ --timeout=*)
57
+ TIMEOUT="${1#*=}"
58
+ shift 1
59
+ ;;
60
+ --)
61
+ shift
62
+ break
63
+ ;;
64
+ --help)
65
+ usage 0
66
+ ;;
67
+ *)
68
+ echoerr "Unknown argument: $1"
69
+ usage 1
70
+ ;;
71
+ esac
72
+ done
73
+
74
+ if [ "$HOST" = "" -o "$PORT" = "" ]; then
75
+ echoerr "Error: you need to provide a host and port to test."
76
+ usage 2
77
+ fi
78
+
79
+ wait_for "$@"
@@ -0,0 +1,430 @@
1
+ require 'cases/helper_sqlserver'
2
+ require 'models/topic'
3
+ require 'models/task'
4
+ require 'models/post'
5
+ require 'models/subscriber'
6
+ require 'models/minimalistic'
7
+
8
+ class AdapterTestSQLServer < ActiveRecord::TestCase
9
+
10
+ fixtures :tasks
11
+
12
+ let(:basic_insert_sql) { "INSERT INTO [funny_jokes] ([name]) VALUES('Knock knock')" }
13
+ let(:basic_update_sql) { "UPDATE [customers] SET [address_street] = NULL WHERE [id] = 2" }
14
+ let(:basic_select_sql) { "SELECT * FROM [customers] WHERE ([customers].[id] = 1)" }
15
+
16
+ it 'has basic and non-senstive information in the adpaters inspect method' do
17
+ string = connection.inspect
18
+ string.must_match %r{ActiveRecord::ConnectionAdapters::SQLServerAdapter}
19
+ string.must_match %r{version\: \d.\d}
20
+ string.must_match %r{mode: (dblib|jdbc)}
21
+ string.must_match %r{azure: (true|false)}
22
+ string.wont_match %r{host}
23
+ string.wont_match %r{password}
24
+ string.wont_match %r{username}
25
+ string.wont_match %r{port}
26
+ end
27
+
28
+ it 'has a 128 max #table_alias_length' do
29
+ assert connection.table_alias_length <= 128
30
+ end
31
+
32
+ it 'raises invalid statement error for bad SQL' do
33
+ assert_raise(ActiveRecord::StatementInvalid) { Topic.connection.update("UPDATE XXX") }
34
+ end
35
+
36
+ it 'is has our adapter_name' do
37
+ assert_equal 'SQLServer', connection.adapter_name
38
+ end
39
+
40
+ it 'supports migrations' do
41
+ assert connection.supports_migrations?
42
+ end
43
+
44
+ it 'support DDL in transactions' do
45
+ assert connection.supports_ddl_transactions?
46
+ end
47
+
48
+ it 'allow owner table name prefixs like dbo to still allow table exists to return true' do
49
+ begin
50
+ assert_equal 'topics', Topic.table_name
51
+ assert Topic.table_exists?
52
+ Topic.table_name = 'dbo.topics'
53
+ assert Topic.table_exists?, 'Tasks table name of dbo.topics should return true for exists.'
54
+ ensure
55
+ Topic.table_name = 'topics'
56
+ end
57
+ end
58
+
59
+ it 'return true to insert sql query for inserts only' do
60
+ assert connection.send(:insert_sql?,'INSERT...')
61
+ 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")
62
+ assert !connection.send(:insert_sql?,'UPDATE...')
63
+ assert !connection.send(:insert_sql?,'SELECT...')
64
+ end
65
+
66
+ it 'return unquoted table name object from basic INSERT UPDATE and SELECT statements' do
67
+ assert_equal 'funny_jokes', connection.send(:get_table_name, basic_insert_sql)
68
+ assert_equal 'customers', connection.send(:get_table_name, basic_update_sql)
69
+ assert_equal 'customers', connection.send(:get_table_name, basic_select_sql)
70
+ end
71
+
72
+ describe 'with different language' do
73
+
74
+ before do
75
+ @default_language = connection.user_options_language
76
+ end
77
+
78
+ after do
79
+ connection.execute("SET LANGUAGE #{@default_language}") rescue nil
80
+ connection.send :initialize_dateformatter
81
+ end
82
+
83
+ it 'memos users dateformat' do
84
+ connection.execute("SET LANGUAGE us_english") rescue nil
85
+ dateformat = connection.instance_variable_get(:@database_dateformat)
86
+ assert_equal 'mdy', dateformat
87
+ end
88
+
89
+ it 'has a dateformatter' do
90
+ assert Date::DATE_FORMATS[:_sqlserver_dateformat]
91
+ assert Time::DATE_FORMATS[:_sqlserver_dateformat]
92
+ end
93
+
94
+ it 'does a datetime insertion when language is german' do
95
+ connection.execute("SET LANGUAGE deutsch")
96
+ connection.send :initialize_dateformatter
97
+ assert_nothing_raised do
98
+ starting = Time.utc(2000, 1, 31, 5, 42, 0)
99
+ ending = Time.new(2006, 12, 31)
100
+ Task.create! starting: starting, ending: ending
101
+ end
102
+ end
103
+
104
+ end
105
+
106
+ describe 'testing #lowercase_schema_reflection' do
107
+
108
+ before do
109
+ SSTestUpper.delete_all
110
+ SSTestUpper.create COLUMN1: 'Got a minute?', COLUMN2: 419
111
+ SSTestUpper.create COLUMN1: 'Favorite number?', COLUMN2: 69
112
+ end
113
+
114
+ after do
115
+ connection.lowercase_schema_reflection = false
116
+ end
117
+
118
+ it 'not lowercase schema reflection by default' do
119
+ assert SSTestUpper.columns_hash['COLUMN1']
120
+ assert_equal 'Got a minute?', SSTestUpper.first.COLUMN1
121
+ assert_equal 'Favorite number?', SSTestUpper.last.COLUMN1
122
+ assert SSTestUpper.columns_hash['COLUMN2']
123
+ end
124
+
125
+ it 'lowercase schema reflection when set' do
126
+ skip 'we do not currently support forcing identifier case' if defined? JRUBY_VERSION
127
+ connection.lowercase_schema_reflection = true
128
+ assert SSTestUppered.columns_hash['column1']
129
+ assert_equal 'Got a minute?', SSTestUppered.first.column1
130
+ assert_equal 'Favorite number?', SSTestUppered.last.column1
131
+ assert SSTestUppered.columns_hash['column2']
132
+ end
133
+
134
+ end
135
+
136
+ describe 'identity inserts' do
137
+
138
+ before do
139
+ @identity_insert_sql = "INSERT INTO [funny_jokes] ([id],[name]) VALUES(420,'Knock knock')"
140
+ @identity_insert_sql_unquoted = "INSERT INTO funny_jokes (id, name) VALUES(420, 'Knock knock')"
141
+ @identity_insert_sql_unordered = "INSERT INTO [funny_jokes] ([name],[id]) VALUES('Knock knock',420)"
142
+ @identity_insert_sql_sp = "EXEC sp_executesql N'INSERT INTO [funny_jokes] ([id],[name]) VALUES (@0, @1)', N'@0 int, @1 nvarchar(255)', @0 = 420, @1 = N'Knock knock'"
143
+ @identity_insert_sql_unquoted_sp = "EXEC sp_executesql N'INSERT INTO [funny_jokes] (id, name) VALUES (@0, @1)', N'@0 int, @1 nvarchar(255)', @0 = 420, @1 = N'Knock knock'"
144
+ @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"
145
+ end
146
+
147
+ it 'return quoted table_name to #query_requires_identity_insert? when INSERT sql contains id column' do
148
+ assert_equal '[funny_jokes]', connection.send(:query_requires_identity_insert?,@identity_insert_sql)
149
+ assert_equal '[funny_jokes]', connection.send(:query_requires_identity_insert?,@identity_insert_sql_unquoted)
150
+ assert_equal '[funny_jokes]', connection.send(:query_requires_identity_insert?,@identity_insert_sql_unordered)
151
+ assert_equal '[funny_jokes]', connection.send(:query_requires_identity_insert?,@identity_insert_sql_sp)
152
+ assert_equal '[funny_jokes]', connection.send(:query_requires_identity_insert?,@identity_insert_sql_unquoted_sp)
153
+ assert_equal '[funny_jokes]', connection.send(:query_requires_identity_insert?,@identity_insert_sql_unordered_sp)
154
+ end
155
+
156
+ it 'return false to #query_requires_identity_insert? for normal SQL' do
157
+ [basic_insert_sql, basic_update_sql, basic_select_sql].each do |sql|
158
+ assert !connection.send(:query_requires_identity_insert?,sql), "SQL was #{sql}"
159
+ end
160
+ end
161
+
162
+ it 'find identity column using #identity_columns' do
163
+ task_id_column = Task.columns_hash['id']
164
+ assert_equal task_id_column.name, connection.send(:identity_columns, Task.table_name).first.name
165
+ assert_equal task_id_column.sql_type, connection.send(:identity_columns, Task.table_name).first.sql_type
166
+ end
167
+
168
+ it 'return an empty array when calling #identity_columns for a table_name with no identity' do
169
+ connection.send(:identity_columns, Subscriber.table_name).must_equal []
170
+ end
171
+
172
+ end
173
+
174
+ describe 'quoting' do
175
+
176
+ it 'return 1 for #quoted_true' do
177
+ assert_equal '1', connection.quoted_true
178
+ end
179
+
180
+ it 'return 0 for #quoted_false' do
181
+ assert_equal '0', connection.quoted_false
182
+ end
183
+
184
+ it 'not escape backslash characters like abstract adapter' do
185
+ string_with_backslashs = "\\n"
186
+ assert_equal string_with_backslashs, connection.quote_string(string_with_backslashs)
187
+ end
188
+
189
+ it 'quote column names with brackets' do
190
+ assert_equal '[foo]', connection.quote_column_name(:foo)
191
+ assert_equal '[foo]', connection.quote_column_name('foo')
192
+ assert_equal '[foo].[bar]', connection.quote_column_name('foo.bar')
193
+ end
194
+
195
+ it 'not quote already quoted column names with brackets' do
196
+ assert_equal '[foo]', connection.quote_column_name('[foo]')
197
+ assert_equal '[foo].[bar]', connection.quote_column_name('[foo].[bar]')
198
+ end
199
+
200
+ it 'quote table names like columns' do
201
+ assert_equal '[foo].[bar]', connection.quote_column_name('foo.bar')
202
+ assert_equal '[foo].[bar].[baz]', connection.quote_column_name('foo.bar.baz')
203
+ end
204
+
205
+ it "surround string with national prefix" do
206
+ assert_equal "N'foo'", connection.quote("foo")
207
+ end
208
+
209
+ it "escape all single quotes by repeating them" do
210
+ assert_equal "N'''quotation''s'''", connection.quote("'quotation's'")
211
+ end
212
+
213
+ end
214
+
215
+ describe 'disabling referential integrity' do
216
+
217
+ before do
218
+ connection.disable_referential_integrity { SSTestHasPk.delete_all; SSTestHasFk.delete_all }
219
+ @parent = SSTestHasPk.create!
220
+ @member = SSTestHasFk.create!(fk_id: @parent.id)
221
+ end
222
+
223
+ it 'NOT ALLOW by default the deletion of a referenced parent' do
224
+ SSTestHasPk.connection.disable_referential_integrity { }
225
+ assert_raise(ActiveRecord::StatementInvalid) { @parent.destroy }
226
+ end
227
+
228
+ it 'ALLOW deletion of referenced parent using #disable_referential_integrity block' do
229
+ SSTestHasPk.connection.disable_referential_integrity { @parent.destroy }
230
+ end
231
+
232
+ it 'again NOT ALLOW deletion of referenced parent after #disable_referential_integrity block' do
233
+ assert_raise(ActiveRecord::StatementInvalid) do
234
+ SSTestHasPk.connection.disable_referential_integrity { }
235
+ @parent.destroy
236
+ end
237
+ end
238
+
239
+ end
240
+
241
+ describe 'database statements' do
242
+
243
+ it "run the database consistency checker useroptions command" do
244
+ skip 'on azure' if connection_sqlserver_azure?
245
+ keys = [:textsize, :language, :isolation_level, :dateformat]
246
+ user_options = connection.user_options
247
+ keys.each do |key|
248
+ msg = "Expected key:#{key} in user_options:#{user_options.inspect}"
249
+ assert user_options.key?(key), msg
250
+ end
251
+ end
252
+
253
+ it "return a underscored key hash with indifferent access of the results" do
254
+ skip 'on azure' if connection_sqlserver_azure?
255
+ user_options = connection.user_options
256
+ assert_equal 'read committed', user_options['isolation_level']
257
+ assert_equal 'read committed', user_options[:isolation_level]
258
+ end
259
+
260
+ end
261
+
262
+ describe 'schema statements' do
263
+
264
+ it 'create integers when no limit supplied' do
265
+ assert_equal 'integer', connection.type_to_sql(:integer)
266
+ end
267
+
268
+ it 'create integers when limit is 4' do
269
+ assert_equal 'integer', connection.type_to_sql(:integer, 4)
270
+ end
271
+
272
+ it 'create integers when limit is 3' do
273
+ assert_equal 'integer', connection.type_to_sql(:integer, 3)
274
+ end
275
+
276
+ it 'create smallints when limit is less than 3' do
277
+ assert_equal 'smallint', connection.type_to_sql(:integer, 2)
278
+ assert_equal 'smallint', connection.type_to_sql(:integer, 1)
279
+ end
280
+
281
+ it 'create bigints when limit is greateer than 4' do
282
+ assert_equal 'bigint', connection.type_to_sql(:integer, 5)
283
+ assert_equal 'bigint', connection.type_to_sql(:integer, 6)
284
+ assert_equal 'bigint', connection.type_to_sql(:integer, 7)
285
+ assert_equal 'bigint', connection.type_to_sql(:integer, 8)
286
+ end
287
+
288
+ it 'create floats when no limit supplied' do
289
+ assert_equal 'float', connection.type_to_sql(:float)
290
+ end
291
+
292
+ end
293
+
294
+ describe 'views' do
295
+
296
+ # Using connection.views
297
+
298
+ it 'return an array' do
299
+ assert_instance_of Array, connection.views
300
+ end
301
+
302
+ it 'find SSTestCustomersView table name' do
303
+ connection.views.must_include 'sst_customers_view'
304
+ end
305
+
306
+ it 'work with dynamic finders' do
307
+ name = 'MetaSkills'
308
+ customer = SSTestCustomersView.create! name: name
309
+ assert_equal customer, SSTestCustomersView.find_by_name(name)
310
+ end
311
+
312
+ it 'not contain system views' do
313
+ systables = ['sysconstraints','syssegments']
314
+ systables.each do |systable|
315
+ assert !connection.views.include?(systable), "This systable #{systable} should not be in the views array."
316
+ end
317
+ end
318
+
319
+ it 'allow the connection#view_information method to return meta data on the view' do
320
+ view_info = connection.send(:view_information,'sst_customers_view')
321
+ assert_equal('sst_customers_view', view_info['TABLE_NAME'])
322
+ assert_match(/CREATE VIEW sst_customers_view/, view_info['VIEW_DEFINITION'])
323
+ end
324
+
325
+ it 'allow the connection#view_table_name method to return true table_name for the view' do
326
+ assert_equal 'customers', connection.send(:view_table_name,'sst_customers_view')
327
+ assert_equal 'topics', connection.send(:view_table_name,'topics'), 'No view here, the same table name should come back.'
328
+ end
329
+
330
+ # With same column names
331
+
332
+ it 'have matching column objects' do
333
+ columns = ['id','name','balance']
334
+ assert !SSTestCustomersView.columns.blank?
335
+ assert_equal columns.size, SSTestCustomersView.columns.size
336
+ columns.each do |colname|
337
+ assert_instance_of ActiveRecord::ConnectionAdapters::SQLServerColumn,
338
+ SSTestCustomersView.columns_hash[colname],
339
+ "Column name #{colname.inspect} was not found in these columns #{SSTestCustomersView.columns.map(&:name).inspect}"
340
+ end
341
+ end
342
+
343
+ it 'find identity column' do
344
+ SSTestCustomersView.primary_key.must_equal 'id'
345
+ connection.primary_key(SSTestCustomersView.table_name).must_equal 'id'
346
+ SSTestCustomersView.columns_hash['id'].must_be :is_identity?
347
+ end
348
+
349
+ it 'find default values' do
350
+ assert_equal 0, SSTestCustomersView.new.balance
351
+ end
352
+
353
+ it 'respond true to data_source_exists?' do
354
+ assert SSTestCustomersView.connection.data_source_exists?(SSTestCustomersView.table_name)
355
+ end
356
+
357
+ # With aliased column names
358
+
359
+ it 'have matching column objects' do
360
+ columns = ['id','pretend_null']
361
+ assert !SSTestStringDefaultsView.columns.blank?
362
+ assert_equal columns.size, SSTestStringDefaultsView.columns.size
363
+ columns.each do |colname|
364
+ assert_instance_of ActiveRecord::ConnectionAdapters::SQLServerColumn,
365
+ SSTestStringDefaultsView.columns_hash[colname],
366
+ "Column name #{colname.inspect} was not found in these columns #{SSTestStringDefaultsView.columns.map(&:name).inspect}"
367
+ end
368
+ end
369
+
370
+ it 'find identity column' do
371
+ SSTestStringDefaultsView.primary_key.must_equal 'id'
372
+ connection.primary_key(SSTestStringDefaultsView.table_name).must_equal 'id'
373
+ SSTestStringDefaultsView.columns_hash['id'].must_be :is_identity?
374
+ end
375
+
376
+ it 'find default values' do
377
+ assert_equal 'null', SSTestStringDefaultsView.new.pretend_null,
378
+ SSTestStringDefaultsView.columns_hash['pretend_null'].inspect
379
+ end
380
+
381
+ it 'respond true to data_source_exists?' do
382
+ assert SSTestStringDefaultsView.connection.data_source_exists?(SSTestStringDefaultsView.table_name)
383
+ end
384
+
385
+ # That have more than 4000 chars for their defintion
386
+
387
+ it 'cope with null returned for the defintion' do
388
+ assert_nothing_raised() { SSTestStringDefaultsBigView.columns }
389
+ end
390
+
391
+ it 'using alternate view defintion still be able to find real default' do
392
+ assert_equal 'null', SSTestStringDefaultsBigView.new.pretend_null,
393
+ SSTestStringDefaultsBigView.columns_hash['pretend_null'].inspect
394
+ end
395
+
396
+ end
397
+
398
+ describe 'database_prefix_remote_server?' do
399
+
400
+ after do
401
+ connection_options.delete(:database_prefix)
402
+ end
403
+
404
+ it 'returns false if database_prefix is not configured' do
405
+ assert_equal false, connection.database_prefix_remote_server?
406
+ end
407
+
408
+ it 'returns true if database_prefix has been set' do
409
+ connection_options[:database_prefix] = "server.database.schema."
410
+ assert_equal true, connection.database_prefix_remote_server?
411
+ end
412
+
413
+ it 'returns false if database_prefix has been set incorrectly' do
414
+ connection_options[:database_prefix] = "server.database.schema"
415
+ assert_equal false, connection.database_prefix_remote_server?
416
+ end
417
+
418
+ end
419
+
420
+ it 'in_memory_oltp' do
421
+ if ENV['IN_MEMORY_OLTP'] && connection.supports_in_memory_oltp?
422
+ SSTMemory.primary_key.must_equal 'id'
423
+ SSTMemory.columns_hash['id'].must_be :is_identity?
424
+ else
425
+ skip 'supports_in_memory_oltp? => false'
426
+ end
427
+ end
428
+
429
+ end
430
+