activerecord-sqlserver-adapter 7.2.1 → 7.2.3

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: 73bbb76f7c1a620edbaf0aa6e69c5a8fcb9ba2f7c7c14716bb2663f776b8cb0d
4
- data.tar.gz: a6d9ac56dbcddd486bd0111da5db2e2d0cc6c2bbc3519041a73fffa5cfc3fddb
3
+ metadata.gz: 05376f4fb4ac7599dc2f61c926eed10a587bb21f34c68dc47de9025d2a031d6d
4
+ data.tar.gz: cadbc6f8881d3f8cc70bfa2892abb3a7de2f6805c932c960bc0212c8376fc904
5
5
  SHA512:
6
- metadata.gz: 921bd35d9de85b363190dee9b001373fbae60b0c1e99755ff4b172c9f51510d7353b49fb39d636b4acc015755067846bfed6ca4f984eb75d91def007679154da
7
- data.tar.gz: 384e76d966178e7c8bdc4f84cc03e3739bcfec1291fd42e57d8eb4804b7df37e4311f94ee659efa4d6b76a82ae833f8cd741f66bb667abf7a1e0c2f182107be9
6
+ metadata.gz: 4ed7c2b41c36c70c0efc188421238224c80093d83430756028d3108402302cb75fe03ca8d07990322fd4c4f58d9e0da51b1180cd310963c34ebd11a15bab65ab
7
+ data.tar.gz: 5a4e6f2a659c0fb23e0feadd04d8489f3ac9679767a94f4cf4e4da46de52f0cd70da617cada139ded171efbef2e342833b3967b8bdf2feb4eb48062eb8323d85
data/CHANGELOG.md CHANGED
@@ -1,3 +1,18 @@
1
+ ## v7.2.3
2
+
3
+ #### Fixed
4
+
5
+ - [#1262](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/1262) Fix distinct alias when multiple databases used.
6
+
7
+ ## v7.2.2
8
+
9
+ #### Fixed
10
+
11
+ - [#1244](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/1244) Allow INSERT statements with SELECT notation
12
+ - [#1247](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/1247) Fix queries with date and date-time placeholder conditions
13
+ - [#1249](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/1249) Binary basic columns should be limitable
14
+ - [#1255](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/1255) Fixed the ordering of optimizer hints in the generated SQL
15
+
1
16
  ## v7.2.1
2
17
 
3
18
  #### Fixed
data/VERSION CHANGED
@@ -1 +1 @@
1
- 7.2.1
1
+ 7.2.3
@@ -339,7 +339,7 @@ module ActiveRecord
339
339
  end
340
340
  end
341
341
 
342
- value = basic_attribute_type?(attr) ? attr : attr.value_for_database
342
+ value = active_model_attribute?(attr) ? attr.value_for_database : attr
343
343
 
344
344
  if value.is_a?(Numeric)
345
345
  value > 2_147_483_647 ? "bigint".freeze : "int".freeze
@@ -349,7 +349,7 @@ module ActiveRecord
349
349
  end
350
350
 
351
351
  def sp_executesql_sql_param(attr)
352
- return quote(attr) if basic_attribute_type?(attr)
352
+ return quote(attr) unless active_model_attribute?(attr)
353
353
 
354
354
  case value = attr.value_for_database
355
355
  when Type::Binary::Data, ActiveRecord::Type::SQLServer::Data
@@ -359,14 +359,8 @@ module ActiveRecord
359
359
  end
360
360
  end
361
361
 
362
- def basic_attribute_type?(type)
363
- type.is_a?(Symbol) ||
364
- type.is_a?(String) ||
365
- type.is_a?(Numeric) ||
366
- type.is_a?(Time) ||
367
- type.is_a?(TrueClass) ||
368
- type.is_a?(FalseClass) ||
369
- type.is_a?(NilClass)
362
+ def active_model_attribute?(type)
363
+ type.is_a?(::ActiveModel::Attribute)
370
364
  end
371
365
 
372
366
  def sp_executesql_sql(sql, types, params, name)
@@ -291,7 +291,7 @@ module ActiveRecord
291
291
  end
292
292
 
293
293
  def type_to_sql(type, limit: nil, precision: nil, scale: nil, **)
294
- type_limitable = %w(string integer float char nchar varchar nvarchar).include?(type.to_s)
294
+ type_limitable = %w(string integer float char nchar varchar nvarchar binary_basic).include?(type.to_s)
295
295
  limit = nil unless type_limitable
296
296
 
297
297
  case type.to_s
@@ -347,12 +347,16 @@ module ActiveRecord
347
347
 
348
348
  def columns_for_distinct(columns, orders)
349
349
  order_columns = orders.reject(&:blank?).map { |s|
350
- s = s.to_sql unless s.is_a?(String)
350
+ s = visitor.compile(s) unless s.is_a?(String)
351
351
  s.gsub(/\s+(?:ASC|DESC)\b/i, "")
352
352
  .gsub(/\s+NULLS\s+(?:FIRST|LAST)\b/i, "")
353
- }.reject(&:blank?).map.with_index { |column, i| "#{column} AS alias_#{i}" }
353
+ }
354
+ .reject(&:blank?)
355
+ .reject { |s| columns.include?(s) }
354
356
 
355
- (order_columns << super).join(", ")
357
+ order_columns_aliased = order_columns.map.with_index { |column, i| "#{column} AS alias_#{i}" }
358
+
359
+ (order_columns_aliased << super).join(", ")
356
360
  end
357
361
 
358
362
  def update_table_definition(table_name, base)
@@ -681,6 +685,7 @@ module ActiveRecord
681
685
  s.split(/INSERT INTO/i)[1]
682
686
  .split(/OUTPUT INSERTED/i)[0]
683
687
  .split(/(DEFAULT)?\s+VALUES/i)[0]
688
+ .split(/\bSELECT\b(?![^\[]*\])/i)[0]
684
689
  .match(/\s*([^(]*)/i)[0]
685
690
  elsif s.match?(/^\s*UPDATE\s+.*/i)
686
691
  s.match(/UPDATE\s+([^\(\s]+)\s*/i)[1]
@@ -134,26 +134,24 @@ module Arel
134
134
 
135
135
  def visit_Arel_Nodes_SelectStatement(o, collector)
136
136
  @select_statement = o
137
+ optimizer_hints = nil
137
138
  distinct_One_As_One_Is_So_Not_Fetch o
138
139
  if o.with
139
140
  collector = visit o.with, collector
140
141
  collector << " "
141
142
  end
142
- collector = o.cores.inject(collector) { |c, x|
143
- visit_Arel_Nodes_SelectCore(x, c)
144
- }
143
+ collector = o.cores.inject(collector) do |collect, core|
144
+ optimizer_hints = core.optimizer_hints if core.optimizer_hints
145
+ visit_Arel_Nodes_SelectCore(core, collect)
146
+ end
145
147
  collector = visit_Orders_And_Let_Fetch_Happen o, collector
146
148
  collector = visit_Make_Fetch_Happen o, collector
149
+ collector = maybe_visit optimizer_hints, collector
147
150
  collector
148
151
  ensure
149
152
  @select_statement = nil
150
153
  end
151
154
 
152
- def visit_Arel_Nodes_SelectCore(o, collector)
153
- collector = super
154
- maybe_visit o.optimizer_hints, collector
155
- end
156
-
157
155
  def visit_Arel_Nodes_OptimizerHints(o, collector)
158
156
  hints = o.expr.map { |v| sanitize_as_option_clause(v) }.join(", ")
159
157
  collector << "OPTION (#{hints})"
@@ -580,4 +580,27 @@ class AdapterTestSQLServer < ActiveRecord::TestCase
580
580
  end
581
581
  end
582
582
  end
583
+
584
+ describe "placeholder conditions" do
585
+ it 'using time placeholder' do
586
+ assert_equal Task.where("starting < ?", Time.now).count, 1
587
+ end
588
+
589
+ it 'using date placeholder' do
590
+ assert_equal Task.where("starting < ?", Date.today).count, 1
591
+ end
592
+
593
+ it 'using date-time placeholder' do
594
+ assert_equal Task.where("starting < ?", DateTime.current).count, 1
595
+ end
596
+ end
597
+
598
+ describe "distinct select query" do
599
+ it "generated SQL does not contain unnecessary alias projection" do
600
+ sqls = capture_sql do
601
+ Post.includes(:comments).joins(:comments).first
602
+ end
603
+ assert_no_match(/AS alias_0/, sqls.first)
604
+ end
605
+ end
583
606
  end
@@ -36,6 +36,15 @@ class OptimizerHitsTestSQLServer < ActiveRecord::TestCase
36
36
  end
37
37
  end
38
38
 
39
+
40
+ it "support order" do
41
+ assert_queries_match(%r{\ASELECT .+ FROM .+ ORDER .+ OPTION .+\z}) do
42
+ companies = Company.optimizer_hints("LABEL='FindCompanies'")
43
+ companies = companies.order(:id)
44
+ companies.to_a
45
+ end
46
+ end
47
+
39
48
  it "sanitize values" do
40
49
  assert_queries_match(%r{\ASELECT .+ FROM .+ OPTION \(HASH GROUP\)\z}) do
41
50
  companies = Company.optimizer_hints("OPTION (HASH GROUP)")
@@ -93,39 +93,41 @@ class SchemaDumperTestSQLServer < ActiveRecord::TestCase
93
93
  assert_line :binary_col, type: "binary"
94
94
 
95
95
  # Our type methods.
96
- _(columns["real_col"].sql_type).must_equal "real"
97
- _(columns["money_col"].sql_type).must_equal "money"
98
- _(columns["smalldatetime_col"].sql_type).must_equal "smalldatetime"
99
- _(columns["datetime2_col"].sql_type).must_equal "datetime2(7)"
100
- _(columns["datetimeoffset"].sql_type).must_equal "datetimeoffset(7)"
101
- _(columns["smallmoney_col"].sql_type).must_equal "smallmoney"
102
- _(columns["char_col"].sql_type).must_equal "char(1)"
103
- _(columns["varchar_col"].sql_type).must_equal "varchar(8000)"
104
- _(columns["text_basic_col"].sql_type).must_equal "text"
105
- _(columns["nchar_col"].sql_type).must_equal "nchar(1)"
106
- _(columns["ntext_col"].sql_type).must_equal "ntext"
107
- _(columns["binary_basic_col"].sql_type).must_equal "binary(1)"
108
- _(columns["varbinary_col"].sql_type).must_equal "varbinary(8000)"
109
- _(columns["uuid_col"].sql_type).must_equal "uniqueidentifier"
110
- _(columns["sstimestamp_col"].sql_type).must_equal "timestamp"
111
- _(columns["json_col"].sql_type).must_equal "nvarchar(max)"
112
-
113
- assert_line :real_col, type: "real"
114
- assert_line :money_col, type: "money", precision: 19, scale: 4
115
- assert_line :smalldatetime_col, type: "smalldatetime"
116
- assert_line :datetime2_col, type: "datetime", precision: 7
117
- assert_line :datetimeoffset, type: "datetimeoffset", precision: 7
118
- assert_line :smallmoney_col, type: "smallmoney", precision: 10, scale: 4
119
- assert_line :char_col, type: "char", limit: 1
120
- assert_line :varchar_col, type: "varchar"
121
- assert_line :text_basic_col, type: "text_basic"
122
- assert_line :nchar_col, type: "nchar", limit: 1
123
- assert_line :ntext_col, type: "ntext"
124
- assert_line :binary_basic_col, type: "binary_basic", limit: 1
125
- assert_line :varbinary_col, type: "varbinary"
126
- assert_line :uuid_col, type: "uuid"
127
- assert_line :sstimestamp_col, type: "ss_timestamp", null: false
128
- assert_line :json_col, type: "text"
96
+ _(columns["real_col"].sql_type).must_equal "real"
97
+ _(columns["money_col"].sql_type).must_equal "money"
98
+ _(columns["smalldatetime_col"].sql_type).must_equal "smalldatetime"
99
+ _(columns["datetime2_col"].sql_type).must_equal "datetime2(7)"
100
+ _(columns["datetimeoffset"].sql_type).must_equal "datetimeoffset(7)"
101
+ _(columns["smallmoney_col"].sql_type).must_equal "smallmoney"
102
+ _(columns["char_col"].sql_type).must_equal "char(1)"
103
+ _(columns["varchar_col"].sql_type).must_equal "varchar(8000)"
104
+ _(columns["text_basic_col"].sql_type).must_equal "text"
105
+ _(columns["nchar_col"].sql_type).must_equal "nchar(1)"
106
+ _(columns["ntext_col"].sql_type).must_equal "ntext"
107
+ _(columns["binary_basic_col"].sql_type).must_equal "binary(1)"
108
+ _(columns["binary_basic_16_col"].sql_type).must_equal "binary(16)"
109
+ _(columns["varbinary_col"].sql_type).must_equal "varbinary(8000)"
110
+ _(columns["uuid_col"].sql_type).must_equal "uniqueidentifier"
111
+ _(columns["sstimestamp_col"].sql_type).must_equal "timestamp"
112
+ _(columns["json_col"].sql_type).must_equal "nvarchar(max)"
113
+
114
+ assert_line :real_col, type: "real"
115
+ assert_line :money_col, type: "money", precision: 19, scale: 4
116
+ assert_line :smalldatetime_col, type: "smalldatetime"
117
+ assert_line :datetime2_col, type: "datetime", precision: 7
118
+ assert_line :datetimeoffset, type: "datetimeoffset", precision: 7
119
+ assert_line :smallmoney_col, type: "smallmoney", precision: 10, scale: 4
120
+ assert_line :char_col, type: "char", limit: 1
121
+ assert_line :varchar_col, type: "varchar"
122
+ assert_line :text_basic_col, type: "text_basic"
123
+ assert_line :nchar_col, type: "nchar", limit: 1
124
+ assert_line :ntext_col, type: "ntext"
125
+ assert_line :binary_basic_col, type: "binary_basic", limit: 1
126
+ assert_line :binary_basic_16_col, type: "binary_basic", limit: 16
127
+ assert_line :varbinary_col, type: "varbinary"
128
+ assert_line :uuid_col, type: "uuid"
129
+ assert_line :sstimestamp_col, type: "ss_timestamp", null: false
130
+ assert_line :json_col, type: "text"
129
131
  end
130
132
 
131
133
  it "dump column collation" do
@@ -96,6 +96,10 @@ class SchemaTestSQLServer < ActiveRecord::TestCase
96
96
  it do
97
97
  assert_equal "[test].[aliens]", connection.send(:get_raw_table_name, "EXEC sp_executesql N'INSERT INTO [test].[aliens] ([name]) OUTPUT INSERTED.[id] VALUES (@0)', N'@0 varchar(255)', @0 = 'Trisolarans'")
98
98
  end
99
+
100
+ it do
101
+ assert_equal "[with].[select notation]", connection.send(:get_raw_table_name, "INSERT INTO [with].[select notation] SELECT * FROM [table_name]")
102
+ end
99
103
  end
100
104
  end
101
105
  end
@@ -33,6 +33,7 @@ ActiveRecord::Schema.define do
33
33
  t.nchar :nchar_col
34
34
  t.ntext :ntext_col
35
35
  t.binary_basic :binary_basic_col
36
+ t.binary_basic :binary_basic_16_col, limit: 16
36
37
  t.varbinary :varbinary_col
37
38
  t.uuid :uuid_col
38
39
  t.ss_timestamp :sstimestamp_col
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.2.1
4
+ version: 7.2.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ken Collins
@@ -15,7 +15,7 @@ authors:
15
15
  autorequire:
16
16
  bindir: bin
17
17
  cert_chain: []
18
- date: 2024-10-02 00:00:00.000000000 Z
18
+ date: 2024-12-08 00:00:00.000000000 Z
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  name: activerecord
@@ -239,8 +239,8 @@ licenses:
239
239
  - MIT
240
240
  metadata:
241
241
  bug_tracker_uri: https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/issues
242
- changelog_uri: https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/blob/v7.2.1/CHANGELOG.md
243
- source_code_uri: https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/tree/v7.2.1
242
+ changelog_uri: https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/blob/v7.2.3/CHANGELOG.md
243
+ source_code_uri: https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/tree/v7.2.3
244
244
  post_install_message:
245
245
  rdoc_options: []
246
246
  require_paths:
@@ -256,7 +256,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
256
256
  - !ruby/object:Gem::Version
257
257
  version: '0'
258
258
  requirements: []
259
- rubygems_version: 3.5.17
259
+ rubygems_version: 3.5.21
260
260
  signing_key:
261
261
  specification_version: 4
262
262
  summary: ActiveRecord SQL Server Adapter.