activerecord-sqlserver-adapter 5.1.6 → 5.2.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (35) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +3 -1
  3. data/.travis.yml +16 -19
  4. data/CHANGELOG.md +6 -46
  5. data/Dockerfile +14 -0
  6. data/Gemfile +1 -2
  7. data/README.md +4 -4
  8. data/VERSION +1 -1
  9. data/activerecord-sqlserver-adapter.gemspec +1 -1
  10. data/circle.yml +8 -6
  11. data/docker-compose.ci.yml +11 -0
  12. data/lib/active_record/connection_adapters/sqlserver/core_ext/calculations.rb +11 -18
  13. data/lib/active_record/connection_adapters/sqlserver/database_limits.rb +13 -2
  14. data/lib/active_record/connection_adapters/sqlserver/database_statements.rb +45 -9
  15. data/lib/active_record/connection_adapters/sqlserver/schema_creation.rb +2 -1
  16. data/lib/active_record/connection_adapters/sqlserver/schema_dumper.rb +2 -2
  17. data/lib/active_record/connection_adapters/sqlserver/schema_statements.rb +33 -14
  18. data/lib/active_record/connection_adapters/sqlserver/transaction.rb +3 -4
  19. data/lib/active_record/connection_adapters/sqlserver/type/json.rb +1 -1
  20. data/lib/active_record/connection_adapters/sqlserver/type/string.rb +7 -0
  21. data/lib/active_record/connection_adapters/sqlserver_adapter.rb +14 -12
  22. data/lib/active_record/tasks/sqlserver_database_tasks.rb +3 -1
  23. data/lib/arel/visitors/sqlserver.rb +1 -1
  24. data/lib/arel_sqlserver.rb +0 -1
  25. data/test/bin/install-freetds.sh +1 -1
  26. data/test/cases/adapter_test_sqlserver.rb +10 -2
  27. data/test/cases/coerced_tests.rb +262 -13
  28. data/test/cases/column_test_sqlserver.rb +6 -0
  29. data/test/cases/helper_sqlserver.rb +2 -1
  30. data/test/cases/migration_test_sqlserver.rb +3 -1
  31. data/test/cases/order_test_sqlserver.rb +19 -19
  32. data/test/schema/sqlserver_specific_schema.rb +9 -1
  33. data/test/support/core_ext/query_cache.rb +29 -0
  34. metadata +11 -9
  35. data/test/bin/.keep +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ed52e9558d488ea412397afde7def592ba77bc02
4
- data.tar.gz: 74fa1e05812b1dceb9adc7c70b54340dcd8592f1
3
+ metadata.gz: 377130fc57eb80986c8ba867952e53d05bd45716
4
+ data.tar.gz: 375ddc75d6a352aec3546a0ceba47e92aa08c048
5
5
  SHA512:
