activerecord 6.0.3.4 → 6.1.2

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.

Files changed (245) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +891 -695
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +3 -3
  5. data/lib/active_record.rb +7 -14
  6. data/lib/active_record/aggregations.rb +5 -5
  7. data/lib/active_record/association_relation.rb +30 -12
  8. data/lib/active_record/associations.rb +118 -11
  9. data/lib/active_record/associations/alias_tracker.rb +19 -15
  10. data/lib/active_record/associations/association.rb +44 -28
  11. data/lib/active_record/associations/association_scope.rb +19 -15
  12. data/lib/active_record/associations/belongs_to_association.rb +22 -8
  13. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +8 -3
  14. data/lib/active_record/associations/builder/association.rb +32 -5
  15. data/lib/active_record/associations/builder/belongs_to.rb +10 -7
  16. data/lib/active_record/associations/builder/collection_association.rb +5 -4
  17. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +0 -1
  18. data/lib/active_record/associations/builder/has_many.rb +6 -2
  19. data/lib/active_record/associations/builder/has_one.rb +11 -14
  20. data/lib/active_record/associations/builder/singular_association.rb +1 -1
  21. data/lib/active_record/associations/collection_association.rb +19 -6
  22. data/lib/active_record/associations/collection_proxy.rb +13 -5
  23. data/lib/active_record/associations/foreign_association.rb +13 -0
  24. data/lib/active_record/associations/has_many_association.rb +24 -2
  25. data/lib/active_record/associations/has_many_through_association.rb +10 -4
  26. data/lib/active_record/associations/has_one_association.rb +15 -1
  27. data/lib/active_record/associations/join_dependency.rb +72 -50
  28. data/lib/active_record/associations/join_dependency/join_association.rb +39 -16
  29. data/lib/active_record/associations/join_dependency/join_part.rb +3 -3
  30. data/lib/active_record/associations/preloader.rb +11 -5
  31. data/lib/active_record/associations/preloader/association.rb +51 -25
  32. data/lib/active_record/associations/preloader/through_association.rb +2 -2
  33. data/lib/active_record/associations/singular_association.rb +1 -1
  34. data/lib/active_record/associations/through_association.rb +1 -1
  35. data/lib/active_record/attribute_assignment.rb +10 -8
  36. data/lib/active_record/attribute_methods.rb +64 -54
  37. data/lib/active_record/attribute_methods/before_type_cast.rb +13 -9
  38. data/lib/active_record/attribute_methods/dirty.rb +1 -11
  39. data/lib/active_record/attribute_methods/primary_key.rb +6 -2
  40. data/lib/active_record/attribute_methods/query.rb +3 -6
  41. data/lib/active_record/attribute_methods/read.rb +8 -11
  42. data/lib/active_record/attribute_methods/serialization.rb +11 -5
  43. data/lib/active_record/attribute_methods/time_zone_conversion.rb +12 -13
  44. data/lib/active_record/attribute_methods/write.rb +12 -20
  45. data/lib/active_record/attributes.rb +33 -8
  46. data/lib/active_record/autosave_association.rb +57 -40
  47. data/lib/active_record/base.rb +2 -14
  48. data/lib/active_record/callbacks.rb +152 -22
  49. data/lib/active_record/coders/yaml_column.rb +1 -1
  50. data/lib/active_record/connection_adapters.rb +50 -0
  51. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +191 -134
  52. data/lib/active_record/connection_adapters/abstract/database_limits.rb +2 -44
  53. data/lib/active_record/connection_adapters/abstract/database_statements.rb +65 -22
  54. data/lib/active_record/connection_adapters/abstract/query_cache.rb +3 -8
  55. data/lib/active_record/connection_adapters/abstract/quoting.rb +34 -34
  56. data/lib/active_record/connection_adapters/abstract/savepoints.rb +3 -3
  57. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +153 -116
  58. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +116 -27
  59. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +3 -3
  60. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +228 -83
  61. data/lib/active_record/connection_adapters/abstract/transaction.rb +80 -32
  62. data/lib/active_record/connection_adapters/abstract_adapter.rb +54 -72
  63. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +133 -96
  64. data/lib/active_record/connection_adapters/column.rb +15 -1
  65. data/lib/active_record/connection_adapters/deduplicable.rb +29 -0
  66. data/lib/active_record/connection_adapters/legacy_pool_manager.rb +31 -0
  67. data/lib/active_record/connection_adapters/mysql/database_statements.rb +23 -25
  68. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +1 -1
  69. data/lib/active_record/connection_adapters/mysql/quoting.rb +1 -1
  70. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +32 -6
  71. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +8 -0
  72. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +5 -2
  73. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +11 -7
  74. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +10 -1
  75. data/lib/active_record/connection_adapters/mysql2_adapter.rb +31 -12
  76. data/lib/active_record/connection_adapters/pool_config.rb +73 -0
  77. data/lib/active_record/connection_adapters/pool_manager.rb +43 -0
  78. data/lib/active_record/connection_adapters/postgresql/column.rb +24 -1
  79. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +13 -54
  80. data/lib/active_record/connection_adapters/postgresql/oid.rb +2 -0
  81. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +3 -5
  82. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +2 -2
  83. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +10 -2
  84. data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +49 -0
  85. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +2 -2
  86. data/lib/active_record/connection_adapters/postgresql/oid/macaddr.rb +25 -0
  87. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +2 -2
  88. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +24 -5
  89. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +11 -1
  90. data/lib/active_record/connection_adapters/postgresql/quoting.rb +4 -4
  91. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +1 -1
  92. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +5 -1
  93. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +61 -29
  94. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +8 -0
  95. data/lib/active_record/connection_adapters/postgresql_adapter.rb +73 -58
  96. data/lib/active_record/connection_adapters/schema_cache.rb +98 -15
  97. data/lib/active_record/connection_adapters/sql_type_metadata.rb +10 -0
  98. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +31 -6
  99. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +1 -1
  100. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +5 -1
  101. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +37 -4
  102. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +49 -50
  103. data/lib/active_record/connection_handling.rb +218 -71
  104. data/lib/active_record/core.rb +245 -61
  105. data/lib/active_record/database_configurations.rb +124 -85
  106. data/lib/active_record/database_configurations/connection_url_resolver.rb +98 -0
  107. data/lib/active_record/database_configurations/database_config.rb +52 -9
  108. data/lib/active_record/database_configurations/hash_config.rb +54 -8
  109. data/lib/active_record/database_configurations/url_config.rb +15 -40
  110. data/lib/active_record/delegated_type.rb +209 -0
  111. data/lib/active_record/destroy_association_async_job.rb +36 -0
  112. data/lib/active_record/enum.rb +82 -38
  113. data/lib/active_record/errors.rb +47 -12
  114. data/lib/active_record/explain.rb +9 -4
  115. data/lib/active_record/explain_subscriber.rb +1 -1
  116. data/lib/active_record/fixture_set/file.rb +10 -17
  117. data/lib/active_record/fixture_set/model_metadata.rb +1 -2
  118. data/lib/active_record/fixture_set/render_context.rb +1 -1
  119. data/lib/active_record/fixture_set/table_row.rb +2 -2
  120. data/lib/active_record/fixtures.rb +58 -9
  121. data/lib/active_record/gem_version.rb +3 -3
  122. data/lib/active_record/inheritance.rb +40 -18
  123. data/lib/active_record/insert_all.rb +35 -6
  124. data/lib/active_record/integration.rb +3 -5
  125. data/lib/active_record/internal_metadata.rb +16 -7
  126. data/lib/active_record/legacy_yaml_adapter.rb +7 -3
  127. data/lib/active_record/locking/optimistic.rb +33 -17
  128. data/lib/active_record/locking/pessimistic.rb +6 -2
  129. data/lib/active_record/log_subscriber.rb +27 -8
  130. data/lib/active_record/middleware/database_selector.rb +4 -1
  131. data/lib/active_record/middleware/database_selector/resolver.rb +5 -0
  132. data/lib/active_record/middleware/database_selector/resolver/session.rb +3 -0
  133. data/lib/active_record/migration.rb +113 -83
  134. data/lib/active_record/migration/command_recorder.rb +47 -27
  135. data/lib/active_record/migration/compatibility.rb +68 -17
  136. data/lib/active_record/model_schema.rb +117 -13
  137. data/lib/active_record/nested_attributes.rb +2 -3
  138. data/lib/active_record/no_touching.rb +1 -1
  139. data/lib/active_record/persistence.rb +50 -45
  140. data/lib/active_record/query_cache.rb +15 -5
  141. data/lib/active_record/querying.rb +11 -6
  142. data/lib/active_record/railtie.rb +64 -44
  143. data/lib/active_record/railties/console_sandbox.rb +2 -4
  144. data/lib/active_record/railties/databases.rake +276 -99
  145. data/lib/active_record/readonly_attributes.rb +4 -0
  146. data/lib/active_record/reflection.rb +71 -57
  147. data/lib/active_record/relation.rb +96 -67
  148. data/lib/active_record/relation/batches.rb +38 -31
  149. data/lib/active_record/relation/batches/batch_enumerator.rb +25 -9
  150. data/lib/active_record/relation/calculations.rb +101 -44
  151. data/lib/active_record/relation/delegation.rb +2 -1
  152. data/lib/active_record/relation/finder_methods.rb +45 -15
  153. data/lib/active_record/relation/from_clause.rb +1 -1
  154. data/lib/active_record/relation/merger.rb +27 -25
  155. data/lib/active_record/relation/predicate_builder.rb +59 -38
  156. data/lib/active_record/relation/predicate_builder/array_handler.rb +8 -9
  157. data/lib/active_record/relation/predicate_builder/association_query_value.rb +4 -5
  158. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +10 -6
  159. data/lib/active_record/relation/predicate_builder/relation_handler.rb +1 -1
  160. data/lib/active_record/relation/query_methods.rb +333 -195
  161. data/lib/active_record/relation/record_fetch_warning.rb +3 -3
  162. data/lib/active_record/relation/spawn_methods.rb +8 -7
  163. data/lib/active_record/relation/where_clause.rb +104 -57
  164. data/lib/active_record/result.rb +41 -33
  165. data/lib/active_record/runtime_registry.rb +2 -2
  166. data/lib/active_record/sanitization.rb +6 -17
  167. data/lib/active_record/schema_dumper.rb +34 -4
  168. data/lib/active_record/schema_migration.rb +2 -8
  169. data/lib/active_record/scoping/named.rb +6 -17
  170. data/lib/active_record/secure_token.rb +16 -8
  171. data/lib/active_record/serialization.rb +5 -3
  172. data/lib/active_record/signed_id.rb +116 -0
  173. data/lib/active_record/statement_cache.rb +20 -4
  174. data/lib/active_record/store.rb +2 -2
  175. data/lib/active_record/suppressor.rb +2 -2
  176. data/lib/active_record/table_metadata.rb +42 -51
  177. data/lib/active_record/tasks/database_tasks.rb +140 -113
  178. data/lib/active_record/tasks/mysql_database_tasks.rb +34 -35
  179. data/lib/active_record/tasks/postgresql_database_tasks.rb +24 -26
  180. data/lib/active_record/tasks/sqlite_database_tasks.rb +13 -9
  181. data/lib/active_record/test_databases.rb +5 -4
  182. data/lib/active_record/test_fixtures.rb +37 -16
  183. data/lib/active_record/timestamp.rb +4 -6
  184. data/lib/active_record/touch_later.rb +21 -21
  185. data/lib/active_record/transactions.rb +19 -66
  186. data/lib/active_record/type.rb +8 -1
  187. data/lib/active_record/type/serialized.rb +6 -2
  188. data/lib/active_record/type/time.rb +10 -0
  189. data/lib/active_record/type_caster/connection.rb +0 -1
  190. data/lib/active_record/type_caster/map.rb +8 -5
  191. data/lib/active_record/validations.rb +1 -0
  192. data/lib/active_record/validations/numericality.rb +35 -0
  193. data/lib/active_record/validations/uniqueness.rb +24 -4
  194. data/lib/arel.rb +5 -13
  195. data/lib/arel/attributes/attribute.rb +4 -0
  196. data/lib/arel/collectors/bind.rb +5 -0
  197. data/lib/arel/collectors/composite.rb +8 -0
  198. data/lib/arel/collectors/sql_string.rb +7 -0
  199. data/lib/arel/collectors/substitute_binds.rb +7 -0
  200. data/lib/arel/nodes.rb +3 -1
  201. data/lib/arel/nodes/binary.rb +82 -8
  202. data/lib/arel/nodes/bind_param.rb +8 -0
  203. data/lib/arel/nodes/casted.rb +21 -9
  204. data/lib/arel/nodes/equality.rb +6 -9
  205. data/lib/arel/nodes/grouping.rb +3 -0
  206. data/lib/arel/nodes/homogeneous_in.rb +72 -0
  207. data/lib/arel/nodes/in.rb +8 -1
  208. data/lib/arel/nodes/infix_operation.rb +13 -1
  209. data/lib/arel/nodes/join_source.rb +1 -1
  210. data/lib/arel/nodes/node.rb +7 -6
  211. data/lib/arel/nodes/ordering.rb +27 -0
  212. data/lib/arel/nodes/sql_literal.rb +3 -0
  213. data/lib/arel/nodes/table_alias.rb +7 -3
  214. data/lib/arel/nodes/unary.rb +0 -1
  215. data/lib/arel/predications.rb +12 -18
  216. data/lib/arel/select_manager.rb +1 -2
  217. data/lib/arel/table.rb +13 -5
  218. data/lib/arel/visitors.rb +0 -7
  219. data/lib/arel/visitors/dot.rb +14 -2
  220. data/lib/arel/visitors/mysql.rb +11 -1
  221. data/lib/arel/visitors/postgresql.rb +15 -4
  222. data/lib/arel/visitors/to_sql.rb +89 -78
  223. data/lib/rails/generators/active_record/migration.rb +6 -1
  224. data/lib/rails/generators/active_record/migration/migration_generator.rb +1 -0
  225. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +2 -0
  226. data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +3 -3
  227. data/lib/rails/generators/active_record/model/model_generator.rb +39 -2
  228. data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +7 -0
  229. metadata +25 -26
  230. data/lib/active_record/advisory_lock_base.rb +0 -18
  231. data/lib/active_record/attribute_decorators.rb +0 -88
  232. data/lib/active_record/connection_adapters/connection_specification.rb +0 -296
  233. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +0 -29
  234. data/lib/active_record/define_callbacks.rb +0 -22
  235. data/lib/active_record/railties/collection_cache_association_loading.rb +0 -34
  236. data/lib/active_record/relation/predicate_builder/base_handler.rb +0 -18
  237. data/lib/active_record/relation/where_clause_factory.rb +0 -33
  238. data/lib/arel/attributes.rb +0 -22
  239. data/lib/arel/visitors/depth_first.rb +0 -203
  240. data/lib/arel/visitors/ibm_db.rb +0 -34
  241. data/lib/arel/visitors/informix.rb +0 -62
  242. data/lib/arel/visitors/mssql.rb +0 -156
  243. data/lib/arel/visitors/oracle.rb +0 -158
  244. data/lib/arel/visitors/oracle12.rb +0 -65
  245. data/lib/arel/visitors/where_sql.rb +0 -22
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "active_support/deprecation"
4
-
5
3
  module ActiveRecord
