activerecord-sqlserver-adapter_new 4.2.15

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 (132) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +15 -0
  3. data/CHANGELOG.md +212 -0
  4. data/CODE_OF_CONDUCT.md +31 -0
  5. data/Gemfile +61 -0
  6. data/Guardfile +29 -0
  7. data/MIT-LICENSE +20 -0
  8. data/README.md +201 -0
  9. data/RUNNING_UNIT_TESTS.md +121 -0
  10. data/Rakefile +48 -0
  11. data/VERSION +1 -0
  12. data/activerecord-sqlserver-adapter_new.gemspec +20 -0
  13. data/appveyor.yml +39 -0
  14. data/lib/active_record/connection_adapters/sqlserver/core_ext/active_record.rb +27 -0
  15. data/lib/active_record/connection_adapters/sqlserver/core_ext/attribute_methods.rb +25 -0
  16. data/lib/active_record/connection_adapters/sqlserver/core_ext/explain.rb +40 -0
  17. data/lib/active_record/connection_adapters/sqlserver/core_ext/explain_subscriber.rb +4 -0
  18. data/lib/active_record/connection_adapters/sqlserver/core_ext/odbc.rb +34 -0
  19. data/lib/active_record/connection_adapters/sqlserver/database_limits.rb +49 -0
  20. data/lib/active_record/connection_adapters/sqlserver/database_statements.rb +386 -0
  21. data/lib/active_record/connection_adapters/sqlserver/database_tasks.rb +68 -0
  22. data/lib/active_record/connection_adapters/sqlserver/errors.rb +7 -0
  23. data/lib/active_record/connection_adapters/sqlserver/quoting.rb +69 -0
  24. data/lib/active_record/connection_adapters/sqlserver/schema_cache.rb +114 -0
  25. data/lib/active_record/connection_adapters/sqlserver/schema_creation.rb +52 -0
  26. data/lib/active_record/connection_adapters/sqlserver/schema_statements.rb +473 -0
  27. data/lib/active_record/connection_adapters/sqlserver/showplan.rb +66 -0
  28. data/lib/active_record/connection_adapters/sqlserver/showplan/printer_table.rb +66 -0
  29. data/lib/active_record/connection_adapters/sqlserver/showplan/printer_xml.rb +22 -0
  30. data/lib/active_record/connection_adapters/sqlserver/table_definition.rb +76 -0
  31. data/lib/active_record/connection_adapters/sqlserver/transaction.rb +57 -0
  32. data/lib/active_record/connection_adapters/sqlserver/type.rb +46 -0
  33. data/lib/active_record/connection_adapters/sqlserver/type/big_integer.rb +15 -0
  34. data/lib/active_record/connection_adapters/sqlserver/type/binary.rb +15 -0
  35. data/lib/active_record/connection_adapters/sqlserver/type/boolean.rb +12 -0
  36. data/lib/active_record/connection_adapters/sqlserver/type/char.rb +38 -0
  37. data/lib/active_record/connection_adapters/sqlserver/type/date.rb +21 -0
  38. data/lib/active_record/connection_adapters/sqlserver/type/datetime.rb +41 -0
  39. data/lib/active_record/connection_adapters/sqlserver/type/datetime2.rb +17 -0
  40. data/lib/active_record/connection_adapters/sqlserver/type/datetimeoffset.rb +31 -0
  41. data/lib/active_record/connection_adapters/sqlserver/type/decimal.rb +12 -0
  42. data/lib/active_record/connection_adapters/sqlserver/type/float.rb +15 -0
  43. data/lib/active_record/connection_adapters/sqlserver/type/integer.rb +12 -0
  44. data/lib/active_record/connection_adapters/sqlserver/type/money.rb +21 -0
  45. data/lib/active_record/connection_adapters/sqlserver/type/real.rb +15 -0
  46. data/lib/active_record/connection_adapters/sqlserver/type/small_integer.rb +13 -0
  47. data/lib/active_record/connection_adapters/sqlserver/type/small_money.rb +21 -0
  48. data/lib/active_record/connection_adapters/sqlserver/type/smalldatetime.rb +22 -0
  49. data/lib/active_record/connection_adapters/sqlserver/type/string.rb +12 -0
  50. data/lib/active_record/connection_adapters/sqlserver/type/text.rb +15 -0
  51. data/lib/active_record/connection_adapters/sqlserver/type/time.rb +40 -0
  52. data/lib/active_record/connection_adapters/sqlserver/type/time_value_fractional.rb +76 -0
  53. data/lib/active_record/connection_adapters/sqlserver/type/timestamp.rb +15 -0
  54. data/lib/active_record/connection_adapters/sqlserver/type/tiny_integer.rb +22 -0
  55. data/lib/active_record/connection_adapters/sqlserver/type/unicode_char.rb +15 -0
  56. data/lib/active_record/connection_adapters/sqlserver/type/unicode_string.rb +12 -0
  57. data/lib/active_record/connection_adapters/sqlserver/type/unicode_text.rb +15 -0
  58. data/lib/active_record/connection_adapters/sqlserver/type/unicode_varchar.rb +20 -0
  59. data/lib/active_record/connection_adapters/sqlserver/type/unicode_varchar_max.rb +20 -0
  60. data/lib/active_record/connection_adapters/sqlserver/type/uuid.rb +23 -0
  61. data/lib/active_record/connection_adapters/sqlserver/type/varbinary.rb +20 -0
  62. data/lib/active_record/connection_adapters/sqlserver/type/varbinary_max.rb +20 -0
  63. data/lib/active_record/connection_adapters/sqlserver/type/varchar.rb +20 -0
  64. data/lib/active_record/connection_adapters/sqlserver/type/varchar_max.rb +20 -0
  65. data/lib/active_record/connection_adapters/sqlserver/utils.rb +136 -0
  66. data/lib/active_record/connection_adapters/sqlserver/version.rb +11 -0
  67. data/lib/active_record/connection_adapters/sqlserver_adapter.rb +405 -0
  68. data/lib/active_record/connection_adapters/sqlserver_column.rb +53 -0
  69. data/lib/active_record/sqlserver_base.rb +20 -0
  70. data/lib/active_record/tasks/sqlserver_database_tasks.rb +131 -0
  71. data/lib/activerecord-sqlserver-adapter.rb +1 -0
  72. data/lib/arel/visitors/sqlserver.rb +214 -0
  73. data/lib/arel_sqlserver.rb +3 -0
  74. data/test/appveyor/dbsetup.ps1 +27 -0
  75. data/test/appveyor/dbsetup.sql +11 -0
  76. data/test/cases/adapter_test_sqlserver.rb +444 -0
  77. data/test/cases/coerced_tests.rb +713 -0
  78. data/test/cases/column_test_sqlserver.rb +780 -0
  79. data/test/cases/connection_test_sqlserver.rb +142 -0
  80. data/test/cases/execute_procedure_test_sqlserver.rb +44 -0
  81. data/test/cases/fetch_test_sqlserver.rb +57 -0
  82. data/test/cases/fully_qualified_identifier_test_sqlserver.rb +76 -0
  83. data/test/cases/helper_sqlserver.rb +54 -0
  84. data/test/cases/migration_test_sqlserver.rb +61 -0
  85. data/test/cases/order_test_sqlserver.rb +147 -0
  86. data/test/cases/pessimistic_locking_test_sqlserver.rb +90 -0
  87. data/test/cases/rake_test_sqlserver.rb +163 -0
  88. data/test/cases/schema_dumper_test_sqlserver.rb +198 -0
  89. data/test/cases/schema_test_sqlserver.rb +54 -0
  90. data/test/cases/scratchpad_test_sqlserver.rb +9 -0
  91. data/test/cases/showplan_test_sqlserver.rb +65 -0
  92. data/test/cases/specific_schema_test_sqlserver.rb +167 -0
  93. data/test/cases/transaction_test_sqlserver.rb +66 -0
  94. data/test/cases/utils_test_sqlserver.rb +129 -0
  95. data/test/cases/uuid_test_sqlserver.rb +48 -0
  96. data/test/config.yml +41 -0
  97. data/test/debug.rb +14 -0
  98. data/test/fixtures/1px.gif +0 -0
  99. data/test/migrations/transaction_table/1_table_will_never_be_created.rb +11 -0
  100. data/test/models/sqlserver/booking.rb +3 -0
  101. data/test/models/sqlserver/customers_view.rb +3 -0
  102. data/test/models/sqlserver/datatype.rb +3 -0
  103. data/test/models/sqlserver/datatype_migration.rb +3 -0
  104. data/test/models/sqlserver/dollar_table_name.rb +3 -0
  105. data/test/models/sqlserver/dot_table_name.rb +3 -0
  106. data/test/models/sqlserver/edge_schema.rb +13 -0
  107. data/test/models/sqlserver/fk_has_fk.rb +3 -0
  108. data/test/models/sqlserver/fk_has_pk.rb +3 -0
  109. data/test/models/sqlserver/natural_pk_data.rb +4 -0
  110. data/test/models/sqlserver/natural_pk_int_data.rb +3 -0
  111. data/test/models/sqlserver/no_pk_data.rb +3 -0
  112. data/test/models/sqlserver/object_default.rb +3 -0
  113. data/test/models/sqlserver/quoted_table.rb +7 -0
  114. data/test/models/sqlserver/quoted_view_1.rb +3 -0
  115. data/test/models/sqlserver/quoted_view_2.rb +3 -0
  116. data/test/models/sqlserver/string_default.rb +3 -0
  117. data/test/models/sqlserver/string_defaults_big_view.rb +3 -0
  118. data/test/models/sqlserver/string_defaults_view.rb +3 -0
  119. data/test/models/sqlserver/tinyint_pk.rb +3 -0
  120. data/test/models/sqlserver/upper.rb +3 -0
  121. data/test/models/sqlserver/uppered.rb +3 -0
  122. data/test/models/sqlserver/uuid.rb +3 -0
  123. data/test/schema/datatypes/2012.sql +55 -0
  124. data/test/schema/sqlserver_specific_schema.rb +207 -0
  125. data/test/support/coerceable_test_sqlserver.rb +45 -0
  126. data/test/support/connection_reflection.rb +37 -0
  127. data/test/support/load_schema_sqlserver.rb +29 -0
  128. data/test/support/minitest_sqlserver.rb +1 -0
  129. data/test/support/paths_sqlserver.rb +50 -0
  130. data/test/support/rake_helpers.rb +41 -0
  131. data/test/support/sql_counter_sqlserver.rb +32 -0
  132. metadata +253 -0
