activerecord-sqlserver-adapter 7.0.3.0 → 7.0.5.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4a8fb3b90e33355b2f91c6b6cd6e7494f822a0f348881f385bbaee8fbe3b2eee
4
- data.tar.gz: a1a24523b114d48249c543c445d15c77b50239c39aa022468f9f06efe378efeb
3
+ metadata.gz: 817f19cbeb123346a8b663abe75e79a93af2b318189d4e4ff0b1a74414ccfd65
4
+ data.tar.gz: e9e323ec3d0174bd241ab6c841fbc7b3d204c1019c79cb7eefe47cff72b31da4
5
5
  SHA512:
6
- metadata.gz: 813a2f3bf0752a8c9f310997d01e1ffb7a4216381bcd58cb082c811370f36f81e2c8c17a84b2aafc23493afcda7e86af499cc609721e59f0e0bd4b2931709b90
7
- data.tar.gz: d99ed863a56ab7d9036e433521b64fb04d0e8f2764c01d1109d6767a9f62beb46adbacbb36709d6702dc27f31afd0cdbf0adec148cdd5952a1a343f6392bf90d
6
+ metadata.gz: ace03652a84e2943c84cf9fb2fa303fb5c26e9969f4d6375f09a8ddc5cb8a6bf84ac7609d39f9c97c3ffeaba8ef9b0b60f34c3483e576983977b87aa576cd7d4
7
+ data.tar.gz: e8802d4c5c5d936f6b9dbcd53323785830756b1d605d550cc302e0ca3b3862819e12ccc4b87a5a4982f70561b1a58a16422ed776cfd7dabd842aa355895253b1
data/CHANGELOG.md CHANGED
@@ -1,3 +1,21 @@
1
+ ## v7.0.5.0
2
+
3
+ #### Fixed
4
+
5
+ - [#1113](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/1113) Fix issue with default view value not being found because of case sensitivity
6
+ - [#1126](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/1113) Fix view issue with default column value not found
7
+
8
+ ## v7.0.4.0
9
+
10
+ #### Changed
11
+
12
+ - [#1073](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/1073) Improve performance of view default function lookup
13
+
14
+ #### Fixed
15
+
16
+ - [#1088](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/1088) Fix creation of stored procedures that contain insert statements
17
+ - [#1089](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/1089) When changing columns set date-time columns to datetime(6) by default
18
+
1
19
  ## v7.0.3.0
2
20
 
3
21
  #### Fixed
data/MIT-LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2008-2022
1
+ Copyright (c) Ken Collins
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
@@ -13,7 +13,7 @@ Interested in older versions? We follow a rational versioning policy that tracks
13
13
 
14
14
  | Adapter Version | Rails Version | Support |
15
15
  |-----------------| ------------- | ------------------------------------------------------------------------------------------- |
16
- | `7.0.3.0` | `7.0.x` | [active](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/tree/main) |
16
+ | `7.0.4.0` | `7.0.x` | [active](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/tree/main) |
17
17
  | `6.1.2.1` | `6.1.x` | [active](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/tree/6-1-stable) |
18
18
  | `6.0.3` | `6.0.x` | [active](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/tree/6-0-stable) |
19
19
  | `5.2.1` | `5.2.x` | [ended](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/tree/5-2-stable) |
@@ -190,6 +190,7 @@ Many many people have contributed. If you do not see your name here and it shoul
190
190
 
191
191
  You can see an up-to-date list of contributors here: http://github.com/rails-sqlserver/activerecord-sqlserver-adapter/contributors
192
192
 
193
+
193
194
  ## License
194
195
 
195
- Copyright © 2008-2022. It is free software, and may be redistributed under the terms specified in the [MIT-LICENSE](MIT-LICENSE) file.
196
+ ActiveRecord SQL Server Adapter is released under the [MIT License](https://opensource.org/licenses/MIT).
data/VERSION CHANGED
@@ -1 +1 @@
1
- 7.0.3.0
1
+ 7.0.5.0
@@ -10,7 +10,7 @@ Gem::Specification.new do |spec|
10
10
  spec.required_ruby_version = ">= 2.7.0"
11
11
 
12
12
  spec.license = "MIT"
13
- spec.authors = ["Ken Collins", "Anna Carey", "Will Bond", "Murray Steele", "Shawn Balestracci", "Joe Rafaniello", "Tom Ward"]
13
+ spec.authors = ["Ken Collins", "Anna Carey", "Will Bond", "Murray Steele", "Shawn Balestracci", "Joe Rafaniello", "Tom Ward", "Aidan Haran"]
14
14
  spec.email = ["ken@metaskills.net", "will@wbond.net"]
15
15
  spec.homepage = "http://github.com/rails-sqlserver/activerecord-sqlserver-adapter"
16
16
  spec.summary = "ActiveRecord SQL Server Adapter."
@@ -406,7 +406,7 @@ module ActiveRecord
406
406
  end
407
407
 
408
408
  def insert_sql?(sql)
409
- !(sql =~ /^\s*(INSERT|EXEC sp_executesql N'INSERT)/i).nil?
409
+ !(sql =~ /\A\s*(INSERT|EXEC sp_executesql N'INSERT)/i).nil?
410
410
  end
411
411
 
412
412
  def identity_columns(table_name)
@@ -143,6 +143,15 @@ module ActiveRecord
143
143
  def change_column(table_name, column_name, type, options = {})
144
144
  sql_commands = []
145
145
  indexes = []
146
+
147
+ if type == :datetime
148
+ # If no precision then default it to 6.
149
+ options[:precision] = 6 unless options.key?(:precision)
150
+
151
+ # If there is precision then column must be of type 'datetime2'.
152
+ type = :datetime2 unless options[:precision].nil?
153
+ end
154
+
146
155
  column_object = schema_cache.columns(table_name).find { |c| c.name.to_s == column_name.to_s }
147
156
  without_constraints = options.key?(:default) || options.key?(:limit)
148
157
  default = if !options.key?(:default) && column_object
@@ -150,24 +159,29 @@ module ActiveRecord
150
159
  else
151
160
  options[:default]
152
161
  end
162
+
153
163
  if without_constraints || (column_object && column_object.type != type.to_sym)
154
164
  remove_default_constraint(table_name, column_name)
155
165
  indexes = indexes(table_name).select { |index| index.columns.include?(column_name.to_s) }
156
166
  remove_indexes(table_name, column_name)
157
167
  end
168
+
158
169
  sql_commands << "UPDATE #{quote_table_name(table_name)} SET #{quote_column_name(column_name)}=#{quote_default_expression(options[:default], column_object)} WHERE #{quote_column_name(column_name)} IS NULL" if !options[:null].nil? && options[:null] == false && !options[:default].nil?
159
170
  alter_command = "ALTER TABLE #{quote_table_name(table_name)} ALTER COLUMN #{quote_column_name(column_name)} #{type_to_sql(type, limit: options[:limit], precision: options[:precision], scale: options[:scale])}"
160
171
  alter_command += " COLLATE #{options[:collation]}" if options[:collation].present?
161
172
  alter_command += " NOT NULL" if !options[:null].nil? && options[:null] == false
162
173
  sql_commands << alter_command
174
+
163
175
  if without_constraints
164
176
  default = quote_default_expression(default, column_object || column_for(table_name, column_name))
165
177
  sql_commands << "ALTER TABLE #{quote_table_name(table_name)} ADD CONSTRAINT #{default_constraint_name(table_name, column_name)} DEFAULT #{default} FOR #{quote_column_name(column_name)}"
166
178
  end
179
+
167
180
  # Add any removed indexes back
168
181
  indexes.each do |index|
169
182
  sql_commands << "CREATE INDEX #{quote_table_name(index.name)} ON #{quote_table_name(table_name)} (#{index.columns.map { |c| quote_column_name(c) }.join(', ')})"
170
183
  end
184
+
171
185
  sql_commands.each { |c| do_execute(c) }
172
186
  clear_cache!
173
187
  end
@@ -229,6 +243,7 @@ module ActiveRecord
229
243
  def type_to_sql(type, limit: nil, precision: nil, scale: nil, **)
230
244
  type_limitable = %w(string integer float char nchar varchar nvarchar).include?(type.to_s)
231
245
  limit = nil unless type_limitable
246
+
232
247
  case type.to_s
233
248
  when "integer"
234
249
  case limit
@@ -371,6 +386,15 @@ module ActiveRecord
371
386
  view_exists = view_exists?(table_name)
372
387
  view_tblnm = view_table_name(table_name) if view_exists
373
388
 
389
+ if view_exists
390
+ results = sp_executesql %{
391
+ SELECT LOWER(c.COLUMN_NAME) AS [name], c.COLUMN_DEFAULT AS [default]
392
+ FROM #{database}.INFORMATION_SCHEMA.COLUMNS c
393
+ WHERE c.TABLE_NAME = #{quote(view_tblnm)}
394
+ }.squish, "SCHEMA", []
395
+ default_functions = results.each.with_object({}) {|row, out| out[row["name"]] = row["default"] }.compact
396
+ end
397
+
374
398
  sql = column_definitions_sql(database, identifier)
375
399
 
376
400
  binds = []
@@ -402,13 +426,8 @@ module ActiveRecord
402
426
  ci[:default_function] = begin
403
427
  default = ci[:default_value]
404
428
  if default.nil? && view_exists
405
- default = select_value %{
406
- SELECT c.COLUMN_DEFAULT
407
- FROM #{database}.INFORMATION_SCHEMA.COLUMNS c
408
- WHERE
409
- c.TABLE_NAME = '#{view_tblnm}'
410
- AND c.COLUMN_NAME = '#{views_real_column_name(table_name, ci[:name])}'
411
- }.squish, "SCHEMA"
429
+ view_column = views_real_column_name(table_name, ci[:name]).downcase
430
+ default = default_functions[view_column] if view_column.present?
412
431
  end
413
432
  case default
414
433
  when nil
@@ -601,7 +620,7 @@ module ActiveRecord
601
620
  view_definition = view_information(table_name)[:VIEW_DEFINITION]
602
621
  return column_name unless view_definition
603
622
 
604
- match_data = view_definition.match(/([\w-]*)\s+as\s+#{column_name}/im)
623
+ match_data = view_definition.match(/CREATE\s+VIEW.*AS\s+SELECT.*\W([\w-]*)\s+AS\s+#{column_name}/im)
605
624
  match_data ? match_data[1] : column_name
606
625
  end
607
626
 
@@ -1310,9 +1310,26 @@ class RelationTest < ActiveRecord::TestCase
1310
1310
  # We are not doing order duplicate removal anymore.
1311
1311
  coerce_tests! :test_default_scope_order_with_scope_order
1312
1312
 
1313
- # Leave it up to users to format selects/functions so HAVING works correctly.
1313
+ # Order column must be in the GROUP clause.
1314
1314
  coerce_tests! :test_multiple_where_and_having_clauses
1315
+ def test_multiple_where_and_having_clauses_coerced
1316
+ post = Post.first
1317
+ having_then_where = Post.having(id: post.id).where(title: post.title)
1318
+ .having(id: post.id).where(title: post.title).group(:id).select(:id)
1319
+
1320
+ assert_equal [post], having_then_where
1321
+ end
1322
+
1323
+ # Order column must be in the GROUP clause.
1315
1324
  coerce_tests! :test_having_with_binds_for_both_where_and_having
1325
+ def test_having_with_binds_for_both_where_and_having
1326
+ post = Post.first
1327
+ having_then_where = Post.having(id: post.id).where(title: post.title).group(:id).select(:id)
1328
+ where_then_having = Post.where(title: post.title).having(id: post.id).group(:id).select(:id)
1329
+
1330
+ assert_equal [post], having_then_where
1331
+ assert_equal [post], where_then_having
1332
+ end
1316
1333
 
1317
1334
  # Find any limit via our expression.
1318
1335
  coerce_tests! %r{relations don't load all records in #inspect}
@@ -1322,10 +1339,18 @@ class RelationTest < ActiveRecord::TestCase
1322
1339
  end
1323
1340
  end
1324
1341
 
1325
- # I wanted to add `.order("author_id")` scope to avoid error: Column "posts.id" is invalid in the ORDER BY
1326
- # However, this pull request on Rails core drops order on exists relation. https://github.com/rails/rails/pull/28699
1327
- # so we are skipping all together.
1342
+ # Order column must be in the GROUP clause.
1328
1343
  coerce_tests! :test_empty_complex_chained_relations
1344
+ def test_empty_complex_chained_relations_coerced
1345
+ posts = Post.select("comments_count").where("id is not null").group("author_id", "id").where("legacy_comments_count > 0")
1346
+
1347
+ assert_queries(1) { assert_equal false, posts.empty? }
1348
+ assert_not_predicate posts, :loaded?
1349
+
1350
+ no_posts = posts.where(title: "")
1351
+ assert_queries(1) { assert_equal true, no_posts.empty? }
1352
+ assert_not_predicate no_posts, :loaded?
1353
+ end
1329
1354
 
1330
1355
  # Can't apply offset without ORDER
1331
1356
  coerce_tests! %r{using a custom table affects the wheres}
@@ -2120,6 +2145,17 @@ class FieldOrderedValuesTest < ActiveRecord::TestCase
2120
2145
  Book.where(author_id: nil, name: nil).delete_all
2121
2146
  Book.connection.add_index(:books, [:author_id, :name], unique: true)
2122
2147
  end
2148
+
2149
+ # Need to remove index as SQL Server considers NULLs on a unique-index to be equal unlike PostgreSQL/MySQL/SQLite.
2150
+ coerce_tests! :test_in_order_of_with_nil
2151
+ def test_in_order_of_with_nil_coerced
2152
+ Book.connection.remove_index(:books, column: [:author_id, :name])
2153
+
2154
+ original_test_in_order_of_with_nil
2155
+ ensure
2156
+ Book.where(author_id: nil, name: nil).delete_all
2157
+ Book.connection.add_index(:books, [:author_id, :name], unique: true)
2158
+ end
2123
2159
  end
2124
2160
 
2125
2161
  require "models/dashboard"
@@ -115,4 +115,22 @@ class MigrationTestSQLServer < ActiveRecord::TestCase
115
115
  refute_includes schemas, { "name" => "some schema" }
116
116
  end
117
117
  end
118
+
119
+ describe 'creating stored procedure' do
120
+ it 'stored procedure contains inserts are created successfully' do
121
+ sql = <<-SQL
122
+ CREATE OR ALTER PROCEDURE do_some_task
123
+ AS
124
+ IF NOT EXISTS(SELECT * FROM sys.objects WHERE type = 'U' AND name = 'SomeTableName')
125
+ BEGIN
126
+ CREATE TABLE SomeTableName (SomeNum int PRIMARY KEY CLUSTERED);
127
+ INSERT INTO SomeTableName(SomeNum) VALUES(1);
128
+ END
129
+ SQL
130
+
131
+ assert_nothing_raised { connection.execute(sql) }
132
+ ensure
133
+ connection.execute("DROP PROCEDURE IF EXISTS dbo.do_some_task;")
134
+ end
135
+ end
118
136
  end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "cases/helper_sqlserver"
4
+
5
+ class ViewTestSQLServer < ActiveRecord::TestCase
6
+ let(:connection) { ActiveRecord::Base.connection }
7
+
8
+ describe 'view with default values' do
9
+ before do
10
+ connection.drop_table :view_casing_table rescue nil
11
+ connection.create_table :view_casing_table, force: true do |t|
12
+ t.boolean :Default_Falsey, null: false, default: false
13
+ t.boolean :Default_Truthy, null: false, default: true
14
+ t.string :default_string, null: false, default: "abc"
15
+ end
16
+
17
+ connection.execute("DROP VIEW IF EXISTS view_casing_table_view;")
18
+ connection.execute <<-SQL
19
+ CREATE VIEW view_casing_table_view AS
20
+ SELECT id AS id,
21
+ default_falsey AS falsey,
22
+ default_truthy AS truthy,
23
+ default_string AS s
24
+ FROM view_casing_table
25
+ SQL
26
+ end
27
+
28
+ it "default values are correct when column casing used in tables and views are different" do
29
+ klass = Class.new(ActiveRecord::Base) do
30
+ self.table_name = "view_casing_table_view"
31
+ end
32
+
33
+ obj = klass.new
34
+ assert_equal false, obj.falsey
35
+ assert_equal true, obj.truthy
36
+ assert_equal "abc", obj.s
37
+ assert_equal 0, klass.count
38
+
39
+ obj.save!
40
+ assert_equal false, obj.falsey
41
+ assert_equal true, obj.truthy
42
+ assert_equal "abc", obj.s
43
+ assert_equal 1, klass.count
44
+ end
45
+ end
46
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activerecord-sqlserver-adapter
3
3
  version: !ruby/object:Gem::Version
4
- version: 7.0.3.0
4
+ version: 7.0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ken Collins
@@ -11,10 +11,11 @@ authors:
11
11
  - Shawn Balestracci
12
12
  - Joe Rafaniello
13
13
  - Tom Ward
14
- autorequire:
14
+ - Aidan Haran
15
+ autorequire:
15
16
  bindir: bin
16
17
  cert_chain: []
17
- date: 2023-06-12 00:00:00.000000000 Z
18
+ date: 2023-11-06 00:00:00.000000000 Z
18
19
  dependencies:
19
20
  - !ruby/object:Gem::Dependency
20
21
  name: activerecord
@@ -176,6 +177,7 @@ files:
176
177
  - test/cases/trigger_test_sqlserver.rb
177
178
  - test/cases/utils_test_sqlserver.rb
178
179
  - test/cases/uuid_test_sqlserver.rb
180
+ - test/cases/view_test_sqlserver.rb
179
181
  - test/config.yml
180
182
  - test/debug.rb
181
183
  - test/fixtures/1px.gif
@@ -229,9 +231,9 @@ licenses:
229
231
  - MIT
230
232
  metadata:
231
233
  bug_tracker_uri: https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/issues
232
- changelog_uri: https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/blob/v7.0.3.0/CHANGELOG.md
233
- source_code_uri: https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/tree/v7.0.3.0
234
- post_install_message:
234
+ changelog_uri: https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/blob/v7.0.5.0/CHANGELOG.md
235
+ source_code_uri: https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/tree/v7.0.5.0
236
+ post_install_message:
235
237
  rdoc_options: []
236
238
  require_paths:
237
239
  - lib
@@ -246,8 +248,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
246
248
  - !ruby/object:Gem::Version
247
249
  version: '0'
248
250
  requirements: []
249
- rubygems_version: 3.4.6
250
- signing_key:
251
+ rubygems_version: 3.4.7
252
+ signing_key:
251
253
  specification_version: 4
252
254
  summary: ActiveRecord SQL Server Adapter.
253
255
  test_files:
@@ -290,6 +292,7 @@ test_files:
290
292
  - test/cases/trigger_test_sqlserver.rb
291
293
  - test/cases/utils_test_sqlserver.rb
292
294
  - test/cases/uuid_test_sqlserver.rb
295
+ - test/cases/view_test_sqlserver.rb
293
296
  - test/config.yml
294
297
  - test/debug.rb
295
298
  - test/fixtures/1px.gif