6
- metadata.gz: 260d513189436bcc2d1a1f109e737598f6e466872cb9e7a7d3c183f8c1088877402bbd4b8dc3b7c506e1522759ce02c7ce538d0d9d42b6436d393fe5c2e625e7
7
- data.tar.gz: f95f71dc632eda2c413d1d1224664ce7d48748bdf3ff541f7cee6034535645880b2ea52700db9fbcf4bf615be79ccab2c5a65f2e9883fe4d6d35736bee0785a8
6
+ metadata.gz: c0d096eb7dbc408c115dc1f694455f67923caca5e3921d23641afc137ac4852d7fdd033d8b4ddc641ad2187b1bc0b83229fe8e81da20fff37b1c42f1825e9239
7
+ data.tar.gz: d5170789fb99e9aea3642c22c9c3e39a0ccb1ee78b0a3015a046d2dd5a179736a61f8483dd878d06c19535f0e32e4a15766ecc1474f2b140b4cb3b362c48d7d8
data/.gitignore CHANGED
@@ -9,7 +9,9 @@ Gemfile.lock
9
9
  test/profile/output/*
10
10
  .rvmrc
11
11
  .rbenv-version
12
+ .tool-versions
12
13
  .idea
13
14
  coverage/*
14
15
  .flooignore
15
- .floo
16
+ .floo
17
+ .byebug_history
@@ -4,25 +4,22 @@ services:
4
4
  - docker
5
5
  env:
6
6
  global:
7
- - TINYTDS_VERSION=2.1.0
8
- - ACTIVERECORD_UNITTEST_HOST=localhost
9
- - ACTIVERECORD_UNITTEST_DATASERVER=localhost
10
- rvm:
11
- - 2.2.5
12
- - 2.3.1
13
- - 2.4.0
7
+ - COMPOSE_FILE: docker-compose.ci.yml
14
8
  before_install:
15
- - export PATH=/opt/local/bin:$PATH
16
- - docker info
17
- - sudo ./test/bin/setup.sh
18
- - sudo ./test/bin/install-openssl.sh
19
- - openssl version
20
- - sudo ./test/bin/install-freetds.sh
21
- - tsql -C
9
+ - sudo rm /usr/local/bin/docker-compose
10
+ - sudo curl -L "https://github.com/docker/compose/releases/download/1.22.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
11
+ - sudo chmod +x /usr/local/bin/docker-compose
22
12
  install:
23
- - export PATH=/opt/local/bin:$PATH
24
- - gem install bundler
25
- - bundle --version
26
- - bundle install
13
+ - docker-compose build --build-arg TARGET_VERSION=$TARGET_VERSION
27
14
  script:
28
- - bundle exec rake
15
+ - docker-compose run ci
16
+ matrix:
17
+ include:
18
+ - name: 2.3.8
19
+ env: TARGET_VERSION=2.3.8
20
+ - name: 2.4.5
21
+ env: TARGET_VERSION=2.4.5
22
+ - name: 2.5.3
23
+ env: TARGET_VERSION=2.5.3
24
+ - name: 2.6.0
25
+ env: TARGET_VERSION=2.6.0
@@ -1,54 +1,14 @@
1
- ## v5.1.6
2
-
3
- #### Added
4
-
5
- * Use lock hint when joining table in query.
6
-
7
-
8
- ## v5.1.5
9
-
10
- #### Fixed
11
-
12
- * Memoize `@@version` queries. Fixes #632
13
-
14
-
15
- ## v5.1.4
16
-
17
- #### Fixed
18
-
19
- * Add case insensitive comparison for better performance with CI collations. Fixes #624
20
-
21
-
22
- ## v5.1.3
1
+ ## v5.2.0.rc1
23
2
 
24
3
  #### Fixed
25
4
 
26
- * Use bigint type in sqlserver_type when needed. Fixes #616
27
-
28
-
29
- ## v5.1.2
30
-
31
- #### Fixed
32
-
33
- * The `fast_string_to_time` method when zone local. Fixes #609 #614 #620
34
- * Patched `Relation#build_count_subquery`. Fixes #613.
35
- * Inserts to tables with triggers using default `OUTPUT INSERTED` style. Fixes #595.
36
-
37
-
38
- ## v5.1.1
39
-
40
- #### Fixed
41
-
42
- * Use `ActiveSupport.on_load` to hook into ActiveRecord Fixes #588 #598
43
-
44
-
45
- ## v5.1.0
5
+ - #638 Don't disable referential integrity for the same table twice.
6
+ - #646 Make String equality check work for Type::Data values. Fixes #645.
7
+ - #671 Fix tinyint columns schema migration. Fixes #670.
46
8
 
47
9
  #### Changed
48
10
 
49
- * The `drop_table` with force cascade option now mimics in via pure SQL for us.
50
-
51
- #### Added
11
+ - #642 Added with (nolock) hint to information_schema.views.
52
12
 
53
- * Support MismatchedForeignKey exception.
54
13
 
14
+ Please check [5-1-stable](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/blob/5-1-stable/CHANGELOG.md) for previous changes.
@@ -0,0 +1,14 @@
1
+ ARG TARGET_VERSION=2.5.3
2
+
3
+ FROM wpolicarpo/activerecord-sqlserver-adapter:${TARGET_VERSION}
4
+
5
+ ENV WORKDIR /activerecord-sqlserver-adapter
6
+
7
+ RUN mkdir -p $WORKDIR
8
+ WORKDIR $WORKDIR
9
+
10
+ COPY . $WORKDIR
11
+
12
+ RUN bundle install --jobs `expr $(cat /proc/cpuinfo | grep -c "cpu cores") - 1` --retry 3
13
+
14
+ CMD ["sh"]
data/Gemfile CHANGED
@@ -2,8 +2,7 @@ require 'openssl'
2
2
  source 'https://rubygems.org'
3
3
  gemspec
4
4
 
5
- gem 'sqlite3'
6
- gem 'minitest', '< 5.3.4'
5
+ gem 'sqlite3', '~> 1.3.6'
7
6
  gem 'bcrypt'
8
7
  gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]
9
8
 
data/README.md CHANGED
@@ -14,13 +14,13 @@ Both TinyTDS and the Rails SQL Server Adapter are MIT-licensed open source proje
14
14
 
15
15
  ## About The Adapter
16
16
 
17
- The SQL Server adapter for ActiveRecord v5.1 using SQL Server 2012 or higher.
17
+ The SQL Server adapter for ActiveRecord v5.2 using SQL Server 2012 or higher.
18
18
 
19
- Interested in older versions? We follow a rational versioning policy that tracks Rails. That means that our 5.0.x version of the adapter is only for the latest 5.0 version of Rails. If you need the adapter for SQL Server 2008 or 2005, you are still in the right spot. Just install the latest 3.2.x to 4.1.x version of the adapter that matches your Rails version. We also have stable branches for each major/minor release of ActiveRecord.
19
+ Interested in older versions? We follow a rational versioning policy that tracks Rails. That means that our 5.1.x version of the adapter is only for the latest 5.1 version of Rails. If you need the adapter for SQL Server 2008 or 2005, you are still in the right spot. Just install the latest 3.2.x to 4.1.x version of the adapter that matches your Rails version. We also have stable branches for each major/minor release of ActiveRecord.
20
20
 
21
21
  #### Native Data Type Support
22
22
 
23
- We support every data type supported by FreeTDS. All simplified Rails types in migrations will coorespond to a matching SQL Server national (unicode) data type. Always check the `initialize_native_database_types` [(here)](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/blob/master/lib/active_record/connection_adapters/sqlserver/schema_statements.rb#L243) for an updated list.
23
+ We support every data type supported by FreeTDS. All simplified Rails types in migrations will coorespond to a matching SQL Server national (unicode) data type. Always check the `initialize_native_database_types` [(here)](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/blob/master/lib/active_record/connection_adapters/sqlserver/schema_statements.rb) for an updated list.
24
24
 
25
25
  The following types (date, datetime2, datetimeoffset, time) all require TDS version 7.3 with TinyTDS. We recommend using FreeTDS 1.0 or higher which default to using `TDSVER` to "7.3". The adapter also sets TinyTDS's `tds_version` to this as well if non is specified.
26
26
 
@@ -136,7 +136,7 @@ gem 'activerecord-sqlserver-adapter'
136
136
 
137
137
  ## Contributing
138
138
 
139
- If you would like to contribute a feature or bugfix, thanks! To make sure your fix/feature has a high chance of being added, please read the following guidelines. First, ask on the Gitter, or post a ticket on github issues. Second, make sure there are tests! We will not accept any patch that is not tested. Please read the `RUNNING_UNIT_TESTS` file for the details of how to run the unit tests.
139
+ If you would like to contribute a feature or bugfix, thanks! To make sure your fix/feature has a high chance of being added, please read the following guidelines. First, ask on the Gitter, or post a ticket on github issues. Second, make sure there are tests! We will not accept any patch that is not tested. Please read the [`RUNNING_UNIT_TESTS`](RUNNING_UNIT_TESTS.md) file for the details of how to run the unit tests.
140
140
 
141
141
  * Github: http://github.com/rails-sqlserver/activerecord-sqlserver-adapter
142
142
  * Gitter: https://gitter.im/rails-sqlserver/activerecord-sqlserver-adapter
data/VERSION CHANGED
@@ -1 +1 @@
1
- 5.1.6
1
+ 5.2.0.rc1
@@ -16,6 +16,6 @@ Gem::Specification.new do |spec|
16
16
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
17
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
18
  spec.require_paths = ['lib']
19
- spec.add_dependency 'activerecord', '~> 5.1.0'
19
+ spec.add_dependency 'activerecord', '~> 5.2.0'
20
20
  spec.add_dependency 'tiny_tds'
21
21
  end
data/circle.yml CHANGED
@@ -18,9 +18,10 @@ dependencies:
18
18
  - openssl version
19
19
  - sudo ./test/bin/install-freetds.sh
20
20
  - tsql -C
21
- - rvm-exec 2.2.5 bundle install
22
- - rvm-exec 2.3.1 bundle install
23
- - rvm-exec 2.4.0 bundle install
21
+ - rvm-exec 2.3.8 bundle install
22
+ - rvm-exec 2.4.5 bundle install
23
+ - rvm-exec 2.5.3 bundle install
24
+ - rvm-exec 2.6.0 bundle install
24
25
 
25
26
  database:
26
27
  override:
@@ -31,6 +32,7 @@ database:
31
32
 
32
33
  test:
33
34
  override:
34
- - rvm-exec 2.2.5 bundle exec rake test
35
- - rvm-exec 2.3.1 bundle exec rake test
36
- - rvm-exec 2.4.0 bundle exec rake test
35
+ - rvm-exec 2.3.8 bundle exec rake test
36
+ - rvm-exec 2.4.5 bundle exec rake test
37
+ - rvm-exec 2.5.3 bundle exec rake test
38
+ - rvm-exec 2.6.0 bundle exec rake test
@@ -0,0 +1,11 @@
1
+ version: "2.2"
2
+ services:
3
+ database:
4
+ image: metaskills/mssql-server-linux-rails
5
+ ci:
6
+ environment:
7
+ - ACTIVERECORD_UNITTEST_HOST=database
8
+ build: .
9
+ command: wait-for database:1433 -- bundle exec rake test
10
+ depends_on:
11
+ - "database"
@@ -9,19 +9,16 @@ module ActiveRecord
9
9
  private
10
10
 
11
11
  def build_count_subquery(relation, column_name, distinct)
12
- relation.select_values = [
13
- if column_name == :all
14
- distinct ? table[Arel.star] : Arel.sql(FinderMethods::ONE_AS_ONE)
15
- else
16
- column_alias = Arel.sql("count_column")
17
- aggregate_column(column_name).as(column_alias)
18
- end
19
- ]
20
-
21
- subquery = relation.arel.as(Arel.sql("subquery_for_count"))
22
- select_value = operation_over_aggregate_column(column_alias || Arel.star, "count", false)
12
+ super(relation.unscope(:order), column_name, distinct)
13
+ end
23
14
 
24
- Arel::SelectManager.new(subquery).project(select_value)
15
+ def type_cast_calculated_value(value, type, operation = nil)
16
+ case operation
17
+ when "count" then value.to_i
18
+ when "sum" then type.deserialize(value || 0)
19
+ when "average" then value&.respond_to?(:to_d) ? value.to_d : value
20
+ else type.deserialize(value)
21
+ end
25
22
  end
26
23
  end
27
24
  end
@@ -30,10 +27,6 @@ module ActiveRecord
30
27
  end
31
28
 
32
29
  ActiveSupport.on_load(:active_record) do
33
- if ActiveRecord::VERSION::MAJOR == 5 &&
34
- ActiveRecord::VERSION::MINOR == 1 &&
35
- ActiveRecord::VERSION::TINY >= 4
36
- mod = ActiveRecord::ConnectionAdapters::SQLServer::CoreExt::Calculations
37
- ActiveRecord::Relation.prepend(mod)
38
- end
30
+ mod = ActiveRecord::ConnectionAdapters::SQLServer::CoreExt::Calculations
31
+ ActiveRecord::Relation.prepend(mod)
39
32
  end
@@ -2,7 +2,6 @@ module ActiveRecord
2
2
  module ConnectionAdapters
3
3
  module SQLServer
4
4
  module DatabaseLimits
5
-
6
5
  def table_alias_length
7
6
  128
8
7
  end
@@ -32,7 +31,7 @@ module ActiveRecord
32
31
  end
33
32
 
34
33
  def in_clause_length
35
- 65_536
34
+ 10_000
36
35
  end
37
36
 
38
37
  def sql_query_length
@@ -43,6 +42,18 @@ module ActiveRecord
43
42
  256
44
43
  end
45
44
 
45
+ private
46
+
47
+ # The max number of binds is 2100, but because sp_executesql takes
48
+ # the first 2 params as the query string and the list of types,
49
+ # we have only 2098 spaces left
50
+ def bind_params_length
51
+ 2_098
52
+ end
53
+
54
+ def insert_rows_length
55
+ 1_000
56
+ end
46
57
  end
47
58
  end
48
59
  end
@@ -33,10 +33,6 @@ module ActiveRecord
33
33
  super(sql, name, binds).rows.first.first
34
34
  end
35
35
 
36
- def supports_statement_cache?
37
- true
38
- end
39
-
40
36
  def begin_db_transaction
41
37
  do_execute 'BEGIN TRANSACTION'
42
38
  end
@@ -77,17 +73,55 @@ module ActiveRecord
77
73
 
78
74
  def case_sensitive_comparison(table, attribute, column, value)
79
75
  if column.collation && !column.case_sensitive?
80
- table[attribute].eq(Arel::Nodes::Bin.new(Arel::Nodes::BindParam.new))
76
+ table[attribute].eq(Arel::Nodes::Bin.new(value))
81
77
  else
82
78
  super
83
79
  end
84
80
  end
85
81
 
82
+ # We should propose this change to Rails team
83
+ def insert_fixtures_set(fixture_set, tables_to_delete = [])
84
+ fixture_inserts = []
85
+
86
+ fixture_set.each do |table_name, fixtures|
87
+ fixtures.each_slice(insert_rows_length) do |batch|
88
+ fixture_inserts << build_fixture_sql(batch, table_name)
89
+ end
90
+ end
91
+
92
+ table_deletes = tables_to_delete.map { |table| "DELETE FROM #{quote_table_name table}".dup }
93
+ total_sql = Array.wrap(combine_multi_statements(table_deletes + fixture_inserts))
94
+
95
+ disable_referential_integrity do
96
+ transaction(requires_new: true) do
97
+ total_sql.each do |sql|
98
+ execute sql, "Fixtures Load"
99
+ yield if block_given?
100
+ end
101
+ end
102
+ end
103
+ end
104
+
86
105
  def can_perform_case_insensitive_comparison_for?(column)
87
106
  column.type == :string && (!column.collation || column.case_sensitive?)
88
107
  end
89
108
  private :can_perform_case_insensitive_comparison_for?
90
109
 
110
+ def combine_multi_statements(total_sql)
111
+ total_sql
112
+ end
113
+ private :combine_multi_statements
114
+
115
+ def default_insert_value(column)
116
+ if column.is_identity?
117
+ table_name = quote(quote_table_name(column.table_name))
118
+ Arel.sql("IDENT_CURRENT(#{table_name}) + IDENT_INCR(#{table_name})")
119
+ else
120
+ super
121
+ end
122
+ end
123
+ private :default_insert_value
124
+
91
125
  # === SQLServer Specific ======================================== #
92
126
 
93
127
  def execute_procedure(proc_name, *variables)
@@ -237,6 +271,8 @@ module ActiveRecord
237
271
  def sp_executesql_types_and_parameters(binds)
238
272
  types, params = [], []
239
273
  binds.each_with_index do |attr, index|
274
+ attr = attr.value if attr.is_a?(Arel::Nodes::BindParam)
275
+
240
276
  types << "@#{index} #{sp_executesql_sql_type(attr)}"
241
277
  params << sp_executesql_sql_param(attr)
242
278
  end
@@ -254,12 +290,12 @@ module ActiveRecord
254
290
  end
255
291
 
256
292
  def sp_executesql_sql_param(attr)
257
- case attr.value_for_database
293
+ case value = attr.value_for_database
258
294
  when Type::Binary::Data,
259
295
  ActiveRecord::Type::SQLServer::Data
260
- quote(attr.value_for_database)
296
+ quote(value)
261
297
  else
262
- quote(type_cast(attr.value_for_database))
298
+ quote(type_cast(value))
263
299
  end
264
300
  end
265
301
 
@@ -305,7 +341,7 @@ module ActiveRecord
305
341
  end
306
342
 
307
343
  def exec_insert_requires_identity?(sql, pk, binds)
308
- query_requires_identity_insert?(sql) if pk && binds.map(&:name).include?(pk)
344
+ query_requires_identity_insert?(sql)
309
345
  end
310
346
 
311
347
  def query_requires_identity_insert?(sql)
@@ -8,7 +8,8 @@ module ActiveRecord
8
8
  def visit_TableDefinition(o)
9
9
  if o.as
10
10
  table_name = quote_table_name(o.temporary ? "##{o.name}" : o.name)
11
- projections, source = @conn.to_sql(o.as).match(%r{SELECT\s+(.*)?\s+FROM\s+(.*)?}).captures
11
+ query = o.as.respond_to?(:to_sql) ? o.as.to_sql : o.as
12
+ projections, source = query.match(%r{SELECT\s+(.*)?\s+FROM\s+(.*)?}).captures
12
13
  select_into = "SELECT #{projections} INTO #{table_name} FROM #{source}"
13
14
  else
14
15
  o.instance_variable_set :@as, nil
@@ -1,7 +1,7 @@
1
1
  module ActiveRecord
2
2
  module ConnectionAdapters
3
3
  module SQLServer
4
- module SchemaDumper
4
+ class SchemaDumper < ConnectionAdapters::SchemaDumper
5
5
 
6
6
  SQLSEVER_NO_LIMIT_TYPES = [
7
7
  'text',
@@ -24,7 +24,7 @@ module ActiveRecord
24
24
 
25
25
  def schema_collation(column)
26
26
  return unless column.collation
27
- column.collation if column.collation != collation
27
+ column.collation if column.collation != @connection.collation
28
28
  end
29
29
 
30
30
  def default_primary_key?(column)
@@ -32,22 +32,33 @@ module ActiveRecord
32
32
  end
33
33
  end
34
34
 
35
- def indexes(table_name, name = nil)
36
- data = select("EXEC sp_helpindex #{quote(table_name)}", name) rescue []
35
+ def indexes(table_name)
36
+ data = select("EXEC sp_helpindex #{quote(table_name)}", "SCHEMA") rescue []
37
+
37
38
  data.reduce([]) do |indexes, index|
38
39
  index = index.with_indifferent_access
40
+
39
41
  if index[:index_description] =~ /primary key/
40
42
  indexes
41
43
  else
42
44
  name = index[:index_name]
43
45
  unique = index[:index_description] =~ /unique/
44
46
  where = select_value("SELECT [filter_definition] FROM sys.indexes WHERE name = #{quote(name)}")
45
- columns = index[:index_keys].split(',').map do |column|
47
+ orders = {}
48
+ columns = []
49
+
50
+ index[:index_keys].split(',').each do |column|
46
51
  column.strip!
47
- column.gsub! '(-)', '' if column.ends_with?('(-)')
48
- column
52
+
53
+ if column.ends_with?('(-)')
54
+ column.gsub! '(-)', ''
55
+ orders[column] = :desc
56
+ end
57
+
58
+ columns << column
49
59
  end
50
- indexes << IndexDefinition.new(table_name, name, unique, columns, nil, nil, where)
60
+
61
+ indexes << IndexDefinition.new(table_name, name, unique, columns, where: where, orders: orders)
51
62
  end
52
63
  end
53
64
  end
@@ -209,7 +220,8 @@ module ActiveRecord
209
220
  case type.to_s
210
221
  when 'integer'
211
222
  case limit
212
- when 1..2 then 'smallint'
223
+ when 1 then 'tinyint'
224
+ when 2 then 'smallint'
213
225
  when 3..4, nil then 'integer'
214
226
  when 5..8 then 'bigint'
215
227
  else raise(ActiveRecordError, "No integer type has byte size #{limit}. Use a numeric with precision 0 instead.")
@@ -235,7 +247,8 @@ module ActiveRecord
235
247
  s.gsub(/\s+(?:ASC|DESC)\b/i, '')
236
248
  .gsub(/\s+NULLS\s+(?:FIRST|LAST)\b/i, '')
237
249
  }.reject(&:blank?).map.with_index { |column, i| "#{column} AS alias_#{i}" }
238
- [super, *order_columns].join(', ')
250
+
251
+ (order_columns << super).join(", ")
239
252
  end
240
253
 
241
254
  def update_table_definition(table_name, base)
@@ -254,13 +267,17 @@ module ActiveRecord
254
267
  do_execute sql
255
268
  end
256
269
 
270
+ def create_schema_dumper(options)
271
+ SQLServer::SchemaDumper.create(self, options)
272
+ end
273
+
257
274
  private
258
275
 
259
276
  def data_source_sql(name = nil, type: nil)
260
277
  scope = quoted_scope name, type: type
261
278
  table_name = lowercase_schema_reflection_sql 'TABLE_NAME'
262
279
  sql = "SELECT #{table_name}"
263
- sql << ' FROM INFORMATION_SCHEMA.TABLES'
280
+ sql << ' FROM INFORMATION_SCHEMA.TABLES WITH (NOLOCK)'
264
281
  sql << ' WHERE TABLE_CATALOG = DB_NAME()'
265
282
  sql << " AND TABLE_SCHEMA = #{quote(scope[:schema])}"
266
283
  sql << " AND TABLE_NAME = #{quote(scope[:name])}" if scope[:name]
@@ -399,11 +416,13 @@ module ActiveRecord
399
416
  ci[:default_function] = begin
400
417
  default = ci[:default_value]
401
418
  if default.nil? && view_exists
402
- default = select_value "
419
+ default = select_value %{
403
420
  SELECT c.COLUMN_DEFAULT
404
421
  FROM #{database}.INFORMATION_SCHEMA.COLUMNS c
405
- WHERE c.TABLE_NAME = '#{view_tblnm}'
406
- AND c.COLUMN_NAME = '#{views_real_column_name(table_name, ci[:name])}'".squish, 'SCHEMA'
422
+ WHERE
423
+ c.TABLE_NAME = '#{view_tblnm}'
424
+ AND c.COLUMN_NAME = '#{views_real_column_name(table_name, ci[:name])}'
425
+ }.squish, 'SCHEMA'
407
426
  end
408
427
  case default
409
428
  when nil
@@ -422,7 +441,7 @@ module ActiveRecord
422
441
  else ci[:type]
423
442
  end
424
443
  value = default.match(/\A\((.*)\)\Z/m)[1]
425
- value = select_value "SELECT CAST(#{value} AS #{type}) AS value", 'SCHEMA'
444
+ value = select_value("SELECT CAST(#{value} AS #{type}) AS value", 'SCHEMA')
426
445
  [value, nil]
427
446
  end
428
447
  end
@@ -495,7 +514,7 @@ module ActiveRecord
495
514
  @view_information ||= {}
496
515
  @view_information[table_name] ||= begin
497
516
  identifier = SQLServer::Utils.extract_identifiers(table_name)
498
- view_info = select_one "SELECT * FROM INFORMATION_SCHEMA.VIEWS WHERE TABLE_NAME = #{quote(identifier.object)}", 'SCHEMA'
517
+ view_info = select_one "SELECT * FROM INFORMATION_SCHEMA.VIEWS WITH (NOLOCK) WHERE TABLE_NAME = #{quote(identifier.object)}", 'SCHEMA'
499
518
  if view_info
500
519
  view_info = view_info.with_indifferent_access
501
520
  if view_info[:VIEW_DEFINITION].blank? || view_info[:VIEW_DEFINITION].length == 4000