activerecord 5.2.6 → 6.1.3.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 (316) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +1038 -571
  3. data/MIT-LICENSE +3 -1
  4. data/README.rdoc +7 -5
  5. data/examples/performance.rb +1 -1
  6. data/lib/active_record.rb +13 -12
  7. data/lib/active_record/aggregations.rb +9 -8
  8. data/lib/active_record/association_relation.rb +30 -10
  9. data/lib/active_record/associations.rb +137 -25
  10. data/lib/active_record/associations/alias_tracker.rb +19 -16
  11. data/lib/active_record/associations/association.rb +95 -42
  12. data/lib/active_record/associations/association_scope.rb +23 -21
  13. data/lib/active_record/associations/belongs_to_association.rb +54 -46
  14. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +7 -6
  15. data/lib/active_record/associations/builder/association.rb +45 -22
  16. data/lib/active_record/associations/builder/belongs_to.rb +29 -59
  17. data/lib/active_record/associations/builder/collection_association.rb +8 -17
  18. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +17 -41
  19. data/lib/active_record/associations/builder/has_many.rb +8 -2
  20. data/lib/active_record/associations/builder/has_one.rb +33 -2
  21. data/lib/active_record/associations/builder/singular_association.rb +3 -1
  22. data/lib/active_record/associations/collection_association.rb +31 -29
  23. data/lib/active_record/associations/collection_proxy.rb +25 -21
  24. data/lib/active_record/associations/foreign_association.rb +20 -0
  25. data/lib/active_record/associations/has_many_association.rb +26 -13
  26. data/lib/active_record/associations/has_many_through_association.rb +24 -18
  27. data/lib/active_record/associations/has_one_association.rb +43 -31
  28. data/lib/active_record/associations/has_one_through_association.rb +5 -5
  29. data/lib/active_record/associations/join_dependency.rb +91 -60
  30. data/lib/active_record/associations/join_dependency/join_association.rb +44 -22
  31. data/lib/active_record/associations/join_dependency/join_part.rb +5 -5
  32. data/lib/active_record/associations/preloader.rb +47 -34
  33. data/lib/active_record/associations/preloader/association.rb +71 -43
  34. data/lib/active_record/associations/preloader/through_association.rb +49 -40
  35. data/lib/active_record/associations/singular_association.rb +3 -17
  36. data/lib/active_record/associations/through_association.rb +1 -1
  37. data/lib/active_record/attribute_assignment.rb +17 -19
  38. data/lib/active_record/attribute_methods.rb +81 -143
  39. data/lib/active_record/attribute_methods/before_type_cast.rb +13 -7
  40. data/lib/active_record/attribute_methods/dirty.rb +101 -40
  41. data/lib/active_record/attribute_methods/primary_key.rb +20 -25
  42. data/lib/active_record/attribute_methods/query.rb +4 -8
  43. data/lib/active_record/attribute_methods/read.rb +14 -56
  44. data/lib/active_record/attribute_methods/serialization.rb +12 -7
  45. data/lib/active_record/attribute_methods/time_zone_conversion.rb +12 -15
  46. data/lib/active_record/attribute_methods/write.rb +18 -34
  47. data/lib/active_record/attributes.rb +46 -9
  48. data/lib/active_record/autosave_association.rb +57 -42
  49. data/lib/active_record/base.rb +4 -17
  50. data/lib/active_record/callbacks.rb +158 -43
  51. data/lib/active_record/coders/yaml_column.rb +1 -2
  52. data/lib/active_record/connection_adapters.rb +50 -0
  53. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +272 -130
  54. data/lib/active_record/connection_adapters/abstract/database_limits.rb +7 -36
  55. data/lib/active_record/connection_adapters/abstract/database_statements.rb +167 -146
  56. data/lib/active_record/connection_adapters/abstract/query_cache.rb +18 -14
  57. data/lib/active_record/connection_adapters/abstract/quoting.rb +98 -47
  58. data/lib/active_record/connection_adapters/abstract/savepoints.rb +3 -3
  59. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +153 -110
  60. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +207 -90
  61. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +2 -4
  62. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +385 -144
  63. data/lib/active_record/connection_adapters/abstract/transaction.rb +155 -68
  64. data/lib/active_record/connection_adapters/abstract_adapter.rb +228 -98
  65. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +243 -275
  66. data/lib/active_record/connection_adapters/column.rb +30 -12
  67. data/lib/active_record/connection_adapters/deduplicable.rb +29 -0
  68. data/lib/active_record/connection_adapters/legacy_pool_manager.rb +31 -0
  69. data/lib/active_record/connection_adapters/mysql/column.rb +1 -1
  70. data/lib/active_record/connection_adapters/mysql/database_statements.rb +86 -32
  71. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +1 -2
  72. data/lib/active_record/connection_adapters/mysql/quoting.rb +59 -7
  73. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +34 -10
  74. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +48 -32
  75. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +18 -7
  76. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +139 -19
  77. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +14 -9
  78. data/lib/active_record/connection_adapters/mysql2_adapter.rb +53 -18
  79. data/lib/active_record/connection_adapters/pool_config.rb +73 -0
  80. data/lib/active_record/connection_adapters/pool_manager.rb +43 -0
  81. data/lib/active_record/connection_adapters/postgresql/column.rb +37 -28
  82. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +38 -54
  83. data/lib/active_record/connection_adapters/postgresql/oid.rb +2 -0
  84. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -2
  85. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +1 -4
  86. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +3 -5
  87. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +2 -2
  88. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +10 -2
  89. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +0 -1
  90. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +1 -2
  91. data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +49 -0
  92. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +3 -4
  93. data/lib/active_record/connection_adapters/postgresql/oid/macaddr.rb +25 -0
  94. data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +1 -1
  95. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +3 -4
  96. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +25 -7
  97. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +1 -1
  98. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +9 -7
  99. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +15 -3
  100. data/lib/active_record/connection_adapters/postgresql/quoting.rb +47 -10
  101. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +2 -2
  102. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +19 -4
  103. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +107 -91
  104. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +0 -1
  105. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +120 -100
  106. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +31 -26
  107. data/lib/active_record/connection_adapters/postgresql/utils.rb +0 -1
  108. data/lib/active_record/connection_adapters/postgresql_adapter.rb +224 -120
  109. data/lib/active_record/connection_adapters/schema_cache.rb +127 -21
  110. data/lib/active_record/connection_adapters/sql_type_metadata.rb +19 -6
  111. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +144 -0
  112. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +42 -7
  113. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +5 -1
  114. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +77 -13
  115. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +174 -186
  116. data/lib/active_record/connection_adapters/statement_pool.rb +0 -1
  117. data/lib/active_record/connection_handling.rb +293 -33
  118. data/lib/active_record/core.rb +323 -97
  119. data/lib/active_record/counter_cache.rb +8 -30
  120. data/lib/active_record/database_configurations.rb +272 -0
  121. data/lib/active_record/database_configurations/connection_url_resolver.rb +98 -0
  122. data/lib/active_record/database_configurations/database_config.rb +80 -0
  123. data/lib/active_record/database_configurations/hash_config.rb +96 -0
  124. data/lib/active_record/database_configurations/url_config.rb +53 -0
  125. data/lib/active_record/delegated_type.rb +209 -0
  126. data/lib/active_record/destroy_association_async_job.rb +36 -0
  127. data/lib/active_record/dynamic_matchers.rb +3 -4
  128. data/lib/active_record/enum.rb +111 -37
  129. data/lib/active_record/errors.rb +62 -19
  130. data/lib/active_record/explain.rb +10 -6
  131. data/lib/active_record/explain_subscriber.rb +1 -1
  132. data/lib/active_record/fixture_set/file.rb +10 -17
  133. data/lib/active_record/fixture_set/model_metadata.rb +32 -0
  134. data/lib/active_record/fixture_set/render_context.rb +17 -0
  135. data/lib/active_record/fixture_set/table_row.rb +152 -0
  136. data/lib/active_record/fixture_set/table_rows.rb +46 -0
  137. data/lib/active_record/fixtures.rb +200 -481
  138. data/lib/active_record/gem_version.rb +4 -4
  139. data/lib/active_record/inheritance.rb +53 -24
  140. data/lib/active_record/insert_all.rb +208 -0
  141. data/lib/active_record/integration.rb +67 -17
  142. data/lib/active_record/internal_metadata.rb +26 -9
  143. data/lib/active_record/legacy_yaml_adapter.rb +7 -3
  144. data/lib/active_record/locking/optimistic.rb +37 -23
  145. data/lib/active_record/locking/pessimistic.rb +9 -5
  146. data/lib/active_record/log_subscriber.rb +35 -35
  147. data/lib/active_record/middleware/database_selector.rb +77 -0
  148. data/lib/active_record/middleware/database_selector/resolver.rb +92 -0
  149. data/lib/active_record/middleware/database_selector/resolver/session.rb +48 -0
  150. data/lib/active_record/migration.rb +206 -157
  151. data/lib/active_record/migration/command_recorder.rb +96 -44
  152. data/lib/active_record/migration/compatibility.rb +142 -64
  153. data/lib/active_record/migration/join_table.rb +0 -1
  154. data/lib/active_record/model_schema.rb +148 -22
  155. data/lib/active_record/nested_attributes.rb +4 -7
  156. data/lib/active_record/no_touching.rb +8 -1
  157. data/lib/active_record/null_relation.rb +0 -1
  158. data/lib/active_record/persistence.rb +267 -59
  159. data/lib/active_record/query_cache.rb +21 -4
  160. data/lib/active_record/querying.rb +40 -23
  161. data/lib/active_record/railtie.rb +115 -58
  162. data/lib/active_record/railties/console_sandbox.rb +2 -4
  163. data/lib/active_record/railties/controller_runtime.rb +30 -35
  164. data/lib/active_record/railties/databases.rake +408 -78
  165. data/lib/active_record/readonly_attributes.rb +4 -0
  166. data/lib/active_record/reflection.rb +109 -93
  167. data/lib/active_record/relation.rb +374 -104
  168. data/lib/active_record/relation/batches.rb +44 -35
  169. data/lib/active_record/relation/batches/batch_enumerator.rb +25 -9
  170. data/lib/active_record/relation/calculations.rb +153 -90
  171. data/lib/active_record/relation/delegation.rb +35 -50
  172. data/lib/active_record/relation/finder_methods.rb +64 -39
  173. data/lib/active_record/relation/from_clause.rb +5 -1
  174. data/lib/active_record/relation/merger.rb +32 -40
  175. data/lib/active_record/relation/predicate_builder.rb +62 -45
  176. data/lib/active_record/relation/predicate_builder/array_handler.rb +13 -13
  177. data/lib/active_record/relation/predicate_builder/association_query_value.rb +5 -9
  178. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +1 -2
  179. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +11 -10
  180. data/lib/active_record/relation/predicate_builder/range_handler.rb +3 -23
  181. data/lib/active_record/relation/predicate_builder/relation_handler.rb +1 -1
  182. data/lib/active_record/relation/query_attribute.rb +13 -8
  183. data/lib/active_record/relation/query_methods.rb +475 -186
  184. data/lib/active_record/relation/record_fetch_warning.rb +3 -3
  185. data/lib/active_record/relation/spawn_methods.rb +9 -9
  186. data/lib/active_record/relation/where_clause.rb +111 -61
  187. data/lib/active_record/result.rb +64 -38
  188. data/lib/active_record/runtime_registry.rb +2 -2
  189. data/lib/active_record/sanitization.rb +22 -41
  190. data/lib/active_record/schema.rb +2 -11
  191. data/lib/active_record/schema_dumper.rb +54 -9
  192. data/lib/active_record/schema_migration.rb +7 -9
  193. data/lib/active_record/scoping.rb +8 -9
  194. data/lib/active_record/scoping/default.rb +4 -6
  195. data/lib/active_record/scoping/named.rb +17 -24
  196. data/lib/active_record/secure_token.rb +16 -8
  197. data/lib/active_record/serialization.rb +5 -3
  198. data/lib/active_record/signed_id.rb +116 -0
  199. data/lib/active_record/statement_cache.rb +49 -6
  200. data/lib/active_record/store.rb +88 -9
  201. data/lib/active_record/suppressor.rb +2 -2
  202. data/lib/active_record/table_metadata.rb +42 -43
  203. data/lib/active_record/tasks/database_tasks.rb +277 -81
  204. data/lib/active_record/tasks/mysql_database_tasks.rb +37 -39
  205. data/lib/active_record/tasks/postgresql_database_tasks.rb +27 -32
  206. data/lib/active_record/tasks/sqlite_database_tasks.rb +14 -17
  207. data/lib/active_record/test_databases.rb +24 -0
  208. data/lib/active_record/test_fixtures.rb +246 -0
  209. data/lib/active_record/timestamp.rb +43 -32
  210. data/lib/active_record/touch_later.rb +23 -22
  211. data/lib/active_record/transactions.rb +62 -118
  212. data/lib/active_record/translation.rb +1 -1
  213. data/lib/active_record/type.rb +10 -5
  214. data/lib/active_record/type/adapter_specific_registry.rb +3 -13
  215. data/lib/active_record/type/hash_lookup_type_map.rb +0 -1
  216. data/lib/active_record/type/serialized.rb +6 -3
  217. data/lib/active_record/type/time.rb +10 -0
  218. data/lib/active_record/type/type_map.rb +0 -1
  219. data/lib/active_record/type/unsigned_integer.rb +0 -1
  220. data/lib/active_record/type_caster/connection.rb +15 -15
  221. data/lib/active_record/type_caster/map.rb +8 -8
  222. data/lib/active_record/validations.rb +4 -3
  223. data/lib/active_record/validations/associated.rb +1 -2
  224. data/lib/active_record/validations/numericality.rb +35 -0
  225. data/lib/active_record/validations/uniqueness.rb +38 -30
  226. data/lib/arel.rb +54 -0
  227. data/lib/arel/alias_predication.rb +9 -0
  228. data/lib/arel/attributes/attribute.rb +41 -0
  229. data/lib/arel/collectors/bind.rb +29 -0
  230. data/lib/arel/collectors/composite.rb +39 -0
  231. data/lib/arel/collectors/plain_string.rb +20 -0
  232. data/lib/arel/collectors/sql_string.rb +27 -0
  233. data/lib/arel/collectors/substitute_binds.rb +35 -0
  234. data/lib/arel/crud.rb +42 -0
  235. data/lib/arel/delete_manager.rb +18 -0
  236. data/lib/arel/errors.rb +9 -0
  237. data/lib/arel/expressions.rb +29 -0
  238. data/lib/arel/factory_methods.rb +49 -0
  239. data/lib/arel/insert_manager.rb +49 -0
  240. data/lib/arel/math.rb +45 -0
  241. data/lib/arel/nodes.rb +70 -0
  242. data/lib/arel/nodes/and.rb +32 -0
  243. data/lib/arel/nodes/ascending.rb +23 -0
  244. data/lib/arel/nodes/binary.rb +126 -0
  245. data/lib/arel/nodes/bind_param.rb +44 -0
  246. data/lib/arel/nodes/case.rb +55 -0
  247. data/lib/arel/nodes/casted.rb +62 -0
  248. data/lib/arel/nodes/comment.rb +29 -0
  249. data/lib/arel/nodes/count.rb +12 -0
  250. data/lib/arel/nodes/delete_statement.rb +45 -0
  251. data/lib/arel/nodes/descending.rb +23 -0
  252. data/lib/arel/nodes/equality.rb +15 -0
  253. data/lib/arel/nodes/extract.rb +24 -0
  254. data/lib/arel/nodes/false.rb +16 -0
  255. data/lib/arel/nodes/full_outer_join.rb +8 -0
  256. data/lib/arel/nodes/function.rb +44 -0
  257. data/lib/arel/nodes/grouping.rb +11 -0
  258. data/lib/arel/nodes/homogeneous_in.rb +72 -0
  259. data/lib/arel/nodes/in.rb +15 -0
  260. data/lib/arel/nodes/infix_operation.rb +92 -0
  261. data/lib/arel/nodes/inner_join.rb +8 -0
  262. data/lib/arel/nodes/insert_statement.rb +37 -0
  263. data/lib/arel/nodes/join_source.rb +20 -0
  264. data/lib/arel/nodes/matches.rb +18 -0
  265. data/lib/arel/nodes/named_function.rb +23 -0
  266. data/lib/arel/nodes/node.rb +51 -0
  267. data/lib/arel/nodes/node_expression.rb +13 -0
  268. data/lib/arel/nodes/ordering.rb +27 -0
  269. data/lib/arel/nodes/outer_join.rb +8 -0
  270. data/lib/arel/nodes/over.rb +15 -0
  271. data/lib/arel/nodes/regexp.rb +16 -0
  272. data/lib/arel/nodes/right_outer_join.rb +8 -0
  273. data/lib/arel/nodes/select_core.rb +67 -0
  274. data/lib/arel/nodes/select_statement.rb +41 -0
  275. data/lib/arel/nodes/sql_literal.rb +19 -0
  276. data/lib/arel/nodes/string_join.rb +11 -0
  277. data/lib/arel/nodes/table_alias.rb +31 -0
  278. data/lib/arel/nodes/terminal.rb +16 -0
  279. data/lib/arel/nodes/true.rb +16 -0
  280. data/lib/arel/nodes/unary.rb +44 -0
  281. data/lib/arel/nodes/unary_operation.rb +20 -0
  282. data/lib/arel/nodes/unqualified_column.rb +22 -0
  283. data/lib/arel/nodes/update_statement.rb +41 -0
  284. data/lib/arel/nodes/values_list.rb +9 -0
  285. data/lib/arel/nodes/window.rb +126 -0
  286. data/lib/arel/nodes/with.rb +11 -0
  287. data/lib/arel/order_predications.rb +13 -0
  288. data/lib/arel/predications.rb +250 -0
  289. data/lib/arel/select_manager.rb +270 -0
  290. data/lib/arel/table.rb +118 -0
  291. data/lib/arel/tree_manager.rb +72 -0
  292. data/lib/arel/update_manager.rb +34 -0
  293. data/lib/arel/visitors.rb +13 -0
  294. data/lib/arel/visitors/dot.rb +308 -0
  295. data/lib/arel/visitors/mysql.rb +93 -0
  296. data/lib/arel/visitors/postgresql.rb +120 -0
  297. data/lib/arel/visitors/sqlite.rb +38 -0
  298. data/lib/arel/visitors/to_sql.rb +899 -0
  299. data/lib/arel/visitors/visitor.rb +45 -0
  300. data/lib/arel/window_predications.rb +9 -0
  301. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +0 -1
  302. data/lib/rails/generators/active_record/migration.rb +19 -2
  303. data/lib/rails/generators/active_record/migration/migration_generator.rb +3 -5
  304. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +3 -1
  305. data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +7 -5
  306. data/lib/rails/generators/active_record/model/model_generator.rb +39 -2
  307. data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +7 -0
  308. data/lib/rails/generators/active_record/model/templates/model.rb.tt +10 -1
  309. metadata +119 -34
  310. data/lib/active_record/attribute_decorators.rb +0 -90
  311. data/lib/active_record/collection_cache_key.rb +0 -53
  312. data/lib/active_record/connection_adapters/connection_specification.rb +0 -287
  313. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +0 -33
  314. data/lib/active_record/define_callbacks.rb +0 -22
  315. data/lib/active_record/relation/predicate_builder/base_handler.rb +0 -19
  316. data/lib/active_record/relation/where_clause_factory.rb +0 -34
