activerecord 6.0.0 → 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.

Files changed (270) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +1045 -575
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +4 -4
  5. data/lib/active_record.rb +7 -13
  6. data/lib/active_record/aggregations.rb +5 -6
  7. data/lib/active_record/association_relation.rb +30 -10
  8. data/lib/active_record/associations.rb +120 -13
  9. data/lib/active_record/associations/alias_tracker.rb +19 -16
  10. data/lib/active_record/associations/association.rb +49 -29
  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 -3
  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 +25 -8
  22. data/lib/active_record/associations/collection_proxy.rb +14 -7
  23. data/lib/active_record/associations/foreign_association.rb +13 -0
  24. data/lib/active_record/associations/has_many_association.rb +24 -3
  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 +77 -42
  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 +13 -8
  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 -9
  36. data/lib/active_record/attribute_methods.rb +64 -54
  37. data/lib/active_record/attribute_methods/before_type_cast.rb +13 -10
  38. data/lib/active_record/attribute_methods/dirty.rb +3 -13
  39. data/lib/active_record/attribute_methods/primary_key.rb +6 -4
  40. data/lib/active_record/attribute_methods/query.rb +3 -6
  41. data/lib/active_record/attribute_methods/read.rb +8 -12
  42. data/lib/active_record/attribute_methods/serialization.rb +11 -6
  43. data/lib/active_record/attribute_methods/time_zone_conversion.rb +12 -15
  44. data/lib/active_record/attribute_methods/write.rb +12 -21
  45. data/lib/active_record/attributes.rb +33 -9
  46. data/lib/active_record/autosave_association.rb +63 -44
  47. data/lib/active_record/base.rb +2 -14
  48. data/lib/active_record/callbacks.rb +153 -24
  49. data/lib/active_record/coders/yaml_column.rb +1 -2
  50. data/lib/active_record/connection_adapters.rb +50 -0
  51. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +202 -138
  52. data/lib/active_record/connection_adapters/abstract/database_limits.rb +2 -44
  53. data/lib/active_record/connection_adapters/abstract/database_statements.rb +87 -38
  54. data/lib/active_record/connection_adapters/abstract/query_cache.rb +5 -10
  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 +152 -116
  58. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +141 -52
  59. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +3 -3
  60. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +267 -105
  61. data/lib/active_record/connection_adapters/abstract/transaction.rb +82 -35
  62. data/lib/active_record/connection_adapters/abstract_adapter.rb +74 -77
  63. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +149 -115
  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/column.rb +1 -1
  68. data/lib/active_record/connection_adapters/mysql/database_statements.rb +30 -36
  69. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +1 -2
  70. data/lib/active_record/connection_adapters/mysql/quoting.rb +18 -3
  71. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +32 -7
  72. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +8 -0
  73. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +5 -2
  74. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +17 -13
  75. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +10 -1
  76. data/lib/active_record/connection_adapters/mysql2_adapter.rb +31 -13
  77. data/lib/active_record/connection_adapters/pool_config.rb +73 -0
  78. data/lib/active_record/connection_adapters/pool_manager.rb +43 -0
  79. data/lib/active_record/connection_adapters/postgresql/column.rb +24 -1
  80. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +21 -56
  81. data/lib/active_record/connection_adapters/postgresql/oid.rb +2 -0
  82. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +0 -1
  83. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +3 -5
  84. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +2 -2
  85. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +10 -2
  86. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +0 -1
  87. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +0 -1
  88. data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +49 -0
  89. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +2 -3
  90. data/lib/active_record/connection_adapters/postgresql/oid/macaddr.rb +25 -0
  91. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +2 -2
  92. data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +1 -1
  93. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +2 -3
  94. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +24 -6
  95. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +1 -1
  96. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +11 -2
  97. data/lib/active_record/connection_adapters/postgresql/quoting.rb +4 -4
  98. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +2 -2
  99. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +7 -3
  100. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +1 -1
  101. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +0 -1
  102. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +72 -54
  103. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +8 -0
  104. data/lib/active_record/connection_adapters/postgresql/utils.rb +0 -1
  105. data/lib/active_record/connection_adapters/postgresql_adapter.rb +83 -65
  106. data/lib/active_record/connection_adapters/schema_cache.rb +98 -15
  107. data/lib/active_record/connection_adapters/sql_type_metadata.rb +10 -0
  108. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +38 -12
  109. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +1 -2
  110. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +5 -1
  111. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +38 -5
  112. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +61 -57
  113. data/lib/active_record/connection_adapters/statement_pool.rb +0 -1
  114. data/lib/active_record/connection_handling.rb +219 -81
  115. data/lib/active_record/core.rb +253 -67
  116. data/lib/active_record/counter_cache.rb +4 -1
  117. data/lib/active_record/database_configurations.rb +124 -85
  118. data/lib/active_record/database_configurations/connection_url_resolver.rb +98 -0
  119. data/lib/active_record/database_configurations/database_config.rb +52 -9
  120. data/lib/active_record/database_configurations/hash_config.rb +54 -8
  121. data/lib/active_record/database_configurations/url_config.rb +15 -41
  122. data/lib/active_record/delegated_type.rb +209 -0
  123. data/lib/active_record/destroy_association_async_job.rb +36 -0
  124. data/lib/active_record/dynamic_matchers.rb +2 -3
  125. data/lib/active_record/enum.rb +82 -38
  126. data/lib/active_record/errors.rb +47 -12
  127. data/lib/active_record/explain.rb +9 -5
  128. data/lib/active_record/explain_subscriber.rb +1 -1
  129. data/lib/active_record/fixture_set/file.rb +10 -17
  130. data/lib/active_record/fixture_set/model_metadata.rb +1 -2
  131. data/lib/active_record/fixture_set/render_context.rb +1 -1
  132. data/lib/active_record/fixture_set/table_row.rb +2 -3
  133. data/lib/active_record/fixture_set/table_rows.rb +0 -1
  134. data/lib/active_record/fixtures.rb +58 -12
  135. data/lib/active_record/gem_version.rb +2 -2
  136. data/lib/active_record/inheritance.rb +40 -21
  137. data/lib/active_record/insert_all.rb +39 -10
  138. data/lib/active_record/integration.rb +3 -5
  139. data/lib/active_record/internal_metadata.rb +16 -7
  140. data/lib/active_record/legacy_yaml_adapter.rb +7 -3
  141. data/lib/active_record/locking/optimistic.rb +33 -18
  142. data/lib/active_record/locking/pessimistic.rb +6 -2
  143. data/lib/active_record/log_subscriber.rb +28 -9
  144. data/lib/active_record/middleware/database_selector.rb +4 -2
  145. data/lib/active_record/middleware/database_selector/resolver.rb +14 -14
  146. data/lib/active_record/middleware/database_selector/resolver/session.rb +3 -0
  147. data/lib/active_record/migration.rb +115 -85
  148. data/lib/active_record/migration/command_recorder.rb +53 -45
  149. data/lib/active_record/migration/compatibility.rb +71 -20
  150. data/lib/active_record/migration/join_table.rb +0 -1
  151. data/lib/active_record/model_schema.rb +120 -15
  152. data/lib/active_record/nested_attributes.rb +2 -5
  153. data/lib/active_record/no_touching.rb +1 -1
  154. data/lib/active_record/null_relation.rb +0 -1
  155. data/lib/active_record/persistence.rb +50 -46
  156. data/lib/active_record/query_cache.rb +15 -5
  157. data/lib/active_record/querying.rb +12 -7
  158. data/lib/active_record/railtie.rb +65 -45
  159. data/lib/active_record/railties/console_sandbox.rb +2 -4
  160. data/lib/active_record/railties/databases.rake +277 -97
  161. data/lib/active_record/readonly_attributes.rb +4 -0
  162. data/lib/active_record/reflection.rb +77 -63
  163. data/lib/active_record/relation.rb +107 -67
  164. data/lib/active_record/relation/batches.rb +38 -32
  165. data/lib/active_record/relation/batches/batch_enumerator.rb +25 -9
  166. data/lib/active_record/relation/calculations.rb +102 -45
  167. data/lib/active_record/relation/delegation.rb +9 -7
  168. data/lib/active_record/relation/finder_methods.rb +55 -17
  169. data/lib/active_record/relation/from_clause.rb +5 -1
  170. data/lib/active_record/relation/merger.rb +27 -26
  171. data/lib/active_record/relation/predicate_builder.rb +59 -40
  172. data/lib/active_record/relation/predicate_builder/array_handler.rb +8 -9
  173. data/lib/active_record/relation/predicate_builder/association_query_value.rb +4 -5
  174. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +10 -6
  175. data/lib/active_record/relation/predicate_builder/relation_handler.rb +1 -1
  176. data/lib/active_record/relation/query_methods.rb +343 -180
  177. data/lib/active_record/relation/record_fetch_warning.rb +3 -3
  178. data/lib/active_record/relation/spawn_methods.rb +8 -8
  179. data/lib/active_record/relation/where_clause.rb +107 -61
  180. data/lib/active_record/result.rb +41 -34
  181. data/lib/active_record/runtime_registry.rb +2 -2
  182. data/lib/active_record/sanitization.rb +6 -17
  183. data/lib/active_record/schema_dumper.rb +34 -4
  184. data/lib/active_record/schema_migration.rb +2 -8
  185. data/lib/active_record/scoping.rb +0 -1
  186. data/lib/active_record/scoping/default.rb +0 -1
  187. data/lib/active_record/scoping/named.rb +7 -18
  188. data/lib/active_record/secure_token.rb +16 -8
  189. data/lib/active_record/serialization.rb +5 -3
  190. data/lib/active_record/signed_id.rb +116 -0
  191. data/lib/active_record/statement_cache.rb +20 -4
  192. data/lib/active_record/store.rb +3 -3
  193. data/lib/active_record/suppressor.rb +2 -2
  194. data/lib/active_record/table_metadata.rb +42 -36
  195. data/lib/active_record/tasks/database_tasks.rb +140 -113
  196. data/lib/active_record/tasks/mysql_database_tasks.rb +34 -36
  197. data/lib/active_record/tasks/postgresql_database_tasks.rb +24 -27
  198. data/lib/active_record/tasks/sqlite_database_tasks.rb +13 -10
  199. data/lib/active_record/test_databases.rb +5 -4
  200. data/lib/active_record/test_fixtures.rb +38 -16
  201. data/lib/active_record/timestamp.rb +4 -7
  202. data/lib/active_record/touch_later.rb +20 -21
  203. data/lib/active_record/transactions.rb +26 -73
  204. data/lib/active_record/type.rb +8 -2
  205. data/lib/active_record/type/adapter_specific_registry.rb +2 -5
  206. data/lib/active_record/type/hash_lookup_type_map.rb +0 -1
  207. data/lib/active_record/type/serialized.rb +6 -3
  208. data/lib/active_record/type/time.rb +10 -0
  209. data/lib/active_record/type/type_map.rb +0 -1
  210. data/lib/active_record/type/unsigned_integer.rb +0 -1
  211. data/lib/active_record/type_caster/connection.rb +0 -1
  212. data/lib/active_record/type_caster/map.rb +8 -5
  213. data/lib/active_record/validations.rb +3 -3
  214. data/lib/active_record/validations/associated.rb +1 -2
  215. data/lib/active_record/validations/numericality.rb +35 -0
  216. data/lib/active_record/validations/uniqueness.rb +24 -4
  217. data/lib/arel.rb +15 -12
  218. data/lib/arel/attributes/attribute.rb +4 -0
  219. data/lib/arel/collectors/bind.rb +5 -0
  220. data/lib/arel/collectors/composite.rb +8 -0
  221. data/lib/arel/collectors/sql_string.rb +7 -0
  222. data/lib/arel/collectors/substitute_binds.rb +7 -0
  223. data/lib/arel/nodes.rb +3 -1
  224. data/lib/arel/nodes/binary.rb +82 -8
  225. data/lib/arel/nodes/bind_param.rb +8 -0
  226. data/lib/arel/nodes/casted.rb +21 -9
  227. data/lib/arel/nodes/equality.rb +6 -9
  228. data/lib/arel/nodes/grouping.rb +3 -0
  229. data/lib/arel/nodes/homogeneous_in.rb +72 -0
  230. data/lib/arel/nodes/in.rb +8 -1
  231. data/lib/arel/nodes/infix_operation.rb +13 -1
  232. data/lib/arel/nodes/join_source.rb +1 -1
  233. data/lib/arel/nodes/node.rb +7 -6
  234. data/lib/arel/nodes/ordering.rb +27 -0
  235. data/lib/arel/nodes/sql_literal.rb +3 -0
  236. data/lib/arel/nodes/table_alias.rb +7 -3
  237. data/lib/arel/nodes/unary.rb +0 -1
  238. data/lib/arel/predications.rb +17 -24
  239. data/lib/arel/select_manager.rb +1 -2
  240. data/lib/arel/table.rb +13 -5
  241. data/lib/arel/visitors.rb +0 -7
  242. data/lib/arel/visitors/dot.rb +14 -3
  243. data/lib/arel/visitors/mysql.rb +11 -1
  244. data/lib/arel/visitors/postgresql.rb +15 -5
  245. data/lib/arel/visitors/sqlite.rb +0 -1
  246. data/lib/arel/visitors/to_sql.rb +89 -79
  247. data/lib/arel/visitors/visitor.rb +0 -1
  248. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +0 -1
  249. data/lib/rails/generators/active_record/migration.rb +6 -2
  250. data/lib/rails/generators/active_record/migration/migration_generator.rb +1 -0
  251. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +2 -0
  252. data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +4 -4
  253. data/lib/rails/generators/active_record/model/model_generator.rb +38 -2
  254. data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +7 -0
  255. metadata +30 -27
  256. data/lib/active_record/attribute_decorators.rb +0 -90
  257. data/lib/active_record/connection_adapters/connection_specification.rb +0 -297
  258. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +0 -29
  259. data/lib/active_record/define_callbacks.rb +0 -22
  260. data/lib/active_record/railties/collection_cache_association_loading.rb +0 -34
  261. data/lib/active_record/relation/predicate_builder/base_handler.rb +0 -18
  262. data/lib/active_record/relation/where_clause_factory.rb +0 -33
  263. data/lib/arel/attributes.rb +0 -22
  264. data/lib/arel/visitors/depth_first.rb +0 -204
  265. data/lib/arel/visitors/ibm_db.rb +0 -34
  266. data/lib/arel/visitors/informix.rb +0 -62
  267. data/lib/arel/visitors/mssql.rb +0 -157
  268. data/lib/arel/visitors/oracle.rb +0 -159
  269. data/lib/arel/visitors/oracle12.rb +0 -66
  270. data/lib/arel/visitors/where_sql.rb +0 -23
