activerecord 6.1.2.1 → 6.1.3

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of activerecord might be problematic. Click here for more details.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 61210a9bf3705c22919bfa2c07869d5d6f2d634e9483344e861b30b73e77201a
4
- data.tar.gz: 0e74625e0dfc674cbcac3a750d628e3ebb0df0e21b4277d72bc1699c403f6e8e
3
+ metadata.gz: 6cdd6094f92ff2d3eef67e5ab7f2a8e2a327fbdffaa1f20182fb5bdb7c803685
4
+ data.tar.gz: 197e68aa68f0946e9fcd55c7f0c2f41c237777c893b20a3a00affddbcaa1f367
5
5
  SHA512:
6
- metadata.gz: 8482b26acd2e28d94d9eeb53e0bcb899e387318c2ef122c8edc9a9243ee3aec0f0d47f8fc3397aea738df4f9c033eff28e813fc8cb12577a4c195594414275f2
7
- data.tar.gz: 255438e998bfe3c7a6364c15795416b8d116b6a2babc27718090d5dcc99cbb2f31d63a5cce5bceaffb6a32608e707fda33ba62e29c44cc1ce573617edaed22c8
6
+ metadata.gz: 4b9b18c89048afe658359cd16b4c13c3a1eb87c8dacae3beeaf99338e2e441f64fd96bf569697cd581ea35f3068f33ee7872f733570f621a774c92b04253dc5e
7
+ data.tar.gz: 4d47d251881e21878596707b1d759f40b8b83a02e759cb1af79d8293498251a6ff3f5b11e4ecdc004ac282c6fc84437bcc60469bf0ed0a880aae1e820e20d4a1
data/CHANGELOG.md CHANGED
@@ -1,3 +1,58 @@
1
+ ## Rails 6.1.3 (February 17, 2021) ##
2
+
3
+ * Fix the MySQL adapter to always set the right collation and charset
4
+ to the connection session.
5
+
6
+ *Rafael Mendonça França*
7
+
8
+ * Fix MySQL adapter handling of time objects when prepared statements
9
+ are enabled.
10
+
11
+ *Rafael Mendonça França*
12
+
13
+ * Fix scoping in enum fields using conditions that would generate
14
+ an `IN` clause.
15
+
16
+ *Ryuta Kamizono*
17
+
18
+ * Skip optimised #exist? query when #include? is called on a relation
19
+ with a having clause
20
+
21
+ Relations that have aliased select values AND a having clause that
22
+ references an aliased select value would generate an error when
23
+ #include? was called, due to an optimisation that would generate
24
+ call #exists? on the relation instead, which effectively alters
25
+ the select values of the query (and thus removes the aliased select
26
+ values), but leaves the having clause intact. Because the having
27
+ clause is then referencing an aliased column that is no longer
28
+ present in the simplified query, an ActiveRecord::InvalidStatement
29
+ error was raised.
30
+
31
+ An sample query affected by this problem:
32
+
33
+ ```ruby
34
+ Author.select('COUNT(*) as total_posts', 'authors.*')
35
+ .joins(:posts)
36
+ .group(:id)
37
+ .having('total_posts > 2')
38
+ .include?(Author.first)
39
+ ```
40
+
41
+ This change adds an addition check to the condition that skips the
42
+ simplified #exists? query, which simply checks for the presence of
43
+ a having clause.
44
+
45
+ Fixes #41417
46
+
47
+ *Michael Smart*
48
+
49
+ * Increment postgres prepared statement counter before making a prepared statement, so if the statement is aborted
50
+ without Rails knowledge (e.g., if app gets kill -9d during long-running query or due to Rack::Timeout), app won't end
51
+ up in perpetual crash state for being inconsistent with Postgres.
52
+
53
+ *wbharding*, *Martin Tepper*
54
+
55
+
1
56
  ## Rails 6.1.2.1 (February 10, 2021) ##