@@ -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
 
@@ -40,31 +41,13 @@ module ActiveRecord
40
41
  committed? || rolledback?
41
42
  end
42
43
 
43
- def set_state(state)
44
- ActiveSupport::Deprecation.warn(<<-MSG.squish)
45
- The set_state method is deprecated and will be removed in
46
- Rails 6.0. Please use rollback! or commit! to set transaction
47
- state directly.
48
- MSG
49
- case state
50
- when :rolledback
51
- rollback!
52
- when :committed
53
- commit!
54
- when nil
55
- nullify!
56
- else
57
- raise ArgumentError, "Invalid transaction state: #{state}"
58
- end
59
- end
60
-
61
44
  def rollback!
62
- @children.each { |c| c.rollback! }
45
+ @children&.each { |c| c.rollback! }
63
46
  @state = :rolledback
64
47
  end
65
48
 
66
49
  def full_rollback!
67
- @children.each { |c| c.rollback! }
50
+ @children&.each { |c| c.rollback! }
68
51
  @state = :fully_rolledback
69
52
  end
70
53
 
@@ -87,52 +70,87 @@ module ActiveRecord
87
70
  def closed?; true; end
88
71
  def open?; false; end
89
72
  def joinable?; false; end
90
- def add_record(record); end
73
+ def add_record(record, _ = true); end
91
74
  end