@@ -5,10 +5,11 @@ module ActiveRecord
5
5
  class TransactionState
6
6
  def initialize(state = nil)
7
7
  @state = state
8
- @children = []
8
+ @children = nil
9
9
  end
10
10
 
11
11
  def add_child(state)
12
+ @children ||= []
12
13
  @children << state
13
14
  end
14
15
 
@@ -41,12 +42,12 @@ module ActiveRecord
41
42
  end
42
43
 
43
44
  def rollback!
44
- @children.each { |c| c.rollback! }
45
+ @children&.each { |c| c.rollback! }
45
46
  @state = :rolledback
46
47
  end
47
48
 
48
49
  def full_rollback!
49
- @children.each { |c| c.rollback! }
50
+ @children&.each { |c| c.rollback! }
50
51
  @state = :fully_rolledback
51
52
  end
52
53
 
@@ -69,24 +70,40 @@ module ActiveRecord
69
70
  def closed?; true; end
70
71
  def open?; false; end
71
72
  def joinable?; false; end
72
- def add_record(record); end
73
+ def add_record(record, _ = true); end
73
74
  end
74
75
 
75
76
  class Transaction #:nodoc:
76
- attr_reader :connection, :state, :records, :savepoint_name, :isolation_level
77
+ attr_reader :connection, :state, :savepoint_name, :isolation_level
78
+ attr_accessor :written
77
79
 