6
4
  module ConnectionAdapters # :nodoc:
7
5
  module DatabaseLimits
@@ -14,18 +12,6 @@ module ActiveRecord
14
12
  max_identifier_length
15
13
  end
16
14
 
17
- # Returns the maximum length of a column name.
18
- def column_name_length
19
- max_identifier_length
20
- end
21
- deprecate :column_name_length
22
-
23
- # Returns the maximum length of a table name.
24
- def table_name_length
25
- max_identifier_length
26
- end
27
- deprecate :table_name_length
28
-
29
15
  # Returns the maximum allowed length for an index name. This
30
16
  # limit is enforced by \Rails and is less than or equal to
31
17
  # #index_name_length. The gap between
@@ -34,47 +20,19 @@ module ActiveRecord
34
20
  def allowed_index_name_length
35
21
  index_name_length
36
22
  end
23
+ deprecate :allowed_index_name_length
37
24
 
38
25
  # Returns the maximum length of an index name.
39
26
  def index_name_length
40
27
  max_identifier_length
41
28
  end
42
29
 
43
- # Returns the maximum number of columns per table.
44
- def columns_per_table
45
- 1024
46
- end
47
- deprecate :columns_per_table
48
-
49
- # Returns the maximum number of indexes per table.
50
- def indexes_per_table
51
- 16
52
- end
53
- deprecate :indexes_per_table
54
-
55
- # Returns the maximum number of columns in a multicolumn index.
56
- def columns_per_multicolumn_index
57
- 16
58
- end
59
- deprecate :columns_per_multicolumn_index
60
-
61
30
  # Returns the maximum number of elements in an IN (x,y,z) clause.