92
75
 
93
76
  class Transaction #:nodoc:
94
- attr_reader :connection, :state, :records, :savepoint_name
95
- attr_writer :joinable
77
+ attr_reader :connection, :state, :savepoint_name, :isolation_level
78
+ attr_accessor :written
96
79
 
97
- def initialize(connection, options, run_commit_callbacks: false)
80
+ def initialize(connection, isolation: nil, joinable: true, run_commit_callbacks: false)
98
81
  @connection = connection
99
82
  @state = TransactionState.new
100
- @records = []
101
- @joinable = options.fetch(:joinable, true)
83
+ @records = nil
84
+ @isolation_level = isolation
85
+ @materialized = false
86
+ @joinable = joinable
102
87
  @run_commit_callbacks = run_commit_callbacks
88
+ @lazy_enrollment_records = nil
89
+ end
90
+
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
103
107
  end
104
108
 
105
- def add_record(record)
106
- records << record
109
+ def materialize!
110
+ @materialized = true
111
+ end
112
+
113
+ def materialized?
114
+ @materialized
107
115
  end
108
116
 
109
117
  def rollback_records
110
- ite = records.uniq
118
+ return unless records
119
+ ite = records.uniq(&:__id__)
120
+ already_run_callbacks = {}
111
121
  while record = ite.shift