78
- def initialize(connection, options, run_commit_callbacks: false)
80
+ def initialize(connection, isolation: nil, joinable: true, run_commit_callbacks: false)
79
81
  @connection = connection
80
82
  @state = TransactionState.new
81
- @records = []
82
- @isolation_level = options[:isolation]
83
+ @records = nil
84
+ @isolation_level = isolation
83
85
  @materialized = false
84
- @joinable = options.fetch(:joinable, true)
86
+ @joinable = joinable
85
87
  @run_commit_callbacks = run_commit_callbacks
88
+ @lazy_enrollment_records = nil
86
89
  end
87
90
 
88
- def add_record(record)
89
- records << record
91
+ def add_record(record, ensure_finalize = true)
92
+ @records ||= []
93
+ if ensure_finalize
94
+ @records << record
95
+ else
96
+ @lazy_enrollment_records ||= ObjectSpace::WeakMap.new
97
+ @lazy_enrollment_records[record] = record
98
+ end
99
+ end
100
+
101
+ def records
102
+ if @lazy_enrollment_records
103
+ @records.concat @lazy_enrollment_records.values
104
+ @lazy_enrollment_records = nil
105
+ end
106
+ @records
90
107
  end
91
108
 
92
109
  def materialize!
@@ -98,7 +115,8 @@ module ActiveRecord
98
115
  end