2
57
 
3
58
  * Fix possible DoS vector in PostgreSQL money type
@@ -395,7 +395,7 @@ module ActiveRecord
395
395
 
396
396
  # Inserts the given fixture into the table. Overridden in adapters that require
397
397
  # something beyond a simple insert (e.g. Oracle).
398
- # Most of adapters should implement `insert_fixtures_set` that leverages bulk SQL insert.
398
+ # Most of adapters should implement +insert_fixtures_set+ that leverages bulk SQL insert.
399
399
  # We keep this method to provide fallback
400
400
  # for databases like sqlite that do not support bulk inserts.
401
401
  def insert_fixture(fixture, table_name)
@@ -116,10 +116,10 @@ module ActiveRecord
116
116
  # Returns true if the connection is a replica.
117
117
  #
118
118
  # If the application is using legacy handling, returns
119
- # true if `connection_handler.prevent_writes` is set.
119
+ # true if +connection_handler.prevent_writes+ is set.
120
120
  #
121
121
  # If the application is using the new connection handling
122
- # will return true based on `current_preventing_writes`.
122
+ # will return true based on +current_preventing_writes+.
123
123
  def preventing_writes?
124
124
  return true if replica?
125
125
  return ActiveRecord::Base.connection_handler.prevent_writes if ActiveRecord::Base.legacy_connection_handling
@@ -751,11 +751,6 @@ module ActiveRecord
751
751
  wait_timeout = 2147483 unless wait_timeout.is_a?(Integer)
752
752
  variables["wait_timeout"] = wait_timeout
753
753
 
754
- # Set the collation of the connection character set.
755
- if @config[:collation]
756
- variables["collation_connection"] = @config[:collation]
757
- end
758
-
759
754
  defaults = [":default", :default].to_set
760
755
 
761
756
  # Make MySQL reject illegal values rather than truncating or blanking them, see
@@ -775,6 +770,15 @@ module ActiveRecord
775
770
  end
776
771
  sql_mode_assignment = "@@SESSION.sql_mode = #{sql_mode}, " if sql_mode
777
772
 
773
+ # NAMES does not have an equals sign, see
774
+ # https://dev.mysql.com/doc/refman/en/set-names.html
775
+ # (trailing comma because variable_assignments will always have content)
776
+ if @config[:encoding]
777
+ encoding = +"NAMES #{@config[:encoding]}"
778
+ encoding << " COLLATE #{@config[:collation]}" if @config[:collation]
779
+ encoding << ", "
780
+ end
781
+
778
782
  # Gather up all of the SET variables...
779
783
  variable_assignments = variables.map do |k, v|
780
784
  if defaults.include?(v)
@@ -786,7 +790,7 @@ module ActiveRecord
786
790
  end.compact.join(", ")
787
791
 
788
792
  # ...and send them all in one query
789
- execute("SET #{sql_mode_assignment} #{variable_assignments}", "SCHEMA")
793
+ execute("SET #{encoding} #{sql_mode_assignment} #{variable_assignments}", "SCHEMA")
790
794
  end
791
795
 
792
796
  def column_definitions(table_name) # :nodoc:
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "active_support/time_with_zone"
4
+
3
5
  module ActiveRecord
4
6
  module ConnectionAdapters
5
7
  module MySQL
@@ -69,10 +71,23 @@ module ActiveRecord
69
71
  private_constant :COLUMN_NAME, :COLUMN_NAME_WITH_ORDER
70
72
 
71
73
  private
74
+ # Override +_type_cast+ we pass to mysql2 Date and Time objects instead
75
+ # of Strings since mysql2 is able to handle those classes more efficiently.
72
76
  def _type_cast(value)
73
77
  case value