@@ -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,444 @@
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|odbc)}
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 = Date.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
+ connection.lowercase_schema_reflection = true
127
+ assert SSTestUppered.columns_hash['column1']
128
+ assert_equal 'Got a minute?', SSTestUppered.first.column1
129
+ assert_equal 'Favorite number?', SSTestUppered.last.column1
130
+ assert SSTestUppered.columns_hash['column2']
131
+ end
132
+
133
+ end
134
+
135
+ describe 'identity inserts' do
136
+
137
+ before do
138
+ @identity_insert_sql = "INSERT INTO [funny_jokes] ([id],[name]) VALUES(420,'Knock knock')"
139
+ @identity_insert_sql_unquoted = "INSERT INTO funny_jokes (id, name) VALUES(420, 'Knock knock')"
140
+ @identity_insert_sql_unordered = "INSERT INTO [funny_jokes] ([name],[id]) VALUES('Knock knock',420)"
141
+ @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'"
142
+ @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'"
143
+ @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"
144
+ end
145
+
146
+ it 'return quoted table_name to #query_requires_identity_insert? when INSERT sql contains id column' do
147
+ assert_equal '[funny_jokes]', connection.send(:query_requires_identity_insert?,@identity_insert_sql)
148
+ assert_equal '[funny_jokes]', connection.send(:query_requires_identity_insert?,@identity_insert_sql_unquoted)
149
+ assert_equal '[funny_jokes]', connection.send(:query_requires_identity_insert?,@identity_insert_sql_unordered)
150
+ assert_equal '[funny_jokes]', connection.send(:query_requires_identity_insert?,@identity_insert_sql_sp)
151
+ assert_equal '[funny_jokes]', connection.send(:query_requires_identity_insert?,@identity_insert_sql_unquoted_sp)
152
+ assert_equal '[funny_jokes]', connection.send(:query_requires_identity_insert?,@identity_insert_sql_unordered_sp)
153
+ end
154
+
155
+ it 'return false to #query_requires_identity_insert? for normal SQL' do
156
+ [basic_insert_sql, basic_update_sql, basic_select_sql].each do |sql|
157
+ assert !connection.send(:query_requires_identity_insert?,sql), "SQL was #{sql}"
158
+ end
159
+ end
160
+
161
+ it 'find identity column using #identity_column' do
162
+ task_id_column = Task.columns_hash['id']
163
+ assert_equal task_id_column.name, connection.send(:identity_column, Task.table_name).name
164
+ assert_equal task_id_column.sql_type, connection.send(:identity_column, Task.table_name).sql_type
165
+ end
166
+
167
+ it 'return nil when calling #identity_column for a table_name with no identity' do
168
+ assert_nil connection.send(:identity_column, Subscriber.table_name)
169
+ end
170
+
171
+ end
172
+
173
+ describe 'quoting' do
174
+
175
+ it 'return 1 for #quoted_true' do
176
+ assert_equal '1', connection.quoted_true
177
+ end
178
+
179
+ it 'return 0 for #quoted_false' do
180
+ assert_equal '0', connection.quoted_false
181
+ end
182
+
183
+ it 'not escape backslash characters like abstract adapter' do
184
+ string_with_backslashs = "\\n"
185
+ assert_equal string_with_backslashs, connection.quote_string(string_with_backslashs)
186
+ end
187
+
188
+ it 'quote column names with brackets' do
189
+ assert_equal '[foo]', connection.quote_column_name(:foo)
190
+ assert_equal '[foo]', connection.quote_column_name('foo')
191
+ assert_equal '[foo].[bar]', connection.quote_column_name('foo.bar')
192
+ end
193
+
194
+ it 'not quote already quoted column names with brackets' do
195
+ assert_equal '[foo]', connection.quote_column_name('[foo]')
196
+ assert_equal '[foo].[bar]', connection.quote_column_name('[foo].[bar]')
197
+ end
198
+
199
+ it 'quote table names like columns' do
200
+ assert_equal '[foo].[bar]', connection.quote_column_name('foo.bar')
201
+ assert_equal '[foo].[bar].[baz]', connection.quote_column_name('foo.bar.baz')
202
+ end
203
+
204
+ it "surround string with national prefix" do
205
+ assert_equal "N'foo'", connection.quote("foo")
206
+ end
207
+
208
+ it "escape all single quotes by repeating them" do
209
+ assert_equal "N'''quotation''s'''", connection.quote("'quotation's'")
210
+ end
211
+
212
+ end
213
+
214
+ describe 'disabling referential integrity' do
215
+
216
+ before do
217
+ connection.disable_referential_integrity { SSTestHasPk.delete_all; SSTestHasFk.delete_all }
218
+ @parent = SSTestHasPk.create!
219
+ @member = SSTestHasFk.create!(fk_id: @parent.id)
220
+ end
221
+
222
+ it 'NOT ALLOW by default the deletion of a referenced parent' do
223
+ SSTestHasPk.connection.disable_referential_integrity { }
224
+ assert_raise(ActiveRecord::StatementInvalid) { @parent.destroy }
225
+ end
226
+
227
+ it 'ALLOW deletion of referenced parent using #disable_referential_integrity block' do
228
+ SSTestHasPk.connection.disable_referential_integrity { @parent.destroy }
229
+ end
230
+
231
+ it 'again NOT ALLOW deletion of referenced parent after #disable_referential_integrity block' do
232
+ assert_raise(ActiveRecord::StatementInvalid) do
233
+ SSTestHasPk.connection.disable_referential_integrity { }
234
+ @parent.destroy
235
+ end
236
+ end
237
+
238
+ end
239
+
240
+ describe 'database statements' do
241
+
242
+ it "run the database consistency checker useroptions command" do
243
+ skip 'on azure' if connection_sqlserver_azure?
244
+ keys = [:textsize, :language, :isolation_level, :dateformat]
245
+ user_options = connection.user_options
246
+ keys.each do |key|
247
+ msg = "Expected key:#{key} in user_options:#{user_options.inspect}"
248
+ assert user_options.key?(key), msg
249
+ end
250
+ end
251
+
252
+ it "return a underscored key hash with indifferent access of the results" do
253
+ skip 'on azure' if connection_sqlserver_azure?
254
+ user_options = connection.user_options
255
+ assert_equal 'read committed', user_options['isolation_level']
256
+ assert_equal 'read committed', user_options[:isolation_level]
257
+ end
258
+
259
+ end
260
+
261
+ describe 'schema statements' do
262
+
263
+ it 'create integers when no limit supplied' do
264
+ assert_equal 'integer', connection.type_to_sql(:integer)
265
+ end
266
+
267
+ it 'create integers when limit is 4' do
268
+ assert_equal 'integer', connection.type_to_sql(:integer, 4)
269
+ end
270
+
271
+ it 'create integers when limit is 3' do
272
+ assert_equal 'integer', connection.type_to_sql(:integer, 3)
273
+ end
274
+
275
+ it 'create smallints when limit is less than 3' do
276
+ assert_equal 'smallint', connection.type_to_sql(:integer, 2)
277
+ assert_equal 'smallint', connection.type_to_sql(:integer, 1)
278
+ end
279
+
280
+ it 'create bigints when limit is greateer than 4' do
281
+ assert_equal 'bigint', connection.type_to_sql(:integer, 5)
282
+ assert_equal 'bigint', connection.type_to_sql(:integer, 6)
283
+ assert_equal 'bigint', connection.type_to_sql(:integer, 7)
284
+ assert_equal 'bigint', connection.type_to_sql(:integer, 8)
285
+ end
286
+
287
+ it 'create floats when no limit supplied' do
288
+ assert_equal 'float', connection.type_to_sql(:float)
289
+ end
290
+
291
+ end
292
+
293
+ describe 'indexes' do
294
+
295
+ let(:desc_index_name) { 'idx_credit_limit_test_desc' }
296
+
297
+ it 'have indexes with descending order' do
298
+ begin
299
+ connection.execute "CREATE INDEX [#{desc_index_name}] ON [accounts] (credit_limit DESC)"
300
+ assert connection.indexes('accounts').find { |i| i.name == desc_index_name }
301
+ ensure
302
+ connection.execute "DROP INDEX [#{desc_index_name}] ON [accounts]"
303
+ end
304
+ end
305
+
306
+ end
307
+
308
+ describe 'views' do
309
+
310
+ # Using connection.views
311
+
312
+ it 'return an array' do
313
+ assert_instance_of Array, connection.views
314
+ end
315
+
316
+ it 'find SSTestCustomersView table name' do
317
+ connection.views.must_include 'sst_customers_view'
318
+ end
319
+
320
+ it 'work with dynamic finders' do
321
+ name = 'MetaSkills'
322
+ customer = SSTestCustomersView.create! name: name
323
+ assert_equal customer, SSTestCustomersView.find_by_name(name)
324
+ end
325
+
326
+ it 'not contain system views' do
327
+ systables = ['sysconstraints','syssegments']
328
+ systables.each do |systable|
329
+ assert !connection.views.include?(systable), "This systable #{systable} should not be in the views array."
330
+ end
331
+ end
332
+
333
+ it 'allow the connection#view_information method to return meta data on the view' do
334
+ view_info = connection.send(:view_information,'sst_customers_view')
335
+ assert_equal('sst_customers_view', view_info['TABLE_NAME'])
336
+ assert_match(/CREATE VIEW sst_customers_view/, view_info['VIEW_DEFINITION'])
337
+ end
338
+
339
+ it 'allow the connection#view_table_name method to return true table_name for the view' do
340
+ assert_equal 'customers', connection.send(:view_table_name,'sst_customers_view')
341
+ assert_equal 'topics', connection.send(:view_table_name,'topics'), 'No view here, the same table name should come back.'
342
+ end
343
+
344
+ # With same column names
345
+
346
+ it 'have matching column objects' do
347
+ columns = ['id','name','balance']
348
+ assert !SSTestCustomersView.columns.blank?
349
+ assert_equal columns.size, SSTestCustomersView.columns.size
350
+ columns.each do |colname|
351
+ assert_instance_of ActiveRecord::ConnectionAdapters::SQLServerColumn,
352
+ SSTestCustomersView.columns_hash[colname],
353
+ "Column name #{colname.inspect} was not found in these columns #{SSTestCustomersView.columns.map(&:name).inspect}"
354
+ end
355
+ end
356
+
357
+ it 'find identity column' do
358
+ SSTestCustomersView.primary_key.must_equal 'id'
359
+ connection.primary_key(SSTestCustomersView.table_name).must_equal 'id'
360
+ SSTestCustomersView.columns_hash['id'].must_be :is_identity?
361
+ end
362
+
363
+ it 'find default values' do
364
+ assert_equal 0, SSTestCustomersView.new.balance
365
+ end
366
+
367
+ it 'respond true to table_exists?' do
368
+ assert SSTestCustomersView.table_exists?
369
+ end
370
+
371
+ # With aliased column names
372
+
373
+ it 'have matching column objects' do
374
+ columns = ['id','pretend_null']
375
+ assert !SSTestStringDefaultsView.columns.blank?
376
+ assert_equal columns.size, SSTestStringDefaultsView.columns.size
377
+ columns.each do |colname|
378
+ assert_instance_of ActiveRecord::ConnectionAdapters::SQLServerColumn,
379
+ SSTestStringDefaultsView.columns_hash[colname],
380
+ "Column name #{colname.inspect} was not found in these columns #{SSTestStringDefaultsView.columns.map(&:name).inspect}"
381
+ end
382
+ end
383
+
384
+ it 'find identity column' do
385
+ SSTestStringDefaultsView.primary_key.must_equal 'id'
386
+ connection.primary_key(SSTestStringDefaultsView.table_name).must_equal 'id'
387
+ SSTestStringDefaultsView.columns_hash['id'].must_be :is_identity?
388
+ end
389
+
390
+ it 'find default values' do
391
+ assert_equal 'null', SSTestStringDefaultsView.new.pretend_null,
392
+ SSTestStringDefaultsView.columns_hash['pretend_null'].inspect
393
+ end
394
+
395
+ it 'respond true to table_exists?' do
396
+ assert SSTestStringDefaultsView.table_exists?
397
+ end
398
+
399
+ # Doing identity inserts
400
+
401
+ it 'be able to do an identity insert' do
402
+ customer = SSTestCustomersView.new
403
+ customer.id = 420
404
+ customer.save!
405
+ assert SSTestCustomersView.find(420)
406
+ end
407
+
408
+ # That have more than 4000 chars for their defintion
409
+
410
+ it 'cope with null returned for the defintion' do
411
+ assert_nothing_raised() { SSTestStringDefaultsBigView.columns }
412
+ end
413
+
414
+ it 'using alternate view defintion still be able to find real default' do
415
+ assert_equal 'null', SSTestStringDefaultsBigView.new.pretend_null,
416
+ SSTestStringDefaultsBigView.columns_hash['pretend_null'].inspect
417
+ end
418
+
419
+ end
420
+
421
+ describe 'database_prefix_remote_server?' do
422
+
423
+ after do
424
+ connection_options.delete(:database_prefix)
425
+ end
426
+
427
+ it 'returns false if database_prefix is not configured' do
428
+ assert_equal false, connection.database_prefix_remote_server?
429
+ end
430
+
431
+ it 'returns true if database_prefix has been set' do
432
+ connection_options[:database_prefix] = "server.database.schema."
433
+ assert_equal true, connection.database_prefix_remote_server?
434
+ end
435
+
436
+ it 'returns false if database_prefix has been set incorrectly' do
437
+ connection_options[:database_prefix] = "server.database.schema"
438
+ assert_equal false, connection.database_prefix_remote_server?
439
+ end
440
+
441
+ end
442
+
443
+ end
444
+