99
116
 
100
117
  def rollback_records
101
- ite = records.uniq(&:object_id)
118
+ return unless records
119
+ ite = records.uniq(&:__id__)
102
120
  already_run_callbacks = {}
103
121
  while record = ite.shift
104
122
  trigger_callbacks = record.trigger_transactional_callbacks?
@@ -107,17 +125,18 @@ module ActiveRecord
107
125
  record.rolledback!(force_restore_state: full_rollback?, should_run_callbacks: should_run_callbacks)
108
126
  end
109
127
  ensure
110
- ite.each do |i|
128
+ ite&.each do |i|
111
129
  i.rolledback!(force_restore_state: full_rollback?, should_run_callbacks: false)
112
130
  end
113
131
  end
114
132
 
115
133
  def before_commit_records
116
- records.uniq.each(&:before_committed!) if @run_commit_callbacks
134
+ records.uniq.each(&:before_committed!) if records && @run_commit_callbacks
117
135
  end
118
136
 
119
137
  def commit_records
120
- ite = records.uniq(&:object_id)
138
+ return unless records
139
+ ite = records.uniq(&:__id__)
121
140
  already_run_callbacks = {}
122
141
  while record = ite.shift
123
142
  if @run_commit_callbacks
@@ -131,7 +150,7 @@ module ActiveRecord
131
150
  end