74
- when Date, Time then value
75
- else super
78
+ when ActiveSupport::TimeWithZone
79
+ # We need to check explicitly for ActiveSupport::TimeWithZone because
80
+ # we need to transform it to Time objects but we don't want to
81
+ # transform Time objects to themselves.
82
+ if ActiveRecord::Base.default_timezone == :utc
83
+ value.getutc
84
+ else
85
+ value.getlocal
86
+ end
87
+ when Date, Time
88
+ value
89
+ else
90
+ super
76
91
  end
77
92
  end
78
93
  end
@@ -227,11 +227,7 @@ module ActiveRecord
227
227
  end
228
228
 
229
229
  def next_key
230
- "a#{@counter + 1}"
231
- end
232
-
233
- def []=(sql, key)
234
- super.tap { @counter += 1 }
230
+ "a#{@counter += 1}"
235
231
  end
236
232
 
237
233
  private
@@ -114,7 +114,7 @@ module ActiveRecord
114
114
  #
115
115
  # If only a role is passed, Active Record will look up the connection
116
116
  # based on the requested role. If a non-established role is requested
117
- # an `ActiveRecord::ConnectionNotEstablished` error will be raised:
117
+ # an +ActiveRecord::ConnectionNotEstablished+ error will be raised:
118
118
  #
119
119
  # ActiveRecord::Base.connected_to(role: :writing) do
120
120
  # Dog.create! # creates dog using dog writing connection
@@ -125,7 +125,7 @@ module ActiveRecord
125
125
  # end
126
126
  #
127
127
  # When swapping to a shard, the role must be passed as well. If a non-existent
128
- # shard is passed, an `ActiveRecord::ConnectionNotEstablished` error will be
128
+ # shard is passed, an +ActiveRecord::ConnectionNotEstablished+ error will be
129
129
  # raised.
130
130
  #
131
131
  # When a shard and role is passed, Active Record will first lookup the role,
@@ -178,11 +178,11 @@ module ActiveRecord
178
178
  end
179
179
  end
180
180
 
181
- # Connects a role and/or shard to the provided connection names. Optionally `prevent_writes`
182
- # can be passed to block writes on a connection. `reading` will automatically set
183
- # `prevent_writes` to true.
181
+ # Connects a role and/or shard to the provided connection names. Optionally +prevent_writes+
182
+ # can be passed to block writes on a connection. +reading+ will automatically set
183
+ # +prevent_writes+ to true.
184
184
  #
185
- # `connected_to_many` is an alternative to deeply nested `connected_to` blocks.
185
+ # +connected_to_many+ is an alternative to deeply nested +connected_to+ blocks.
186
186
  #
187
187
  # Usage:
188
188
  #
@@ -216,7 +216,7 @@ module ActiveRecord
216
216
  # being used. For example, when booting a console in readonly mode.
217
217
  #
218
218
  # It is not recommended to use this method in a request since it
219
- # does not yield to a block like `connected_to`.
219
+ # does not yield to a block like +connected_to+.
220
220
  def connecting_to(role: default_role, shard: default_shard, prevent_writes: false)
221
221
  if legacy_connection_handling
222
222
  raise NotImplementedError, "`connecting_to` is not available with `legacy_connection_handling`."
@@ -230,13 +230,13 @@ module ActiveRecord
230
230
  # Prevent writing to the database regardless of role.
231
231
  #
232
232
  # In some cases you may want to prevent writes to the database
233
- # even if you are on a database that can write. `while_preventing_writes`
233
+ # even if you are on a database that can write. +while_preventing_writes+
234
234
  # will prevent writes to the database for the duration of the block.
235
235
  #
236
236
  # This method does not provide the same protection as a readonly
237
237
  # user and is meant to be a safeguard against accidental writes.
238
238
  #
239
- # See `READ_QUERY` for the queries that are blocked by this
239
+ # See +READ_QUERY+ for the queries that are blocked by this
240
240
  # method.
241
241
  def while_preventing_writes(enabled = true, &block)
242
242
  if legacy_connection_handling
@@ -181,7 +181,7 @@ module ActiveRecord
181
181
  # end