112
- record.rolledback!(force_restore_state: full_rollback?)
122
+ trigger_callbacks = record.trigger_transactional_callbacks?
123
+ should_run_callbacks = !already_run_callbacks[record] && trigger_callbacks
124
+ already_run_callbacks[record] ||= trigger_callbacks
125
+ record.rolledback!(force_restore_state: full_rollback?, should_run_callbacks: should_run_callbacks)
113
126
  end
114
127
  ensure
115
- ite.each do |i|
128
+ ite&.each do |i|
116
129
  i.rolledback!(force_restore_state: full_rollback?, should_run_callbacks: false)
117
130
  end
118
131
  end
119
132
 
120
133
  def before_commit_records
121
- records.uniq.each(&:before_committed!) if @run_commit_callbacks
134
+ records.uniq.each(&:before_committed!) if records && @run_commit_callbacks
122
135
  end
123
136
 
124
137
  def commit_records
125
- ite = records.uniq
138
+ return unless records
139
+ ite = records.uniq(&:__id__)
140
+ already_run_callbacks = {}
126
141
  while record = ite.shift
127
142
  if @run_commit_callbacks
128
- record.committed!
143
+ trigger_callbacks = record.trigger_transactional_callbacks?
144
+ should_run_callbacks = !already_run_callbacks[record] && trigger_callbacks
145
+ already_run_callbacks[record] ||= trigger_callbacks
146
+ record.committed!(should_run_callbacks: should_run_callbacks)
129
147
  else
130
148
  # if not running callbacks, only adds the record to the parent transaction
131
- record.add_to_transaction
149
+ connection.add_transaction_record(record)
132
150
  end
133
151
  end
134
152
  ensure
135
- ite.each { |i| i.committed!(should_run_callbacks: false) }
153
+ ite&.each { |i| i.committed!(should_run_callbacks: false) }
136
154
  end
137
155
 