132
151
  end
133
152
  ensure
134
- ite.each { |i| i.committed!(should_run_callbacks: false) }
153
+ ite&.each { |i| i.committed!(should_run_callbacks: false) }
135
154
  end
136
155
 
137
156
  def full_rollback?; true; end
@@ -141,8 +160,8 @@ module ActiveRecord
141
160
  end
142
161
 
143
162
  class SavepointTransaction < Transaction
144
- def initialize(connection, savepoint_name, parent_transaction, *args)
145
- super(connection, *args)
163
+ def initialize(connection, savepoint_name, parent_transaction, **options)
164
+ super(connection, **options)
146
165
 
147
166
  parent_transaction.state.add_child(@state)
148
167
 
@@ -202,18 +221,29 @@ module ActiveRecord
202
221
  @lazy_transactions_enabled = true
203
222
  end
204
223
 
205
- def begin_transaction(options = {})
224
+ def begin_transaction(isolation: nil, joinable: true, _lazy: true)
206
225
  @connection.lock.synchronize do
207
226
  run_commit_callbacks = !current_transaction.joinable?
208
227
  transaction =
209
228
  if @stack.empty?
210
- RealTransaction.new(@connection, options, run_commit_callbacks: run_commit_callbacks)
229
+ RealTransaction.new(
230
+ @connection,
231
+ isolation: isolation,
232
+ joinable: joinable,
233
+ run_commit_callbacks: run_commit_callbacks
234
+ )
211
235
  else
212
- SavepointTransaction.new(@connection, "active_record_#{@stack.size}", @stack.last, options,
213
- run_commit_callbacks: run_commit_callbacks)
236
+ SavepointTransaction.new(
237
+ @connection,
238
+ "active_record_#{@stack.size}",
239
+ @stack.last,
240
+ isolation: isolation,
241
+ joinable: joinable,
242
+ run_commit_callbacks: run_commit_callbacks
243
+ )
214
244
  end
215
245
 
216
- if @connection.supports_lazy_transactions? && lazy_transactions_enabled? && options[:_lazy] != false
246
+ if @connection.supports_lazy_transactions? && lazy_transactions_enabled? && _lazy
217
247
  @has_unmaterialized_transactions = true
218
248
  else
219
249
  transaction.materialize!
@@ -274,10 +304,12 @@ module ActiveRecord
274
304
  end
275
305
  end
276
306
 
277
- def within_new_transaction(options = {})
307
+ def within_new_transaction(isolation: nil, joinable: true)
278
308
  @connection.lock.synchronize do
279
- transaction = begin_transaction options
280
- yield
309
+ transaction = begin_transaction(isolation: isolation, joinable: joinable)
310
+ ret = yield
311
+ completed = true
312
+ ret
281
313
  rescue Exception => error
282
314
  if transaction
283
315
  rollback_transaction
@@ -285,15 +317,31 @@ module ActiveRecord
285
317
  end
286
318
  raise
287
319
  ensure
