activerecord-sqlserver-adapter 6.1.3.0 → 7.0.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (31) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +11 -69
  3. data/Gemfile +2 -4
  4. data/MIT-LICENSE +1 -1
  5. data/README.md +7 -7
  6. data/VERSION +1 -1
  7. data/activerecord-sqlserver-adapter.gemspec +2 -2
  8. data/lib/active_record/connection_adapters/sqlserver/core_ext/preloader.rb +7 -15
  9. data/lib/active_record/connection_adapters/sqlserver/database_statements.rb +13 -6
  10. data/lib/active_record/connection_adapters/sqlserver/quoting.rb +2 -4
  11. data/lib/active_record/connection_adapters/sqlserver/schema_creation.rb +9 -11
  12. data/lib/active_record/connection_adapters/sqlserver/schema_statements.rb +15 -1
  13. data/lib/active_record/connection_adapters/sqlserver/type/data.rb +3 -1
  14. data/lib/active_record/connection_adapters/sqlserver/type/date.rb +1 -1
  15. data/lib/active_record/connection_adapters/sqlserver/type/datetime.rb +1 -1
  16. data/lib/active_record/connection_adapters/sqlserver/type/time.rb +1 -1
  17. data/lib/active_record/connection_adapters/sqlserver_adapter.rb +92 -87
  18. data/lib/arel/visitors/sqlserver.rb +2 -0
  19. data/test/cases/coerced_tests.rb +287 -89
  20. data/test/cases/column_test_sqlserver.rb +58 -58
  21. data/test/cases/eager_load_too_many_ids_test_sqlserver.rb +18 -0
  22. data/test/cases/schema_dumper_test_sqlserver.rb +2 -2
  23. data/test/migrations/transaction_table/1_table_will_never_be_created.rb +1 -1
  24. data/test/support/coerceable_test_sqlserver.rb +4 -4
  25. data/test/support/marshal_compatibility_fixtures/SQLServer/rails_6_1_topic.dump +0 -0
  26. data/test/support/marshal_compatibility_fixtures/SQLServer/rails_6_1_topic_associations.dump +0 -0
  27. data/test/support/rake_helpers.rb +3 -1
  28. metadata +19 -19
  29. data/test/cases/active_schema_test_sqlserver.rb +0 -55
  30. data/test/support/marshal_compatibility_fixtures/SQLServer/rails_6_0_topic.dump +0 -0
  31. data/test/support/marshal_compatibility_fixtures/SQLServer/rails_6_0_topic_associations.dump +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 746931d24bb3806cafe400f5e4fed544e36dc7b06c6635a2ed4da4aacbf28590
4
- data.tar.gz: dc87a51ccca60af1256b55f511f919c0ce6e5e9c7bb85a1a6865c52ed1e272f4
3
+ metadata.gz: 9983757834cfcc185a0a292ec422cc8e090a5cdff995be814738bb82b0620373
4
+ data.tar.gz: 527f419f372081cd743fcd0898c16183136ac36eaf36dd14a521bb455a5147cc
5
5
  SHA512:
6
- metadata.gz: c33ad8a4f68a70fb8b15ae9b010d47043c412a17494a1248197651cdfebe3e8960fec51648c81bef28ccc9d4fae6dff08b9732a1f7dec9fe9f5cfcb66b8ccbbf
7
- data.tar.gz: 3f40b13dd7c1d69af465467b5f00a60514c02d4d7f2051c6a78c365374a0ae42d475233b9b08646bb94d8ce4899b8627b836098217efee44fc785814b1cd8bf1
6
+ metadata.gz: 4e64604834556a9bf9bd9be39e3aff2cc267729c6d32f28c697d293a6b9be5f5a44c924bbe6fae48f528b88a6c24c2c2d6337a5658aa295284764cb9a66a46c4
7
+ data.tar.gz: c09d354e4af8a5dbb9eb4ef4ab3fdf3b3a527f3ed779895995aac6d60c6335e0698d57cae2509b43e5e3e2825a724bcc41ed2424822b6f067ae6fddfd26ea9bb
data/CHANGELOG.md CHANGED
@@ -1,76 +1,18 @@
1
- ## v6.1.3.0
1
+ ## v7.0.0.0.rc1
2
2
 