138
156
  def full_rollback?; true; end
@@ -142,24 +160,30 @@ module ActiveRecord
142
160
  end
143
161
 
144
162
  class SavepointTransaction < Transaction
145
- def initialize(connection, savepoint_name, parent_transaction, options, *args)
146
- super(connection, options, *args)
163
+ def initialize(connection, savepoint_name, parent_transaction, **options)
164
+ super(connection, **options)
147
165
 
148
166
  parent_transaction.state.add_child(@state)
149
167
 
150
- if options[:isolation]
168
+ if isolation_level
151
169
  raise ActiveRecord::TransactionIsolationError, "cannot set transaction isolation in a nested transaction"
152
170
  end
153
- connection.create_savepoint(@savepoint_name = savepoint_name)
171
+
172
+ @savepoint_name = savepoint_name
173
+ end
174
+
175
+ def materialize!
176
+ connection.create_savepoint(savepoint_name)
177
+ super
154
178
  end
155
179
 
156
180
  def rollback
157
- connection.rollback_to_savepoint(savepoint_name)
181
+ connection.rollback_to_savepoint(savepoint_name) if materialized?
158
182
  @state.rollback!
159
183
  end
160
184
 
161
185
  def commit
162
- connection.release_savepoint(savepoint_name)
186
+ connection.release_savepoint(savepoint_name) if materialized?
163
187
  @state.commit!
164
188
  end
165
189
 
@@ -167,22 +191,23 @@ module ActiveRecord
167
191
  end
168
192
 
169
193
  class RealTransaction < Transaction
170
- def initialize(connection, options, *args)
171
- super
172
- if options[:isolation]
173
- connection.begin_isolated_db_transaction(options[:isolation])
194
+ def materialize!
195
+ if isolation_level
196
+ connection.begin_isolated_db_transaction(isolation_level)
174
197
  else
175
198
  connection.begin_db_transaction
176
199
  end
200
+
201
+ super
177
202
  end
178
203
 
179
204
  def rollback
180
- connection.rollback_db_transaction
205
+ connection.rollback_db_transaction if materialized?
181
206
  @state.full_rollback!
182
207
  end
183
208
 
184
209
  def commit
185
- connection.commit_db_transaction
210
+ connection.commit_db_transaction if materialized?
186
211
  @state.full_commit!
187
212
  end
188
213
  end
@@ -191,24 +216,71 @@ module ActiveRecord
191
216
  def initialize(connection)
192
217
  @stack = []
193
218
  @connection = connection
219
+ @has_unmaterialized_transactions = false
220
+ @materializing_transactions = false
221
+ @lazy_transactions_enabled = true
194
222
  end
195
223
 
196
- def begin_transaction(options = {})
224
+ def begin_transaction(isolation: nil, joinable: true, _lazy: true)
197
225
  @connection.lock.synchronize do
198
226
  run_commit_callbacks = !current_transaction.joinable?
199
227
  transaction =
200
228
  if @stack.empty?
201
- 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
+ )
202
235
  else
203
- SavepointTransaction.new(@connection, "active_record_#{@stack.size}", @stack.last, options,
204
- 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
+ )
205
244
  end
206
245
 
246
+ if @connection.supports_lazy_transactions? && lazy_transactions_enabled? && _lazy
247
+ @has_unmaterialized_transactions = true
248
+ else
249
+ transaction.materialize!
250
+ end
207
251
  @stack.push(transaction)
208
252
  transaction
209
253
  end
210
254
  end
211
255
 
256
+ def disable_lazy_transactions!
257
+ materialize_transactions
258
+ @lazy_transactions_enabled = false
259
+ end
260
+
261
+ def enable_lazy_transactions!
262
+ @lazy_transactions_enabled = true
263
+ end
264
+
265
+ def lazy_transactions_enabled?
266
+ @lazy_transactions_enabled
267
+ end
268
+
269
+ def materialize_transactions
270
+ return if @materializing_transactions
271
+ return unless @has_unmaterialized_transactions
272
+
273
+ @connection.lock.synchronize do
274
+ begin
275
+ @materializing_transactions = true
276
+ @stack.each { |t| t.materialize! unless t.materialized? }
277
+ ensure
278
+ @materializing_transactions = false
279
+ end
280
+ @has_unmaterialized_transactions = false
281
+ end
282
+ end
283
+
212
284
  def commit_transaction
213
285
  @connection.lock.synchronize do
214
286
  transaction = @stack.last
@@ -232,24 +304,40 @@ module ActiveRecord
232
304
  end
233
305
  end
234
306
 
235
- def within_new_transaction(options = {})
307
+ def within_new_transaction(isolation: nil, joinable: true)
236
308
  @connection.lock.synchronize do
237
- begin
238
- transaction = begin_transaction options
239
- yield
240
- rescue Exception => error
241
- if transaction
242
- rollback_transaction
243
- after_failure_actions(transaction, error)
244
- end
245
- raise
246
- ensure
247
- unless error
309
+ transaction = begin_transaction(isolation: isolation, joinable: joinable)
310
+ ret = yield
311
+ completed = true
312
+ ret
313
+ rescue Exception => error
314
+ if transaction
315
+ rollback_transaction
316
+ after_failure_actions(transaction, error)
317
+ end
318
+ raise
319
+ ensure
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?
325
+ else
248
326
  if Thread.current.status == "aborting"
249
- rollback_transaction if transaction
327
+ rollback_transaction
250
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
251
339
  begin
252
- commit_transaction if transaction
340
+ commit_transaction
253
341
  rescue Exception
254
342
  rollback_transaction(transaction) unless transaction.state.completed?
255
343
  raise
@@ -269,7 +357,6 @@ module ActiveRecord
269
357
  end
270
358
 
271
359
  private
272
-
273
360
  NULL_TRANSACTION = NullTransaction.new
274
361
 
275
362
  # Deallocate invalidated prepared statements outside of the transaction
@@ -1,6 +1,6 @@
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"
@@ -13,44 +13,6 @@ require "arel/collectors/substitute_binds"
13
13
 
14
14
  module ActiveRecord