288
- if !error && transaction
289
- if Thread.current.status == "aborting"
290
- rollback_transaction
320
+ if transaction
321
+ if error
322
+ # @connection still holds an open transaction, so we must not
323
+ # put it back in the pool for reuse
324
+ @connection.throw_away! unless transaction.state.rolledback?
291
325
  else
292
- begin
293
- commit_transaction
294
- rescue Exception
295
- rollback_transaction(transaction) unless transaction.state.completed?
296
- raise
326
+ if Thread.current.status == "aborting"
327
+ rollback_transaction
328
+ else
329
+ if !completed && transaction.written
330
+ ActiveSupport::Deprecation.warn(<<~EOW)
331
+ Using `return`, `break` or `throw` to exit a transaction block is
332
+ deprecated without replacement. If the `throw` came from
333
+ `Timeout.timeout(duration)`, pass an exception class as a second
334
+ argument so it doesn't use `throw` to abort its block. This results
335
+ in the transaction being committed, but in the next release of Rails
336
+ it will rollback.
337
+ EOW
338
+ end
339
+ begin
340
+ commit_transaction
341
+ rescue Exception
342
+ rollback_transaction(transaction) unless transaction.state.completed?
343
+ raise
344
+ end
297
345
  end
298
346
  end
299
347
  end
@@ -309,7 +357,6 @@ module ActiveRecord
309
357
  end
310
358
 
311
359
  private
312
-
313
360
  NULL_TRANSACTION = NullTransaction.new
314
361
 
315
362
  # Deallocate invalidated prepared statements outside of the transaction
@@ -1,58 +1,18 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "active_record/connection_adapters/determine_if_preparable_visitor"
3
+ require "set"
4
4
  require "active_record/connection_adapters/schema_cache"
5
5
  require "active_record/connection_adapters/sql_type_metadata"
6
6
  require "active_record/connection_adapters/abstract/schema_dumper"
7
7
  require "active_record/connection_adapters/abstract/schema_creation"
8
8
  require "active_support/concurrency/load_interlock_aware_monitor"
9
- require "active_support/deprecation"
10
9
  require "arel/collectors/bind"
11
10
  require "arel/collectors/composite"
12
11
  require "arel/collectors/sql_string"
13
12
  require "arel/collectors/substitute_binds"
14
- require "concurrent/atomic/thread_local_var"
15
13
 
16
14
  module ActiveRecord
17
15
  module ConnectionAdapters # :nodoc:
18
- extend ActiveSupport::Autoload
19
-
20
- autoload :Column
21
- autoload :ConnectionSpecification
22
-
23
- autoload_at "active_record/connection_adapters/abstract/schema_definitions" do
24
- autoload :IndexDefinition
25
- autoload :ColumnDefinition
26
- autoload :ChangeColumnDefinition
27
- autoload :ForeignKeyDefinition
28
- autoload :TableDefinition
29
- autoload :Table
30
- autoload :AlterTable
31
- autoload :ReferenceDefinition
32
- end
33
-
34
- autoload_at "active_record/connection_adapters/abstract/connection_pool" do
35
- autoload :ConnectionHandler
36
- end
37
-
38
- autoload_under "abstract" do
39
- autoload :SchemaStatements
40
- autoload :DatabaseStatements
41
- autoload :DatabaseLimits
42
- autoload :Quoting
43
- autoload :ConnectionPool
44
- autoload :QueryCache
45
- autoload :Savepoints
46
- end
47
-
48
- autoload_at "active_record/connection_adapters/abstract/transaction" do
49
- autoload :TransactionManager
50
- autoload :NullTransaction
51
- autoload :RealTransaction
52
- autoload :SavepointTransaction
53
- autoload :TransactionState
54
- end
55
-
56
16
  # Active Record supports multiple database systems. AbstractAdapter and
57
17
  # related classes form the abstraction layer which makes this possible.
58
18
  # An AbstractAdapter represents a connection to a database, and provides an
@@ -77,6 +37,7 @@ module ActiveRecord
77
37
  include Savepoints
78
38
 
79
39
  SIMPLE_INT = /\A\d+\z/
40
+ COMMENT_REGEX = %r{(?:\-\-.*\n)*|/\*(?:[^\*]|\*[^/])*\*/}m
80
41
 
81
42
  attr_accessor :pool
82
43
  attr_reader :visitor, :owner, :logger, :lock
@@ -102,9 +63,13 @@ module ActiveRecord
102
63
  end
103
64
  end