182
182
  # end
183
183
  #
184
- # If you preload your test database with all fixture data (probably by running `bin/rails db:fixtures:load`)
184
+ # If you preload your test database with all fixture data (probably by running <tt>bin/rails db:fixtures:load</tt>)
185
185
  # and use transactional tests, then you may omit all fixtures declarations in your test cases since
186
186
  # all the data's already there and every case rolls back its changes.
187
187
  #
@@ -9,8 +9,8 @@ module ActiveRecord
9
9
  module VERSION
10
10
  MAJOR = 6
11
11
  MINOR = 1
12
- TINY = 2
13
- PRE = "1"
12
+ TINY = 3
13
+ PRE = nil
14
14
 
15
15
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
16
16
  end
@@ -320,7 +320,7 @@ module ActiveRecord
320
320
  # +table_name+. Passing a hash containing <tt>:from</tt> and <tt>:to</tt>
321
321
  # as +default_or_changes+ will make this change reversible in the migration.
322
322
  # * <tt>change_column_null(table_name, column_name, null, default = nil)</tt>:
323
- # Sets or removes a +NOT NULL+ constraint on +column_name+. The +null+ flag
323
+ # Sets or removes a <tt>NOT NULL</tt> constraint on +column_name+. The +null+ flag
324
324
  # indicates whether the value can be +NULL+. See
325
325
  # ActiveRecord::ConnectionAdapters::SchemaStatements#change_column_null for
326
326
  # details.
@@ -122,9 +122,9 @@ module ActiveRecord
122
122
  # :singleton-method: immutable_strings_by_default=
123
123
  # :call-seq: immutable_strings_by_default=(bool)
124
124
  #
125
- # Determines whether columns should infer their type as `:string` or
126
- # `:immutable_string`. This setting does not affect the behavior of
127
- # `attribute :foo, :string`. Defaults to false.
125
+ # Determines whether columns should infer their type as +:string+ or
126
+ # +:immutable_string+. This setting does not affect the behavior of
127
+ # <tt>attribute :foo, :string</tt>. Defaults to false.
128
128
 
129
129
  included do
130
130
  mattr_accessor :primary_key_prefix_type, instance_writer: false
@@ -316,7 +316,7 @@ module ActiveRecord
316
316
  # self.ignored_columns = [:category]
317
317
  # end
318
318
  #
319
- # The schema still contains `category`, but now the model omits it, so any meta-driven code or
319
+ # The schema still contains "category", but now the model omits it, so any meta-driven code or
320
320
  # schema caching will not attempt to use the column:
321
321
  #
322
322
  # Project.columns_hash["category"] => nil
@@ -683,8 +683,7 @@ module ActiveRecord
683
683
  end
684
684
 
685
685
  def scope_for_create
686
- hash = where_values_hash
687
- hash.delete(klass.inheritance_column) if klass.finder_needs_type_condition?
686
+ hash = where_clause.to_h(klass.table_name, equality_only: true)
688
687
  create_with_value.each { |k, v| hash[k.to_s] = v } unless create_with_value.empty?
689
688
  hash
690
689
  end
@@ -326,7 +326,7 @@ module ActiveRecord
326
326
  # compared to the records in memory. If the relation is unloaded, an
327
327
  # efficient existence query is performed, as in #exists?.
328
328
  def include?(record)
329
- if loaded? || offset_value || limit_value
329
+ if loaded? || offset_value || limit_value || having_clause.any?
330
330
  records.include?(record)
331
331
  else
332
332
  record.is_a?(klass) && exists?(record.id)
@@ -103,7 +103,9 @@ module ActiveRecord
103
103
 
104
104
  klass ||= AssociationQueryValue
105
105
  queries = klass.new(associated_table, value).queries.map! do |query|