62
31
  # +nil+ means no limit.
63
32
  def in_clause_length
64
33
  nil
65
34
  end
66
-
67
- # Returns the maximum length of an SQL query.
68
- def sql_query_length
69
- 1048575
70
- end
71
- deprecate :sql_query_length
72
-
73
- # Returns maximum number of joins in a single query.
74
- def joins_per_query
75
- 256
76
- end
77
- deprecate :joins_per_query
35
+ deprecate :in_clause_length
78
36
 
79
37
  private
80
38
  def bind_params_length
@@ -14,29 +14,32 @@ module ActiveRecord
14
14
  sql
15
15
  end
16
16
 
17
- def to_sql_and_binds(arel_or_sql_string, binds = []) # :nodoc:
17
+ def to_sql_and_binds(arel_or_sql_string, binds = [], preparable = nil) # :nodoc:
18
18
  if arel_or_sql_string.respond_to?(:ast)
19
19
  unless binds.empty?
20
20
  raise "Passing bind parameters with an arel AST is forbidden. " \
21
21
  "The values must be stored on the AST directly"
22
22
  end
23
23
 
24
+ collector = collector()
25
+
24
26
  if prepared_statements
27
+ collector.preparable = true
25
28
  sql, binds = visitor.compile(arel_or_sql_string.ast, collector)