3
- [Full changelog](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/compare/v6.1.2.1...v6.1.3.0)
4
-
5
- #### Fixed
6
-
7
- - [#1006](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/1006) Fix support for index types
8
- - [#1041](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/1041) Fix hook method that allows custom connection configuration.
9
-
10
- #### Changed
11
-
12
- - [#1014](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/1014) Better handle SQL queries with invalid encoding
13
-
14
- ## v6.1.2.1
15
-
16
- [Full changelog](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/compare/v6.1.2.0...v6.1.2.1)
17
-
18
- #### Fixed
19
-
20
- - [#943](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/943) Fix appname resolution when outside Rails context
21
-
22
- ## v6.1.2.0
23
-
24
- [Full changelog](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/compare/v6.1.1.0...v6.1.2.0)
25
-
26
- #### Fixed
27
-
28
- - [#940](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/940) Primary key violation should result in RecordNotUnique error
3
+ [Full changelog](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/compare/6-1-stable...v7.0.0.0.rc1)
29
4
 
30
5
  #### Changed
31
6
 
32
- - [#941](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/941) No longer support configuring the application name by overriding the 'configure_application_name' method.
33
-
34
- ## v6.1.1.0
35
-
36
- [Full changelog](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/compare/v6.1.0.0...v6.1.1.0)
37
-
38
- #### Fixed
39
-
40
- - [#933](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/933) Conditionally apply SQL Server monkey patches to ActiveRecord so that it is safe to use this gem alongside other database adapters (e.g. PostgreSQL) in a multi-database Rails app
41
- - [#935](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/935) Fix schema cache generation
42
- (**breaking change**)
43
- - [#936](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/936) Fix deteministic fetch when table has a composite primary key
44
- - [#938](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/938) Fix date columns serialization for range values
45
-
46
- ## v6.1.0.0
7
+ - [#968](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/968) Define adapter type maps statically
8
+ - [#983](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/983) Optimize remove_columns to use a single SQL statement
9
+ - [#984](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/984) Better handle SQL queries with invalid encoding
10
+ - [#988](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/988) Raise `ActiveRecord::StatementInvalid` when `columns` is called with a non-existing table (***breaking change***)
47
11
 
48
- - No changes
49
-
50
- ## v6.1.0.0.rc1
51
-
52
- [Full changelog](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/compare/6-0-stable...v6.1.0.0.rc1)
53
-
54
- #### Fixed
55
-
56
- - [#872](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/872) Use native String#start_with
57
- - [#876](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/876) Use native String#end_with
58
- - [#873](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/873) Various fixes to get the tests running for Rails 6.1
59
- - [#874](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/874) Deduplicate schema cache structures
60
- - [#875](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/875) Handle default boolean column values when deduplicating
61
- - [#879](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/879) Added visit method for HomogeneousIn
62
- - [#880](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/880) Handle any default column class when deduplicating
63
- - [#861](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/861) Fix Rails 6.1 database config
64
- - [#890](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/890) Fix removal of invalid ordering from select statements
65
- - [#881](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/881) Dump column collation to schema.rb and allow collation changes using column_change
66
- - [#891](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/891) Add support for if_not_exists to indexes
67
- - [#892](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/892) Add support for if_exists on remove_column
68
- - [#883](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/885) Fix quoting of ActiveRecord::Relation::QueryAttribute and ActiveModel::Attributes
69
- - [#893](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/893) Add Active Record Marshal forward compatibility tests
70
- - [#903](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/903) Raise ActiveRecord::ConnectionNotEstablished on calls to execute with a disconnected connection
71
-
72
- #### Changed
12
+ #### Added
73
13
 
74
- - [#917](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/917) Refactored to use new_client connection pattern
14
+ - [#972](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/972) Support `ActiveRecord::QueryLogs`
15
+ - [#981](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/981) Support `find_by` an encrypted attribute
16
+ - [#985](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/985) Support string returning clause for `ActiveRecord#insert_all`
75
17
 
76
- Please check [6-0-stable](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/blob/6-0-stable/CHANGELOG.md) for previous changes.
18
+ Please check [6-1-stable](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/blob/6-1-stable/CHANGELOG.md) for previous changes.
data/Gemfile CHANGED
@@ -7,12 +7,10 @@ git_source(:github) { |repo| "https://github.com/#{repo}.git" }
7
7
  gemspec
8
8
 
9
9
  gem "bcrypt"
10
-
11
- gem "pg", "~> 1.3"
12
-
10
+ gem "pg", ">= 0.18.0"
13
11
  gem "sqlite3", "~> 1.4"
14
12
  gem "tzinfo-data", platforms: [:mingw, :mswin, :x64_mingw, :jruby]
15
- gem "minitest", ">= 5.15.0", "< 5.16"
13
+ gem "benchmark-ips"
16
14
 
17
15
  if ENV["RAILS_SOURCE"]
18
16
  gemspec path: ENV["RAILS_SOURCE"]
data/MIT-LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2008-2015
1
+ Copyright (c) 2008-2022
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
data/README.md CHANGED
@@ -9,11 +9,12 @@
9
9
 
10
10
  The SQL Server adapter for ActiveRecord using SQL Server 2012 or higher.
11
11
 
12
- Interested in older versions? We follow a rational versioning policy that tracks Rails. That means that our 6.x version of the adapter is only for the latest 6.x 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.
12
+ Interested in older versions? We follow a rational versioning policy that tracks Rails. That means that our 7.x version of the adapter is only for the latest 7.x 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.
13
13
 
14
14
  | Adapter Version | Rails Version | Support |
15
- |-----------------| ------------- |---------------------------------------------------------------------------------------------|
16
- | `6.1.3.0` | `6.1.x` | [active](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/tree/6-1-stable) |
15
+ | --------------- | ------------- | ------------------------------------------------------------------------------------------- |
16
+ | `7.0.0.0.rc1` | `7.0.x` | [unreleased](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/tree/main) |
17
+ | `6.1.2.1` | `6.1.x` | [active](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/tree/6-1-stable) |
17
18
  | `6.0.2` | `6.0.x` | [active](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/tree/6-0-stable) |
18
19
  | `5.2.1` | `5.2.x` | [active](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/tree/5-2-stable) |
19
20
  | `5.1.6` | `5.1.x` | [ended](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/tree/5-1-stable) |
@@ -66,7 +67,7 @@ ActiveRecord::Base.table_name_prefix = 'dbo.'
66
67
  It's also possible to create/change/drop a schema in the migration file as in the example below:
67
68
 
68
69
  ```ruby
69
- class CreateFooSchema < ActiveRecord::Migration[6.0]
70
+ class CreateFooSchema < ActiveRecord::Migration[7.0]
70
71
  def up
71
72
  create_schema('foo')
72
73
 
@@ -84,7 +85,7 @@ end
84
85
 
85
86
  #### Configure Connection
86
87
 
87
- We currently conform to an unpublished and non-standard AbstractAdapter interface to configure connections made to the database. To do so, just implement the `configure_connection` method in an initializer like so. In this case below we are setting the `TEXTSIZE` to 64 megabytes.
88
+ We currently conform to an unpublished and non-standard AbstractAdapter interface to configure connections made to the database. To do so, just override the `configure_connection` method in an initializer like so. In this case below we are setting the `TEXTSIZE` to 64 megabytes.
88
89
 
89
90
  ```ruby
90
91
  module ActiveRecord
@@ -187,5 +188,4 @@ You can see an up-to-date list of contributors here: http://github.com/rails-sql
187
188
 
188
189
  ## License
189
190
 
190
- Copyright © 2008-2020. It is free software, and may be redistributed under the terms specified in the [MIT-LICENSE](MIT-LICENSE) file.
191
-
191
+ Copyright © 2008-2022. It is free software, and may be redistributed under the terms specified in the [MIT-LICENSE](MIT-LICENSE) file.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 6.1.3.0
1
+ 7.0.0.0.rc1
@@ -7,7 +7,7 @@ Gem::Specification.new do |spec|
7
7
  spec.platform = Gem::Platform::RUBY
8
8
  spec.version = version
9
9
 
10
- spec.required_ruby_version = ">= 2.5.0"
10
+ spec.required_ruby_version = ">= 2.7.0"
11
11
 
12
12
  spec.license = "MIT"
13
13
  spec.authors = ["Ken Collins", "Anna Carey", "Will Bond", "Murray Steele", "Shawn Balestracci", "Joe Rafaniello", "Tom Ward"]
@@ -27,6 +27,6 @@ Gem::Specification.new do |spec|
27
27
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
28
28
  spec.require_paths = ["lib"]
29
29
 
30
- spec.add_dependency "activerecord", "~> 6.1.0"
30
+ spec.add_dependency "activerecord", "~> 7.0.0"
31
31
  spec.add_dependency "tiny_tds"
32
32
  end
@@ -6,20 +6,12 @@ module ActiveRecord
6
6
  module ConnectionAdapters
7
7
  module SQLServer
8
8
  module CoreExt
9
- module Preloader
10
- private
9
+ module LoaderQuery
10
+ def load_records_for_keys(keys, &block)
11
+ return super unless scope.connection.adapter_name == "SQLServer"
11
12
 
12
- def records_for(ids)
13
- return super unless klass.connection.adapter_name == "SQLServer"
14
-
15
- ids.each_slice(in_clause_length).flat_map do |slice|
16
- scope.where(association_key_name => slice).load do |record|
17
- # Processing only the first owner
18
- # because the record is modified but not an owner
19
- owner = owners_by_key[convert_key(record[association_key_name])].first
20
- association = owner.association(reflection.name)
21
- association.set_inverse_instance(record)
22
- end.records
13
+ keys.each_slice(in_clause_length).flat_map do |slice|
14
+ scope.where(association_key_name => slice).load(&block).records
23
15
  end
24
16
  end
25
17
 
@@ -33,6 +25,6 @@ module ActiveRecord
33
25
  end
34
26
 
35
27
  ActiveSupport.on_load(:active_record) do
36
- mod = ActiveRecord::ConnectionAdapters::SQLServer::CoreExt::Preloader
37
- ActiveRecord::Associations::Preloader::Association.prepend(mod)
28
+ mod = ActiveRecord::ConnectionAdapters::SQLServer::CoreExt::LoaderQuery
29
+ ActiveRecord::Associations::Preloader::Association::LoaderQuery.prepend(mod)
38
30
  end
@@ -14,6 +14,7 @@ module ActiveRecord
14
14
  end
15
15
 
16
16
  def execute(sql, name = nil)
17
+ sql = transform_query(sql)
17
18
  if preventing_writes? && write_query?(sql)
18
19
  raise ActiveRecord::ReadOnlyError, "Write query attempted while in readonly mode: #{sql}"
19
20
  end
@@ -28,7 +29,8 @@ module ActiveRecord
28
29
  end
29
30
  end
30
31
 
31
- def exec_query(sql, name = "SQL", binds = [], prepare: false)
32
+ def exec_query(sql, name = "SQL", binds = [], prepare: false, async: false)
33
+ sql = transform_query(sql)
32
34
  if preventing_writes? && write_query?(sql)
33
35
  raise ActiveRecord::ReadOnlyError, "Write query attempted while in readonly mode: #{sql}"
34
36
  end
@@ -36,7 +38,7 @@ module ActiveRecord
36
38
  materialize_transactions
37
39
  mark_transaction_written_if_write(sql)
38
40
 
39
- sp_executesql(sql, name, binds, prepare: prepare)
41
+ sp_executesql(sql, name, binds, prepare: prepare, async: async)
40
42
  end
41
43
 
42
44
  def exec_insert(sql, name = nil, binds = [], pk = nil, _sequence_name = nil)
@@ -147,7 +149,12 @@ module ActiveRecord
147
149
  sql = +"INSERT #{insert.into}"
148
150
 
149
151
  if returning = insert.send(:insert_all).returning
150
- sql << " OUTPUT " << returning.map { |column| "INSERTED.#{quote_column_name(column)}" }.join(", ")
152
+ returning_sql = if returning.is_a?(String)
153
+ returning
154
+ else
155
+ returning.map { |column| "INSERTED.#{quote_column_name(column)}" }.join(", ")
156
+ end
157
+ sql << " OUTPUT #{returning_sql}"
151
158
  end
152
159
 
153
160
  sql << " #{insert.values_list}"
@@ -170,7 +177,7 @@ module ActiveRecord
170
177
  case @connection_options[:mode]
171
178
  when :dblib
172
179
  result = ensure_established_connection! { dblib_execute(sql) }
173
- options = { as: :hash, cache_rows: true, timezone: ActiveRecord::Base.default_timezone || :utc }
180
+ options = { as: :hash, cache_rows: true, timezone: ActiveRecord.default_timezone || :utc }
174
181
  result.each(options) do |row|
175
182
  r = row.with_indifferent_access
176
183
  yield(r) if block_given?
@@ -411,7 +418,7 @@ module ActiveRecord
411
418
  # === SQLServer Specific (Selecting) ============================ #
412
419
 
413
420
  def raw_select(sql, name = "SQL", binds = [], options = {})
414
- log(sql, name, binds) { _raw_select(sql, options) }
421
+ log(sql, name, binds, async: options[:async]) { _raw_select(sql, options) }
415
422
  end
416
423
 
417
424
  def _raw_select(sql, options = {})
@@ -443,7 +450,7 @@ module ActiveRecord
443
450
 
444
451
  def handle_to_names_and_values_dblib(handle, options = {})
445
452
  query_options = {}.tap do |qo|
446
- qo[:timezone] = ActiveRecord::Base.default_timezone || :utc
453
+ qo[:timezone] = ActiveRecord.default_timezone || :utc
447
454
  qo[:as] = (options[:ar_result] || options[:fetch] == :rows) ? :array : :hash
448
455
  end
449
456
  results = handle.each(query_options)
@@ -109,9 +109,7 @@ module ActiveRecord
109
109
 
110
110
  private_constant :COLUMN_NAME, :COLUMN_NAME_WITH_ORDER
111
111
 
112
- private
113
-
114
- def _quote(value)
112
+ def quote(value)
115
113
  case value
116
114
  when Type::Binary::Data
117
115
  "0x#{value.hex}"
@@ -124,7 +122,7 @@ module ActiveRecord
124
122
  end
125
123
  end
126
124
 
127
- def _type_cast(value)
125
+ def type_cast(value)
128
126
  case value
129
127
  when ActiveRecord::Type::SQLServer::Data
130
128
  value.to_s
@@ -34,19 +34,17 @@ module ActiveRecord
34
34
  end
35
35
 
36
36
  def visit_CreateIndexDefinition(o)
37
- index = o.index
37
+ if_not_exists = o.if_not_exists
38
+
39
+ o.if_not_exists = false
40
+
41
+ sql = super
38
42
 
39
- sql = []
40
- sql << "IF NOT EXISTS (SELECT name FROM sysindexes WHERE name = '#{o.index.name}')" if o.if_not_exists
41
- sql << "CREATE"
42
- sql << "UNIQUE" if index.unique
43
- sql << index.type.upcase if index.type
44
- sql << "INDEX"
45
- sql << "#{quote_column_name(index.name)} ON #{quote_table_name(index.table)}"
46
- sql << "(#{quoted_columns(index)})"
47
- sql << "WHERE #{index.where}" if index.where
43
+ if if_not_exists
44
+ sql = "IF NOT EXISTS (SELECT name FROM sysindexes WHERE name = '#{o.index.name}') #{sql}"
45
+ end
48
46
 
49
- sql.join(" ")
47
+ sql
50
48
  end
51
49
 
52
50
  def add_column_options!(sql, options)
@@ -378,7 +378,7 @@ module ActiveRecord
378
378
  binds << Relation::QueryAttribute.new("TABLE_NAME", identifier.object, nv128)
379
379
  binds << Relation::QueryAttribute.new("TABLE_SCHEMA", identifier.schema, nv128) unless identifier.schema.blank?
380
380
  results = sp_executesql(sql, "SCHEMA", binds)
381
- results.map do |ci|
381
+ columns = results.map do |ci|
382
382
  ci = ci.symbolize_keys
383
383
  ci[:_type] = ci[:type]
384
384
  ci[:table_name] = view_tblnm || table_name
@@ -437,6 +437,13 @@ module ActiveRecord
437
437
  ci[:is_identity] = ci[:is_identity].to_i == 1 unless [TrueClass, FalseClass].include?(ci[:is_identity].class)
438
438
  ci
439
439
  end
440
+
441
+ # Since Rails 7, it's expected that all adapter raise error when table doesn't exists.
442
+ # I'm not aware of the possibility of tables without columns on SQL Server (postgres have those).
443
+ # Raise error if the method return an empty array
444
+ columns.tap do |result|
445
+ raise ActiveRecord::StatementInvalid, "Table '#{table_name}' doesn't exist" if result.empty?
446
+ end
440
447
  end
441
448
 
442
449
  def column_definitions_sql(database, identifier)
@@ -507,6 +514,13 @@ module ActiveRecord
507
514
  }.gsub(/[ \t\r\n]+/, " ").strip
508
515
  end
509
516
 
517
+ def remove_columns_for_alter(table_name, *column_names, **options)
518
+ first, *rest = column_names
519
+
520
+ # return an array like this [DROP COLUMN col_1, col_2, col_3]. Abstract adapter joins fragments with ", "
521
+ [remove_column_for_alter(table_name, first)] + rest.map { |column_name| quote_column_name(column_name) }
522
+ end
523
+
510
524
  def remove_check_constraints(table_name, column_name)
511
525
  constraints = select_values "SELECT CONSTRAINT_NAME FROM INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE where TABLE_NAME = '#{quote_string(table_name)}' and COLUMN_NAME = '#{quote_string(column_name)}'", "SCHEMA"
512
526
  constraints.each do |constraint|
@@ -7,6 +7,8 @@ module ActiveRecord
7
7
  class Data
8
8
  attr_reader :value, :type
9
9
 
10
+ delegate :sub, to: :value
11
+
10
12
  def initialize(value, type)
11
13
  @value, @type = value, type
12
14
  end
@@ -25,7 +27,7 @@ module ActiveRecord
25
27
  end
26
28
 
27
29
  def eql?(other)
28
- self.class == other.class && self.value == other.value
30
+ self.class == other.class && value == other.value
29
31
  end
30
32
  alias :== :eql?
31
33
  end
@@ -13,7 +13,7 @@ module ActiveRecord
13
13
  value = super
14
14
  return value unless value.acts_like?(:date)
15
15
 
16
- date = super(value).to_s(:_sqlserver_dateformat)
16
+ date = super(value).to_formatted_s(:_sqlserver_dateformat)
17
17
  Data.new date, self
18
18
  end
19
19
 
@@ -15,7 +15,7 @@ module ActiveRecord
15
15
  value = super
16
16
  return value unless value.acts_like?(:time)
17
17
 
18
- datetime = "#{value.to_s(:_sqlserver_datetime)}.#{quote_fractional(value)}"
18
+ datetime = "#{value.to_formatted_s(:_sqlserver_datetime)}.#{quote_fractional(value)}"
19
19
 
20
20
  Data.new datetime, self
21
21
  end
@@ -11,7 +11,7 @@ module ActiveRecord
11
11
  value = super
12
12
  return value unless value.acts_like?(:time)
13
13
 
14
- time = "#{value.to_s(:_sqlserver_time)}.#{quote_fractional(value)}"
14
+ time = "#{value.to_formatted_s(:_sqlserver_time)}.#{quote_fractional(value)}"
15
15
 
16
16
  Data.new time, self
17
17
  end