104
65
 
66
+ DEFAULT_READ_QUERY = [:begin, :commit, :explain, :release, :rollback, :savepoint, :select, :with] # :nodoc:
67
+ private_constant :DEFAULT_READ_QUERY
68
+
105
69
  def self.build_read_query_regexp(*parts) # :nodoc:
106
- parts = parts.map { |part| /\A[\(\s]*#{part}/i }
107
- Regexp.union(*parts)
70
+ parts += DEFAULT_READ_QUERY
71
+ parts = parts.map { |part| /#{part}/i }
72
+ /\A(?:[\(\s]|#{COMMENT_REGEX})*#{Regexp.union(*parts)}/
108
73
  end
109
74
 
110
75
  def self.quoted_column_names # :nodoc:
@@ -129,12 +94,9 @@ module ActiveRecord
129
94
  @statements = build_statement_pool
130
95
  @lock = ActiveSupport::Concurrency::LoadInterlockAwareMonitor.new
131
96
 
132
- if self.class.type_cast_config_to_boolean(config.fetch(:prepared_statements) { true })
133
- @prepared_statement_status = Concurrent::ThreadLocalVar.new(true)
134
- @visitor.extend(DetermineIfPreparableVisitor)
135
- else
136
- @prepared_statement_status = Concurrent::ThreadLocalVar.new(false)
137
- end
97
+ @prepared_statements = self.class.type_cast_config_to_boolean(
98
+ config.fetch(:prepared_statements, true)
99
+ )
138
100
 
139
101
  @advisory_locks_enabled = self.class.type_cast_config_to_boolean(
140
102
  config.fetch(:advisory_locks, true)
@@ -145,12 +107,25 @@ module ActiveRecord
145
107
  @config[:replica] || false
146
108
  end
147
109
 
148
- # Determines whether writes are currently being prevents.
110
+ def use_metadata_table?
111
+ @config.fetch(:use_metadata_table, true)
112
+ end
113
+
114
+ # Determines whether writes are currently being prevented.
115
+ #
116
+ # Returns true if the connection is a replica.
117
+ #
118
+ # If the application is using legacy handling, returns
119
+ # true if +connection_handler.prevent_writes+ is set.
149
120
  #
150
- # Returns true if the connection is a replica, or if +prevent_writes+
151
- # is set to true.
121
+ # If the application is using the new connection handling
122
+ # will return true based on +current_preventing_writes+.
152
123
  def preventing_writes?
153
- replica? || ActiveRecord::Base.connection_handler.prevent_writes
124
+ return true if replica?
125
+ return ActiveRecord::Base.connection_handler.prevent_writes if ActiveRecord::Base.legacy_connection_handling
126
+ return false if connection_klass.nil?
127
+
128
+ connection_klass.current_preventing_writes
154
129
  end
155
130
 
156
131
  def migrations_paths # :nodoc:
@@ -164,12 +139,15 @@ module ActiveRecord
164
139
  def schema_migration # :nodoc:
165
140
  @schema_migration ||= begin
166
141
  conn = self
167
- spec_name = conn.pool.spec.name
168
- name = "#{spec_name}::SchemaMigration"
142
+ spec_name = conn.pool.pool_config.connection_specification_name
143
+
144
+ return ActiveRecord::SchemaMigration if spec_name == "ActiveRecord::Base"
145
+
146
+ schema_migration_name = "#{spec_name}::SchemaMigration"
169
147
 
170
148
  Class.new(ActiveRecord::SchemaMigration) do
171
- define_singleton_method(:name) { name }
172
- define_singleton_method(:to_s) { name }
149
+ define_singleton_method(:name) { schema_migration_name }
150
+ define_singleton_method(:to_s) { schema_migration_name }
173
151
 
174
152
  self.connection_specification_name = spec_name
175
153
  end
@@ -177,7 +155,11 @@ module ActiveRecord
177
155
  end
178
156
 
179
157
  def prepared_statements
180
- @prepared_statement_status.value
158
+ @prepared_statements && !prepared_statements_disabled_cache.include?(object_id)
159
+ end
160
+
161
+ def prepared_statements_disabled_cache # :nodoc:
162
+ Thread.current[:ar_prepared_statements_disabled_cache] ||= Set.new
181
163
  end
182
164
 
183
165
  class Version
@@ -219,6 +201,10 @@ module ActiveRecord
219
201
  @owner = Thread.current
220
202
  end
221
203
 
204
+ def connection_klass # :nodoc:
205
+ @pool.connection_klass
206
+ end
207
+
222
208
  def schema_cache
223
209
  @pool.get_schema_cache(self)
224
210
  end
@@ -264,7 +250,10 @@ module ActiveRecord
264
250
  end
265
251
 
266
252
  def unprepared_statement
267
- @prepared_statement_status.bind(false) { yield }
253
+ cache = prepared_statements_disabled_cache.add(object_id) if @prepared_statements
254
+ yield
255
+ ensure
256
+ cache&.delete(object_id)
268
257
  end
269
258
 
270
259
  # Returns the human-readable name of the adapter. Use mixed case - one
@@ -305,6 +294,10 @@ module ActiveRecord
305
294
  false
306
295
  end
307
296
 
297
+ def supports_partitioned_indexes?
298
+ false
299
+ end
300
+
308
301
  # Does this adapter support index sort order?
309
302
  def supports_index_sort_order?
310
303
  false
@@ -351,12 +344,10 @@ module ActiveRecord
351
344
  false
352
345
  end
353
346
 
354
- # Does this adapter support creating foreign key constraints
355
- # in the same statement as creating the table?
356
- def supports_foreign_keys_in_create?
357
- supports_foreign_keys?
347
+ # Does this adapter support creating check constraints?
348
+ def supports_check_constraints?
349
+ false
358
350
  end
359
- deprecate :supports_foreign_keys_in_create?
360
351
 
361
352
  # Does this adapter support views?
362
353
  def supports_views?
@@ -388,12 +379,6 @@ module ActiveRecord
388
379
  false
389
380
  end
390
381
 
391
- # Does this adapter support multi-value insert?
392
- def supports_multi_insert?
393
- true
394
- end
395
- deprecate :supports_multi_insert?
396
-
397
382
  # Does this adapter support virtual columns?
398
383
  def supports_virtual_columns?
399
384
  false
@@ -409,6 +394,10 @@ module ActiveRecord
409
394
  false
410
395
  end
411
396
 
397
+ def supports_common_table_expressions?
398
+ false
399
+ end
400
+
412
401
  def supports_lazy_transactions?
413
402
  false
414
403
  end
@@ -521,6 +510,12 @@ module ActiveRecord
521
510
  # this should be overridden by concrete adapters
522
511
  end
523
512
 
513
+ # Removes the connection from the pool and disconnect it.
514
+ def throw_away!
515
+ pool.remove self
516
+ disconnect!
517
+ end
518
+
524
519
  # Clear any caching the database adapter may be doing.
525
520
  def clear_cache!
526
521
  @lock.synchronize { @statements.clear } if @statements
@@ -549,7 +544,7 @@ module ActiveRecord
549
544
  @connection
550
545
  end
551
546
 
552
- def default_uniqueness_comparison(attribute, value, klass) # :nodoc:
547
+ def default_uniqueness_comparison(attribute, value) # :nodoc:
553
548
  attribute.eq(value)
554
549
  end
555
550
 
@@ -577,10 +572,6 @@ module ActiveRecord
577
572
  pool.checkin self
578
573
  end
579
574
 
580
- def column_name_for_operation(operation, node) # :nodoc:
581
- visitor.compile(node)
582
- end
583
-
584
575
  def default_index_type?(index) # :nodoc:
585
576
  index.using.nil?
586
577
  end
@@ -609,7 +600,6 @@ module ActiveRecord
609
600
  end
610
601
 
611
602
  private
612
-
613
603
  def type_map
614
604
  @type_map ||= Type::TypeMap.new.tap do |mapping|
615
605
  initialize_type_map(mapping)
@@ -701,7 +691,6 @@ module ActiveRecord
701
691
  binds: binds,
702
692
  type_casted_binds: type_casted_binds,
703
693
  statement_name: statement_name,
704
- connection_id: object_id,
705
694
  connection: self) do
706
695
  @lock.synchronize do
707
696
  yield
@@ -756,6 +745,14 @@ module ActiveRecord
756
745
 
757
746
  def build_statement_pool
758
747
  end
748
+
749
+ # Builds the result object.
750
+ #
751
+ # This is an internal hook to make possible connection adapters to build
752
+ # custom result objects with connection-specific data.
753
+ def build_result(columns:, rows:, column_types: {})
754
+ ActiveRecord::Result.new(columns, rows, column_types)
755
+ end
759
756
  end
760
757
  end
761
758
  end