26
29
 
27
30
  if binds.length > bind_params_length
28
31
  unprepared_statement do
29
- sql, binds = to_sql_and_binds(arel_or_sql_string)
30
- visitor.preparable = false
32
+ return to_sql_and_binds(arel_or_sql_string)
31
33
  end
32
34
  end
35
+ preparable = collector.preparable
33
36
  else
34
37
  sql = visitor.compile(arel_or_sql_string.ast, collector)
35
38
  end
36
- [sql.freeze, binds]
39
+ [sql.freeze, binds, preparable]
37
40
  else
38
- visitor.preparable = false if prepared_statements
39
- [arel_or_sql_string.dup.freeze, binds]
41
+ arel_or_sql_string = arel_or_sql_string.dup.freeze unless arel_or_sql_string.frozen?
42
+ [arel_or_sql_string, binds, preparable]
40
43
  end
41
44
  end
42
45
  private :to_sql_and_binds
@@ -58,17 +61,15 @@ module ActiveRecord
58
61
  # Returns an ActiveRecord::Result instance.
59
62
  def select_all(arel, name = nil, binds = [], preparable: nil)
60
63
  arel = arel_from_relation(arel)
61
- sql, binds = to_sql_and_binds(arel, binds)
62
-
63
- if preparable.nil?
64
- preparable = prepared_statements ? visitor.preparable : false
65
- end
64
+ sql, binds, preparable = to_sql_and_binds(arel, binds, preparable)
66
65
 