15
15
  module ConnectionAdapters # :nodoc:
16
- extend ActiveSupport::Autoload
17
-
18
- autoload :Column
19
- autoload :ConnectionSpecification
20
-
21
- autoload_at "active_record/connection_adapters/abstract/schema_definitions" do
22
- autoload :IndexDefinition
23
- autoload :ColumnDefinition
24
- autoload :ChangeColumnDefinition
25
- autoload :ForeignKeyDefinition
26
- autoload :TableDefinition
27
- autoload :Table
28
- autoload :AlterTable
29
- autoload :ReferenceDefinition
30
- end
31
-
32
- autoload_at "active_record/connection_adapters/abstract/connection_pool" do
33
- autoload :ConnectionHandler
34
- end
35
-
36
- autoload_under "abstract" do
37
- autoload :SchemaStatements
38
- autoload :DatabaseStatements
39
- autoload :DatabaseLimits
40
- autoload :Quoting
41
- autoload :ConnectionPool
42
- autoload :QueryCache
43
- autoload :Savepoints
44
- end
45
-
46
- autoload_at "active_record/connection_adapters/abstract/transaction" do
47
- autoload :TransactionManager
48
- autoload :NullTransaction
49
- autoload :RealTransaction
50
- autoload :SavepointTransaction
51
- autoload :TransactionState
52
- end
53
-
54
16
  # Active Record supports multiple database systems. AbstractAdapter and
55
17
  # related classes form the abstraction layer which makes this possible.
56
18
  # An AbstractAdapter represents a connection to a database, and provides an
@@ -65,7 +27,7 @@ module ActiveRecord
65
27
  # Most of the methods in the adapter are useful during migrations. Most
66
28
  # notably, the instance methods provided by SchemaStatements are very useful.
67
29
  class AbstractAdapter
68
- ADAPTER_NAME = "Abstract".freeze
30
+ ADAPTER_NAME = "Abstract"
69
31
  include ActiveSupport::Callbacks
70
32
  define_callbacks :checkout, :checkin
71
33
 
@@ -75,15 +37,18 @@ module ActiveRecord
75
37
  include Savepoints
76
38
 
77
39
  SIMPLE_INT = /\A\d+\z/
40
+ COMMENT_REGEX = %r{(?:\-\-.*\n)*|/\*(?:[^\*]|\*[^/])*\*/}m
78
41
 
79
- attr_accessor :visitor, :pool
80
- attr_reader :schema_cache, :owner, :logger, :prepared_statements, :lock
42
+ attr_accessor :pool
43
+ attr_reader :visitor, :owner, :logger, :lock
81
44
  alias :in_use? :owner
82
45
 
46
+ set_callback :checkin, :after, :enable_lazy_transactions!
47
+
83
48
  def self.type_cast_config_to_integer(config)
84
49
  if config.is_a?(Integer)
85
50
  config
86
- elsif config =~ SIMPLE_INT
51
+ elsif SIMPLE_INT.match?(config)
87
52
  config.to_i
88
53
  else
89
54
  config
@@ -98,6 +63,23 @@ module ActiveRecord
98
63
  end
99
64
  end
100
65
 