106
- expand_from_hash(query)
106
+ # If the query produced is identical to attributes don't go any deeper.
107
+ # Prevents stack level too deep errors when association and foreign_key are identical.
108
+ query == attributes ? self[key, value] : expand_from_hash(query)
107
109
  end
108
110
 
109
111
  grouping_queries(queries)
@@ -58,8 +58,8 @@ module ActiveRecord
58
58
  end
59
59
  end
60
60
 
61
- def to_h(table_name = nil)
62
- equalities(predicates).each_with_object({}) do |node, hash|
61
+ def to_h(table_name = nil, equality_only: false)
62
+ equalities(predicates, equality_only).each_with_object({}) do |node, hash|
63
63
  next if table_name&.!= node.left.relation.name
64
64
  name = node.left.name.to_s
65
65
  value = extract_node_value(node.right)
@@ -134,14 +134,14 @@ module ActiveRecord
134
134
  attr_node
135
135
  end
136
136
 
137
- def equalities(predicates)
137
+ def equalities(predicates, equality_only)
138
138
  equalities = []
139
139
 
140
140
  predicates.each do |node|
141
- if equality_node?(node)
141
+ if equality_only ? Arel::Nodes::Equality === node : equality_node?(node)
142
142
  equalities << node
143
143
  elsif node.is_a?(Arel::Nodes::And)
144
- equalities.concat equalities(node.children)
144
+ equalities.concat equalities(node.children, equality_only)
145
145
  end
146
146
  end
147
147
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activerecord
3
3
  version: !ruby/object:Gem::Version
4
- version: 6.1.2.1
4
+ version: 6.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Heinemeier Hansson
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-02-10 00:00:00.000000000 Z
11
+ date: 2021-02-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -16,28 +16,28 @@ dependencies:
16
16
  requirements:
17
17
  - - '='
18
18
  - !ruby/object:Gem::Version
19
- version: 6.1.2.1
19
+ version: 6.1.3
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - '='
25
25
  - !ruby/object:Gem::Version
26
- version: 6.1.2.1
26
+ version: 6.1.3
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: activemodel
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - '='
32
32
  - !ruby/object:Gem::Version
33
- version: 6.1.2.1
33
+ version: 6.1.3
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - '='
39
39
  - !ruby/object:Gem::Version
40
- version: 6.1.2.1
40
+ version: 6.1.3
41
41
  description: Databases on Rails. Build a persistent domain model by mapping database
42
42
  tables to Ruby classes. Strong conventions for associations, validations, aggregations,
43
43
  migrations, and testing come baked-in.
@@ -390,11 +390,11 @@ licenses:
390
390
  - MIT
391
391
  metadata:
392
392
  bug_tracker_uri: https://github.com/rails/rails/issues
393
- changelog_uri: https://github.com/rails/rails/blob/v6.1.2.1/activerecord/CHANGELOG.md
394
- documentation_uri: https://api.rubyonrails.org/v6.1.2.1/
393
+ changelog_uri: https://github.com/rails/rails/blob/v6.1.3/activerecord/CHANGELOG.md
394
+ documentation_uri: https://api.rubyonrails.org/v6.1.3/
395
395
  mailing_list_uri: https://discuss.rubyonrails.org/c/rubyonrails-talk
396
- source_code_uri: https://github.com/rails/rails/tree/v6.1.2.1/activerecord
397
- post_install_message:
396
+ source_code_uri: https://github.com/rails/rails/tree/v6.1.3/activerecord
397
+ post_install_message:
398
398
  rdoc_options:
399
399
  - "--main"
400
400
  - README.rdoc
@@ -411,8 +411,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
411
411
  - !ruby/object:Gem::Version
412
412
  version: '0'
413
413
  requirements: []
414
- rubygems_version: 3.0.3
415
- signing_key:
414
+ rubygems_version: 3.2.3
415
+ signing_key:
416
416
  specification_version: 4
417
417
  summary: Object-relational mapper framework (part of Rails).
418
418
  test_files: []