67
66
  if prepared_statements && preparable
68
67
  select_prepared(sql, name, binds)
69
68
  else
70
69
  select(sql, name, binds)
71
70
  end
71
+ rescue ::RangeError
72
+ ActiveRecord::Result.new([], [])
72
73
  end
73
74
 
74
75
  # Returns a record hash with the column names as keys and column values
@@ -153,6 +154,10 @@ module ActiveRecord
153
154
  exec_query(sql, name)
154
155
  end
155
156
 
157
+ def explain(arel, binds = []) # :nodoc:
158
+ raise NotImplementedError
159
+ end
160
+
156
161
  # Executes an INSERT query and returns the new record's ID
157
162
  #
158
163
  # +id_value+ will be returned unless the value is +nil+, in
@@ -186,6 +191,8 @@ module ActiveRecord
186
191
  end
187
192
 
188
193
  def truncate_tables(*table_names) # :nodoc:
194
+ table_names -= [schema_migration.table_name, InternalMetadata.table_name]
195
+
189
196
  return if table_names.empty?
190
197
 
191
198
  with_multi_statements do
@@ -201,15 +208,30 @@ module ActiveRecord
201
208
  #
202
209
  # == Nested transactions support
203
210
  #
211
+ # #transaction calls can be nested. By default, this makes all database
212
+ # statements in the nested transaction block become part of the parent
213
+ # transaction. For example, the following behavior may be surprising:
214
+ #
215
+ # ActiveRecord::Base.transaction do
216
+ # Post.create(title: 'first')
217
+ # ActiveRecord::Base.transaction do
218
+ # Post.create(title: 'second')
219
+ # raise ActiveRecord::Rollback
220
+ # end
221
+ # end
222
+ #
223
+ # This creates both "first" and "second" posts. Reason is the
224
+ # ActiveRecord::Rollback exception in the nested block does not issue a
225
+ # ROLLBACK. Since these exceptions are captured in transaction blocks,
226
+ # the parent block does not see it and the real transaction is committed.
227
+ #
204
228
  # Most databases don't support true nested transactions. At the time of