66
+ DEFAULT_READ_QUERY = [:begin, :commit, :explain, :release, :rollback, :savepoint, :select, :with] # :nodoc:
67
+ private_constant :DEFAULT_READ_QUERY
68
+
69
+ def self.build_read_query_regexp(*parts) # :nodoc:
70
+ parts += DEFAULT_READ_QUERY
71
+ parts = parts.map { |part| /#{part}/i }
72
+ /\A(?:[\(\s]|#{COMMENT_REGEX})*#{Regexp.union(*parts)}/
73
+ end
74
+
75
+ def self.quoted_column_names # :nodoc:
76
+ @quoted_column_names ||= {}
77
+ end
78
+
79
+ def self.quoted_table_names # :nodoc:
80
+ @quoted_table_names ||= {}
81
+ end
82
+
101
83
  def initialize(connection, logger = nil, config = {}) # :nodoc:
102
84
  super()
103
85
 
@@ -106,19 +88,44 @@ module ActiveRecord
106
88
  @instrumenter = ActiveSupport::Notifications.instrumenter
107
89
  @logger = logger
108
90
  @config = config
109
- @pool = nil
91
+ @pool = ActiveRecord::ConnectionAdapters::NullPool.new
110
92
  @idle_since = Concurrent.monotonic_time
111
- @schema_cache = SchemaCache.new self
112
- @quoted_column_names, @quoted_table_names = {}, {}
113
93
  @visitor = arel_visitor
94
+ @statements = build_statement_pool
114
95
  @lock = ActiveSupport::Concurrency::LoadInterlockAwareMonitor.new
115
96
 
116
- if self.class.type_cast_config_to_boolean(config.fetch(:prepared_statements) { true })
117
- @prepared_statements = true
118
- @visitor.extend(DetermineIfPreparableVisitor)
119
- else
120
- @prepared_statements = false
121
- end
97
+ @prepared_statements = self.class.type_cast_config_to_boolean(
98
+ config.fetch(:prepared_statements, true)
99
+ )
100
+
101
+ @advisory_locks_enabled = self.class.type_cast_config_to_boolean(
102
+ config.fetch(:advisory_locks, true)
103
+ )
104
+ end
105
+
106
+ def replica?
107
+ @config[:replica] || false
108
+ end
109
+
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.
120
+ #
121
+ # If the application is using the new connection handling
122
+ # will return true based on +current_preventing_writes+.
123
+ def preventing_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
122
129
  end
123
130
 
124
131
  def migrations_paths # :nodoc:
@@ -126,19 +133,52 @@ module ActiveRecord
126
133
  end
127
134
 
128
135
  def migration_context # :nodoc:
129
- MigrationContext.new(migrations_paths)
136
+ MigrationContext.new(migrations_paths, schema_migration)
137
+ end
138
+
139
+ def schema_migration # :nodoc:
140
+ @schema_migration ||= begin
141
+ conn = self
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"
147
+
148
+ Class.new(ActiveRecord::SchemaMigration) do
149
+ define_singleton_method(:name) { schema_migration_name }
150
+ define_singleton_method(:to_s) { schema_migration_name }
151
+
152
+ self.connection_specification_name = spec_name
153
+ end
154
+ end
155
+ end
156
+
157
+ def prepared_statements
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
130
163
  end
131
164
 
132
165
  class Version
133
166
  include Comparable
134
167
 
135
- def initialize(version_string)
168
+ attr_reader :full_version_string
169
+
170
+ def initialize(version_string, full_version_string = nil)
136
171
  @version = version_string.split(".").map(&:to_i)
172
+ @full_version_string = full_version_string
137
173
  end
138
174
 
139
175
  def <=>(version_string)
140
176
  @version <=> version_string.split(".").map(&:to_i)
141
177
  end
178
+
179
+ def to_s
180
+ @version.join(".")
181
+ end
142
182
  end
143
183
 
144
184
  def valid_type?(type) # :nodoc:
@@ -148,7 +188,7 @@ module ActiveRecord
148
188
  # this method must only be called while holding connection pool's mutex
149
189
  def lease
150
190
  if in_use?
151
- msg = "Cannot lease connection, ".dup
191
+ msg = +"Cannot lease connection, "
152
192
  if @owner == Thread.current
153
193
  msg << "it is already leased by the current thread."
154
194
  else
@@ -161,9 +201,17 @@ module ActiveRecord
161
201
  @owner = Thread.current
162
202
  end
163
203
 
204
+ def connection_klass # :nodoc:
205
+ @pool.connection_klass
206
+ end
207
+
208
+ def schema_cache
209
+ @pool.get_schema_cache(self)
210
+ end
211
+
164
212
  def schema_cache=(cache)
165
213
  cache.connection = self
166
- @schema_cache = cache
214
+ @pool.set_schema_cache(cache)
167
215
  end
168
216
 
169
217
  # this method must only be called while holding connection pool's mutex
@@ -202,10 +250,10 @@ module ActiveRecord
202
250
  end
203
251
 
204
252
  def unprepared_statement
205
- old_prepared_statements, @prepared_statements = @prepared_statements, false
253
+ cache = prepared_statements_disabled_cache.add(object_id) if @prepared_statements
206
254
  yield
207
255
  ensure
208
- @prepared_statements = old_prepared_statements
256
+ cache&.delete(object_id)
209
257
  end
210
258
 
211
259
  # Returns the human-readable name of the adapter. Use mixed case - one
@@ -214,6 +262,11 @@ module ActiveRecord
214
262
  self.class::ADAPTER_NAME
215
263
  end
216
264
 
265
+ # Does the database for this adapter exist?
266
+ def self.database_exists?(config)
267
+ raise NotImplementedError
268
+ end
269
+
217
270
  # Does this adapter support DDL rollbacks in transactions? That is, would
218
271
  # CREATE TABLE or ALTER TABLE get rolled back by a transaction?
219
272
  def supports_ddl_transactions?
@@ -241,6 +294,10 @@ module ActiveRecord
241
294
  false
242
295
  end
243
296
 
297
+ def supports_partitioned_indexes?
298
+ false
299
+ end
300
+
244
301
  # Does this adapter support index sort order?
245
302
  def supports_index_sort_order?
246
303
  false
@@ -287,10 +344,9 @@ module ActiveRecord
287
344
  false
288
345
  end
289
346
 
290
- # Does this adapter support creating foreign key constraints
291
- # in the same statement as creating the table?
292
- def supports_foreign_keys_in_create?
293
- supports_foreign_keys?
347
+ # Does this adapter support creating check constraints?
348
+ def supports_check_constraints?
349
+ false
294
350
  end
295
351
 
296
352
  # Does this adapter support views?
@@ -298,6 +354,11 @@ module ActiveRecord
298
354
  false
299
355
  end
300
356
 
357
+ # Does this adapter support materialized views?
358
+ def supports_materialized_views?
359
+ false
360
+ end
361
+
301
362
  # Does this adapter support datetime with precision?
302
363
  def supports_datetime_with_precision?
303
364
  false
@@ -318,11 +379,6 @@ module ActiveRecord
318
379
  false
319
380
  end
320
381
 
321
- # Does this adapter support multi-value insert?
322
- def supports_multi_insert?
323
- true
324
- end
325
-
326
382
  # Does this adapter support virtual columns?
327
383
  def supports_virtual_columns?
328
384
  false
@@ -333,6 +389,35 @@ module ActiveRecord
333
389
  false
334
390
  end
335
391
 
392
+ # Does this adapter support optimizer hints?
393
+ def supports_optimizer_hints?
394
+ false
395
+ end
396
+
397
+ def supports_common_table_expressions?
398
+ false
399
+ end
400
+
401
+ def supports_lazy_transactions?
402
+ false
403
+ end
404
+
405
+ def supports_insert_returning?
406
+ false
407
+ end
408
+
409
+ def supports_insert_on_duplicate_skip?
410
+ false
411
+ end
412
+
413
+ def supports_insert_on_duplicate_update?
414
+ false
415
+ end
416
+
417
+ def supports_insert_conflict_target?
418
+ false
419
+ end
420
+
336
421
  # This is meant to be implemented by the adapters that support extensions
337
422
  def disable_extension(name)
338
423
  end
@@ -341,6 +426,10 @@ module ActiveRecord
341
426
  def enable_extension(name)
342
427
  end
343
428
 
429
+ def advisory_locks_enabled? # :nodoc:
430
+ supports_advisory_locks? && @advisory_locks_enabled
431
+ end
432
+
344
433
  # This is meant to be implemented by the adapters that support advisory
345
434
  # locks
346
435
  #
@@ -406,6 +495,9 @@ module ActiveRecord
406
495
  #
407
496
  # Prevent @connection's finalizer from touching the socket, or
408
497
  # otherwise communicating with its server, when it is collected.
498
+ if schema_cache.connection == self
499
+ schema_cache.connection = nil
500
+ end
409
501
  end
410
502
 
411
503
  # Reset the state of this connection, directing the DBMS to clear
@@ -418,11 +510,15 @@ module ActiveRecord
418
510
  # this should be overridden by concrete adapters
419
511
  end
420
512
 
421
- ###
422
- # Clear any caching the database adapter may be doing, for example
423
- # clearing the prepared statement cache. This is database specific.
513
+ # Removes the connection from the pool and disconnect it.
514
+ def throw_away!
515
+ pool.remove self
516
+ disconnect!
517
+ end
518
+
519
+ # Clear any caching the database adapter may be doing.
424
520
  def clear_cache!
425
- # this should be overridden by concrete adapters
521
+ @lock.synchronize { @statements.clear } if @statements
426
522
  end
427
523
 
428
524
  # Returns true if its required to reload the connection between requests for development mode.
@@ -444,18 +540,25 @@ module ActiveRecord
444
540
  # This is useful for when you need to call a proprietary method such as
445
541
  # PostgreSQL's lo_* methods.
446
542
  def raw_connection
543
+ disable_lazy_transactions!
447
544
  @connection
448
545
  end
449
546
 
450
- def case_sensitive_comparison(table, attribute, column, value) # :nodoc:
451
- table[attribute].eq(value)
547
+ def default_uniqueness_comparison(attribute, value) # :nodoc:
548
+ attribute.eq(value)
549
+ end
550
+
551
+ def case_sensitive_comparison(attribute, value) # :nodoc:
552
+ attribute.eq(value)
452
553
  end
453
554
 
454
- def case_insensitive_comparison(table, attribute, column, value) # :nodoc:
555
+ def case_insensitive_comparison(attribute, value) # :nodoc:
556
+ column = column_for_attribute(attribute)
557
+
455
558
  if can_perform_case_insensitive_comparison_for?(column)
456
- table[attribute].lower.eq(table.lower(value))
559
+ attribute.lower.eq(attribute.relation.lower(value))
457
560
  else
458
- table[attribute].eq(value)
561
+ attribute.eq(value)
459
562
  end
460
563
  end
461
564
 
@@ -469,16 +572,31 @@ module ActiveRecord
469
572
  pool.checkin self
470
573
  end
471
574
 
472
- def column_name_for_operation(operation, node) # :nodoc:
473
- column_name_from_arel_node(node)
575
+ def default_index_type?(index) # :nodoc:
576
+ index.using.nil?
474
577
  end
475
578
 
476
- def column_name_from_arel_node(node) # :nodoc:
477
- visitor.accept(node, Arel::Collectors::SQLString.new).value
579
+ # Called by ActiveRecord::InsertAll,
580
+ # Passed an instance of ActiveRecord::InsertAll::Builder,
581
+ # This method implements standard bulk inserts for all databases, but
582
+ # should be overridden by adapters to implement common features with
583
+ # non-standard syntax like handling duplicates or returning values.
584
+ def build_insert_sql(insert) # :nodoc:
585
+ if insert.skip_duplicates? || insert.update_duplicates?
586
+ raise NotImplementedError, "#{self.class} should define `build_insert_sql` to implement adapter-specific logic for handling duplicates during INSERT"
587
+ end
588
+
589
+ "INSERT #{insert.into} #{insert.values_list}"
478
590
  end
479
591
 
480
- def default_index_type?(index) # :nodoc:
481
- index.using.nil?
592
+ def get_database_version # :nodoc:
593
+ end
594
+
595
+ def database_version # :nodoc:
596
+ schema_cache.database_version
597
+ end
598
+
599
+ def check_version # :nodoc:
482
600
  end
483
601
 
484
602
  private
@@ -555,14 +673,12 @@ module ActiveRecord
555
673
  $1.to_i if sql_type =~ /\((.*)\)/
556
674
  end
557
675
 
558
- def translate_exception_class(e, sql)
559
- begin
560
- message = "#{e.class.name}: #{e.message}: #{sql}"
561
- rescue Encoding::CompatibilityError
562
- message = "#{e.class.name}: #{e.message.force_encoding sql.encoding}: #{sql}"
563
- end
676
+ def translate_exception_class(e, sql, binds)
677
+ message = "#{e.class.name}: #{e.message}"
564
678
 
565
- exception = translate_exception(e, message)
679
+ exception = translate_exception(
680
+ e, message: message, sql: sql, binds: binds
681
+ )
566
682
  exception.set_backtrace e.backtrace
567
683
  exception
568
684
  end
@@ -575,24 +691,22 @@ module ActiveRecord
575
691
  binds: binds,
576
692
  type_casted_binds: type_casted_binds,
577
693
  statement_name: statement_name,
578
- connection_id: object_id) do
579
- begin
580
- @lock.synchronize do
581
- yield
582
- end
583
- rescue => e
584
- raise translate_exception_class(e, sql)
694
+ connection: self) do
695
+ @lock.synchronize do
696
+ yield
585
697
  end
698
+ rescue => e
699
+ raise translate_exception_class(e, sql, binds)
586
700
  end
587
701
  end
588
702
 
589
- def translate_exception(exception, message)
703
+ def translate_exception(exception, message:, sql:, binds:)
590
704
  # override in derived class
591
705
  case exception
592
706
  when RuntimeError
593
707
  exception
594
708
  else
595
- ActiveRecord::StatementInvalid.new(message)
709
+ ActiveRecord::StatementInvalid.new(message, sql: sql, binds: binds)
596
710
  end
597
711
  end
598
712
 
@@ -606,6 +720,11 @@ module ActiveRecord
606
720
  raise(ActiveRecordError, "No such column: #{table_name}.#{column_name}")
607
721
  end
608
722
 
723
+ def column_for_attribute(attribute)
724
+ table_name = attribute.relation.name
725
+ schema_cache.columns_hash(table_name)[attribute.name.to_s]
726
+ end
727
+
609
728
  def collector
610
729
  if prepared_statements
611
730
  Arel::Collectors::Composite.new(
@@ -623,6 +742,17 @@ module ActiveRecord
623
742
  def arel_visitor
624
743
  Arel::Visitors::ToSql.new(self)
625
744
  end
745
+
746
+ def build_statement_pool
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
626
756
  end
627
757
  end
628
758
  end