activerecord-jdbcsqlserver-adapter 50.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.
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
+