205
229
  # writing, the only database that supports true nested transactions that
206
230
  # we're aware of, is MS-SQL.
207
231
  #
208
232
  # In order to get around this problem, #transaction will emulate the effect
209
233
  # of nested transactions, by using savepoints:
210
- # https://dev.mysql.com/doc/refman/5.7/en/savepoint.html
211
- # Savepoints are supported by MySQL and PostgreSQL. SQLite3 version >= '3.6.8'
212
- # supports savepoints.
234
+ # https://dev.mysql.com/doc/refman/en/savepoint.html.
213
235
  #
214
236
  # It is safe to call this method if a database transaction is already open,
215
237
  # i.e. if #transaction is called within another #transaction block. In case
@@ -221,6 +243,24 @@ module ActiveRecord
221
243
  # - However, if +:requires_new+ is set, the block will be wrapped in a
222
244
  # database savepoint acting as a sub-transaction.
223
245
  #
246
+ # In order to get a ROLLBACK for the nested transaction you may ask for a
247
+ # real sub-transaction by passing <tt>requires_new: true</tt>.
248
+ # If anything goes wrong, the database rolls back to the beginning of
249
+ # the sub-transaction without rolling back the parent transaction.
250
+ # If we add it to the previous example:
251
+ #
252
+ # ActiveRecord::Base.transaction do
253
+ # Post.create(title: 'first')
254
+ # ActiveRecord::Base.transaction(requires_new: true) do
255
+ # Post.create(title: 'second')
256
+ # raise ActiveRecord::Rollback
257
+ # end
258
+ # end
259
+ #
260
+ # only post with title "first" is created.
261
+ #
262
+ # See ActiveRecord::Transactions to learn more.
263
+ #
224
264
  # === Caveats
225
265
  #
226
266
  # MySQL doesn't support DDL transactions. If you perform a DDL operation,
@@ -260,7 +300,7 @@ module ActiveRecord
260
300
  # semantics of these different levels:
261
301
  #
262
302
  # * https://www.postgresql.org/docs/current/static/transaction-iso.html
263
- # * https://dev.mysql.com/doc/refman/5.7/en/set-transaction.html
303
+ # * https://dev.mysql.com/doc/refman/en/set-transaction.html
264
304
  #
265
305
  # An ActiveRecord::TransactionIsolationError will be raised if:
266
306
  #
@@ -289,6 +329,13 @@ module ActiveRecord
289
329
  :commit_transaction, :rollback_transaction, :materialize_transactions,
290
330
  :disable_lazy_transactions!, :enable_lazy_transactions!, to: :transaction_manager
291
331
 
332
+ def mark_transaction_written_if_write(sql) # :nodoc:
333
+ transaction = current_transaction
334
+ if transaction.open?
335
+ transaction.written ||= write_query?(sql)
336
+ end
337
+ end
338
+
292
339
  def transaction_open?
293
340
  current_transaction.open?
294
341
  end
@@ -299,12 +346,8 @@ module ActiveRecord
299
346
 
300
347
  # Register a record with the current transaction so that its after_commit and after_rollback callbacks
301
348
  # can be called.
302
- def add_transaction_record(record)
303
- current_transaction.add_record(record)
304
- end
305
-
306
- def transaction_state
307
- current_transaction.state
349
+ def add_transaction_record(record, ensure_finalize = true)
350
+ current_transaction.add_record(record, ensure_finalize)
308
351
  end
309
352
 
310
353
  # Begins the transaction (and turns off auto-committing).
@@ -351,7 +394,7 @@ module ActiveRecord
351
394
  end
352
395
 
353
396
  # Inserts the given fixture into the table. Overridden in adapters that require
354
- # something beyond a simple insert (eg. Oracle).
397
+ # something beyond a simple insert (e.g. Oracle).
355
398
  # Most of adapters should implement `insert_fixtures_set` that leverages bulk SQL insert.
356
399
  # We keep this method to provide fallback
357
400
  # for databases like sqlite that do not support bulk inserts.
@@ -7,7 +7,7 @@ module ActiveRecord
7
7
  module QueryCache
8
8
  class << self
9
9
  def included(base) #:nodoc:
10
- dirties_query_cache base, :insert, :update, :delete, :truncate, :truncate_tables,
10
+ dirties_query_cache base, :create, :insert, :update, :delete, :truncate, :truncate_tables,
11
11
  :rollback_to_savepoint, :rollback_db_transaction, :exec_insert_all
12
12
 
13
13
  base.set_callback :checkout, :after, :configure_query_cache!
@@ -18,7 +18,7 @@ module ActiveRecord
18
18
  method_names.each do |method_name|
19
19
  base.class_eval <<-end_code, __FILE__, __LINE__ + 1
20
20
  def #{method_name}(*)
21
- ActiveRecord::Base.clear_query_caches_for_current_thread if @query_cache_enabled
21
+ ActiveRecord::Base.clear_query_caches_for_current_thread
22
22
  super
23
23
  end
24
24
  end_code
@@ -96,11 +96,7 @@ module ActiveRecord
96
96
  def select_all(arel, name = nil, binds = [], preparable: nil)
97
97
  if @query_cache_enabled && !locked?(arel)
98
98
  arel = arel_from_relation(arel)
99
- sql, binds = to_sql_and_binds(arel, binds)
100
-
101
- if preparable.nil?
102
- preparable = prepared_statements ? visitor.preparable : false
103
- end
99
+ sql, binds, preparable = to_sql_and_binds(arel, binds, preparable)
104
100
 
105
101
  cache_sql(sql, name, binds) { super(sql, name, binds, preparable: preparable) }
106
102
  else
@@ -133,7 +129,6 @@ module ActiveRecord
133
129
  binds: binds,
134
130
  type_casted_binds: -> { type_casted_binds(binds) },
135
131
  name: name,
136
- connection_id: object_id,
137
132
  connection: self,
138
133
  cached: true
139
134
  }
@@ -9,10 +9,12 @@ module ActiveRecord
9
9
  # Quotes the column value to help prevent
10
10
  # {SQL injection attacks}[https://en.wikipedia.org/wiki/SQL_injection].
11
11
  def quote(value)
12
- value = id_value_for_database(value) if value.is_a?(Base)
13
-
14
- if value.respond_to?(:value_for_database)
15
- value = value.value_for_database
12
+ if value.is_a?(Base)
13
+ ActiveSupport::Deprecation.warn(<<~MSG)
14
+ Passing an Active Record object to `quote` directly is deprecated
15
+ and will be no longer quoted as id value in Rails 6.2.
16
+ MSG
17
+ value = value.id_for_database
16
18
  end
17
19
 
18
20
  _quote(value)
@@ -22,16 +24,23 @@ module ActiveRecord
22
24
  # SQLite does not understand dates, so this method will convert a Date
23
25
  # to a String.
24
26
  def type_cast(value, column = nil)
25
- value = id_value_for_database(value) if value.is_a?(Base)
27
+ if value.is_a?(Base)
28
+ ActiveSupport::Deprecation.warn(<<~MSG)
29
+ Passing an Active Record object to `type_cast` directly is deprecated
30
+ and will be no longer type casted as id value in Rails 6.2.
31
+ MSG
32
+ value = value.id_for_database
33
+ end
26
34
 
27
35
  if column
28
- value = type_cast_from_column(column, value)
36
+ ActiveSupport::Deprecation.warn(<<~MSG)
37
+ Passing a column to `type_cast` is deprecated and will be removed in Rails 6.2.
38
+ MSG
39
+ type = lookup_cast_type_from_column(column)
40
+ value = type.serialize(value)
29
41
  end
30
42
 
31
43
  _type_cast(value)
32
- rescue TypeError
33
- to_type = column ? " to #{column.type}" : ""
34
- raise TypeError, "can't cast #{value.class}#{to_type}"
35
44
  end
36
45
 
37
46
  # If you are having to call this function, you are likely doing something
@@ -43,16 +52,6 @@ module ActiveRecord
43
52
  # represent the type doesn't sufficiently reflect the differences
44
53
  # (varchar vs binary) for example. The type used to get this primitive
45
54
  # should have been provided before reaching the connection adapter.
46
- def type_cast_from_column(column, value) # :nodoc:
47
- if column
48
- type = lookup_cast_type_from_column(column)
49
- type.serialize(value)
50
- else
51
- value
52
- end
53
- end
54
-
55
- # See docs for #type_cast_from_column
56
55
  def lookup_cast_type_from_column(column) # :nodoc:
57
56
  lookup_cast_type(column.sql_type)
58
57
  end
@@ -114,16 +113,16 @@ module ActiveRecord
114
113
  # if the value is a Time responding to usec.
115
114
  def quoted_date(value)
116
115
  if value.acts_like?(:time)
117
- zone_conversion_method = ActiveRecord::Base.default_timezone == :utc ? :getutc : :getlocal
118
-
119
- if value.respond_to?(zone_conversion_method)
120
- value = value.send(zone_conversion_method)
116
+ if ActiveRecord::Base.default_timezone == :utc
117
+ value = value.getutc if value.respond_to?(:getutc) && !value.utc?
118
+ else
119
+ value = value.getlocal if value.respond_to?(:getlocal)
121
120
  end
122
121
  end
123
122
 
124
123
  result = value.to_s(:db)
125
124
  if value.respond_to?(:usec) && value.usec > 0
126
- "#{result}.#{sprintf("%06d", value.usec)}"
125
+ result << "." << sprintf("%06d", value.usec)
127
126
  else
128
127
  result
129
128
  end
@@ -162,7 +161,7 @@ module ActiveRecord
162
161
  # table_name.column_name | function(one or no argument)
163
162
  ((?:\w+\.)?\w+) | \w+\((?:|\g<2>)\)
164
163
  )
165
- (?:\s+AS\s+\w+)?
164
+ (?:(?:\s+AS)?\s+\w+)?
166
165
  )
167
166
  (?:\s*,\s*\g<1>)*
168
167
  \z
@@ -197,10 +196,17 @@ module ActiveRecord
197
196
 
198
197
  private
199
198
  def type_casted_binds(binds)
200
- if binds.first.is_a?(Array)
199
+ case binds.first
200
+ when Array
201
201
  binds.map { |column, value| type_cast(value, column) }
202
202
  else
203
- binds.map { |attr| type_cast(attr.value_for_database) }
203
+ binds.map do |value|
204
+ if ActiveModel::Attribute === value
205
+ type_cast(value.value_for_database)
206
+ else
207
+ type_cast(value)
208
+ end
209
+ end
204
210
  end
205
211
  end
206
212
 
@@ -208,12 +214,6 @@ module ActiveRecord
208
214
  type_map.lookup(sql_type)
209
215
  end
210
216
 
211
- def id_value_for_database(value)
212
- if primary_key = value.class.primary_key
213
- value.instance_variable_get(:@attributes)[primary_key].value_for_database
214
- end
215
- end
216
-
217
217
  def _quote(value)
218
218
  case value
219
219
  when String, Symbol, ActiveSupport::Multibyte::Chars
@@ -243,7 +243,7 @@ module ActiveRecord
243
243
  when nil, Numeric, String then value
244
244
  when Type::Time::Value then quoted_time(value)
245
245
  when Date, Time then quoted_date(value)
246
- else raise TypeError
246
+ else raise TypeError, "can't cast #{value.class.name}"
247
247
  end
248
248
  end
249
249
  end
@@ -8,15 +8,15 @@ module ActiveRecord
8
8
  end
9
9
 
10
10
  def create_savepoint(name = current_savepoint_name)
11
- execute("SAVEPOINT #{name}")
11
+ execute("SAVEPOINT #{name}", "TRANSACTION")
12
12
  end
13
13
 
14
14
  def exec_rollback_to_savepoint(name = current_savepoint_name)
15
- execute("ROLLBACK TO SAVEPOINT #{name}")
15
+ execute("ROLLBACK TO SAVEPOINT #{name}", "TRANSACTION")
16
16
  end
17
17
 
18
18
  def release_savepoint(name = current_savepoint_name)
19
- execute("RELEASE SAVEPOINT #{name}")
19
+ execute("RELEASE SAVEPOINT #{name}", "TRANSACTION")
20
20
  end
21
21
  end
22
22
  end