activerecord 7.0.0 → 7.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (249) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +1607 -1040
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +17 -18
  5. data/lib/active_record/aggregations.rb +16 -13
  6. data/lib/active_record/association_relation.rb +1 -1
  7. data/lib/active_record/associations/association.rb +18 -3
  8. data/lib/active_record/associations/association_scope.rb +16 -9
  9. data/lib/active_record/associations/belongs_to_association.rb +14 -6
  10. data/lib/active_record/associations/builder/association.rb +3 -3
  11. data/lib/active_record/associations/builder/belongs_to.rb +21 -8
  12. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +1 -5
  13. data/lib/active_record/associations/builder/singular_association.rb +4 -0
  14. data/lib/active_record/associations/collection_association.rb +17 -12
  15. data/lib/active_record/associations/collection_proxy.rb +22 -12
  16. data/lib/active_record/associations/foreign_association.rb +10 -3
  17. data/lib/active_record/associations/has_many_association.rb +27 -17
  18. data/lib/active_record/associations/has_many_through_association.rb +10 -6
  19. data/lib/active_record/associations/has_one_association.rb +10 -3
  20. data/lib/active_record/associations/join_dependency.rb +20 -14
  21. data/lib/active_record/associations/preloader/association.rb +27 -6
  22. data/lib/active_record/associations/preloader/through_association.rb +1 -1
  23. data/lib/active_record/associations/preloader.rb +13 -10
  24. data/lib/active_record/associations/singular_association.rb +1 -1
  25. data/lib/active_record/associations/through_association.rb +22 -11
  26. data/lib/active_record/associations.rb +345 -219
  27. data/lib/active_record/attribute_assignment.rb +0 -2
  28. data/lib/active_record/attribute_methods/before_type_cast.rb +17 -0
  29. data/lib/active_record/attribute_methods/dirty.rb +40 -26
  30. data/lib/active_record/attribute_methods/primary_key.rb +76 -24
  31. data/lib/active_record/attribute_methods/query.rb +28 -16
  32. data/lib/active_record/attribute_methods/read.rb +18 -5
  33. data/lib/active_record/attribute_methods/serialization.rb +172 -69
  34. data/lib/active_record/attribute_methods/write.rb +3 -3
  35. data/lib/active_record/attribute_methods.rb +110 -28
  36. data/lib/active_record/attributes.rb +3 -3
  37. data/lib/active_record/autosave_association.rb +56 -10
  38. data/lib/active_record/base.rb +10 -5
  39. data/lib/active_record/callbacks.rb +16 -32
  40. data/lib/active_record/coders/column_serializer.rb +61 -0
  41. data/lib/active_record/coders/json.rb +1 -1
  42. data/lib/active_record/coders/yaml_column.rb +70 -34
  43. data/lib/active_record/connection_adapters/abstract/connection_handler.rb +164 -89
  44. data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +2 -0
  45. data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +3 -1
  46. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +63 -43
  47. data/lib/active_record/connection_adapters/abstract/database_limits.rb +5 -0
  48. data/lib/active_record/connection_adapters/abstract/database_statements.rb +128 -32
  49. data/lib/active_record/connection_adapters/abstract/query_cache.rb +60 -22
  50. data/lib/active_record/connection_adapters/abstract/quoting.rb +52 -8
  51. data/lib/active_record/connection_adapters/abstract/savepoints.rb +4 -3
  52. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +18 -4
  53. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +163 -29
  54. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +14 -1
  55. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +302 -129
  56. data/lib/active_record/connection_adapters/abstract/transaction.rb +287 -58
  57. data/lib/active_record/connection_adapters/abstract_adapter.rb +504 -106
  58. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +217 -104
  59. data/lib/active_record/connection_adapters/column.rb +9 -0
  60. data/lib/active_record/connection_adapters/mysql/column.rb +1 -0
  61. data/lib/active_record/connection_adapters/mysql/database_statements.rb +23 -144
  62. data/lib/active_record/connection_adapters/mysql/quoting.rb +29 -12
  63. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +9 -0
  64. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +10 -1
  65. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +8 -2
  66. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +38 -14
  67. data/lib/active_record/connection_adapters/mysql2/database_statements.rb +148 -0
  68. data/lib/active_record/connection_adapters/mysql2_adapter.rb +98 -53
  69. data/lib/active_record/connection_adapters/pool_config.rb +14 -5
  70. data/lib/active_record/connection_adapters/pool_manager.rb +19 -9
  71. data/lib/active_record/connection_adapters/postgresql/column.rb +3 -2
  72. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +72 -45
  73. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -1
  74. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +2 -2
  75. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +11 -2
  76. data/lib/active_record/connection_adapters/postgresql/oid/timestamp_with_time_zone.rb +3 -1
  77. data/lib/active_record/connection_adapters/postgresql/quoting.rb +41 -8
  78. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +6 -10
  79. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +76 -6
  80. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +131 -2
  81. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +53 -0
  82. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +358 -57
  83. data/lib/active_record/connection_adapters/postgresql/utils.rb +9 -10
  84. data/lib/active_record/connection_adapters/postgresql_adapter.rb +343 -181
  85. data/lib/active_record/connection_adapters/schema_cache.rb +287 -59
  86. data/lib/active_record/connection_adapters/sqlite3/column.rb +49 -0
  87. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +45 -39
  88. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +22 -5
  89. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +7 -0
  90. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +41 -22
  91. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +242 -81
  92. data/lib/active_record/connection_adapters/statement_pool.rb +7 -0
  93. data/lib/active_record/connection_adapters/trilogy/database_statements.rb +98 -0
  94. data/lib/active_record/connection_adapters/trilogy_adapter.rb +254 -0
  95. data/lib/active_record/connection_adapters.rb +3 -1
  96. data/lib/active_record/connection_handling.rb +73 -96
  97. data/lib/active_record/core.rb +136 -148
  98. data/lib/active_record/counter_cache.rb +46 -25
  99. data/lib/active_record/database_configurations/connection_url_resolver.rb +1 -0
  100. data/lib/active_record/database_configurations/database_config.rb +9 -3
  101. data/lib/active_record/database_configurations/hash_config.rb +22 -12
  102. data/lib/active_record/database_configurations/url_config.rb +17 -11
  103. data/lib/active_record/database_configurations.rb +87 -34
  104. data/lib/active_record/delegated_type.rb +9 -4
  105. data/lib/active_record/deprecator.rb +7 -0
  106. data/lib/active_record/destroy_association_async_job.rb +2 -0
  107. data/lib/active_record/disable_joins_association_relation.rb +1 -1
  108. data/lib/active_record/encryption/auto_filtered_parameters.rb +66 -0
  109. data/lib/active_record/encryption/cipher/aes256_gcm.rb +4 -1
  110. data/lib/active_record/encryption/config.rb +25 -1
  111. data/lib/active_record/encryption/configurable.rb +13 -14
  112. data/lib/active_record/encryption/context.rb +10 -3
  113. data/lib/active_record/encryption/contexts.rb +8 -4
  114. data/lib/active_record/encryption/derived_secret_key_provider.rb +9 -3
  115. data/lib/active_record/encryption/deterministic_key_provider.rb +1 -1
  116. data/lib/active_record/encryption/encryptable_record.rb +38 -22
  117. data/lib/active_record/encryption/encrypted_attribute_type.rb +19 -8
  118. data/lib/active_record/encryption/encryptor.rb +7 -7
  119. data/lib/active_record/encryption/envelope_encryption_key_provider.rb +3 -3
  120. data/lib/active_record/encryption/extended_deterministic_queries.rb +83 -71
  121. data/lib/active_record/encryption/extended_deterministic_uniqueness_validator.rb +3 -3
  122. data/lib/active_record/encryption/key_generator.rb +12 -1
  123. data/lib/active_record/encryption/message.rb +1 -1
  124. data/lib/active_record/encryption/message_serializer.rb +2 -0
  125. data/lib/active_record/encryption/properties.rb +4 -4
  126. data/lib/active_record/encryption/scheme.rb +20 -23
  127. data/lib/active_record/encryption.rb +1 -0
  128. data/lib/active_record/enum.rb +114 -27
  129. data/lib/active_record/errors.rb +108 -15
  130. data/lib/active_record/explain.rb +23 -3
  131. data/lib/active_record/explain_subscriber.rb +1 -1
  132. data/lib/active_record/fixture_set/model_metadata.rb +14 -4
  133. data/lib/active_record/fixture_set/render_context.rb +2 -0
  134. data/lib/active_record/fixture_set/table_row.rb +29 -8
  135. data/lib/active_record/fixtures.rb +121 -73
  136. data/lib/active_record/future_result.rb +30 -5
  137. data/lib/active_record/gem_version.rb +2 -2
  138. data/lib/active_record/inheritance.rb +30 -16
  139. data/lib/active_record/insert_all.rb +55 -8
  140. data/lib/active_record/integration.rb +10 -10
  141. data/lib/active_record/internal_metadata.rb +118 -30
  142. data/lib/active_record/locking/optimistic.rb +32 -18
  143. data/lib/active_record/locking/pessimistic.rb +8 -5
  144. data/lib/active_record/log_subscriber.rb +39 -17
  145. data/lib/active_record/marshalling.rb +56 -0
  146. data/lib/active_record/message_pack.rb +124 -0
  147. data/lib/active_record/middleware/database_selector/resolver.rb +4 -0
  148. data/lib/active_record/middleware/database_selector.rb +18 -13
  149. data/lib/active_record/middleware/shard_selector.rb +7 -5
  150. data/lib/active_record/migration/command_recorder.rb +104 -9
  151. data/lib/active_record/migration/compatibility.rb +158 -64
  152. data/lib/active_record/migration/default_strategy.rb +23 -0
  153. data/lib/active_record/migration/execution_strategy.rb +19 -0
  154. data/lib/active_record/migration.rb +271 -117
  155. data/lib/active_record/model_schema.rb +82 -50
  156. data/lib/active_record/nested_attributes.rb +23 -3
  157. data/lib/active_record/normalization.rb +159 -0
  158. data/lib/active_record/persistence.rb +200 -47
  159. data/lib/active_record/promise.rb +84 -0
  160. data/lib/active_record/query_cache.rb +3 -21
  161. data/lib/active_record/query_logs.rb +87 -51
  162. data/lib/active_record/query_logs_formatter.rb +41 -0
  163. data/lib/active_record/querying.rb +16 -3
  164. data/lib/active_record/railtie.rb +127 -61
  165. data/lib/active_record/railties/controller_runtime.rb +12 -8
  166. data/lib/active_record/railties/databases.rake +142 -143
  167. data/lib/active_record/railties/job_runtime.rb +23 -0
  168. data/lib/active_record/readonly_attributes.rb +32 -5
  169. data/lib/active_record/reflection.rb +177 -45
  170. data/lib/active_record/relation/batches/batch_enumerator.rb +5 -3
  171. data/lib/active_record/relation/batches.rb +190 -61
  172. data/lib/active_record/relation/calculations.rb +200 -83
  173. data/lib/active_record/relation/delegation.rb +23 -9
  174. data/lib/active_record/relation/finder_methods.rb +77 -16
  175. data/lib/active_record/relation/merger.rb +2 -0
  176. data/lib/active_record/relation/predicate_builder/association_query_value.rb +31 -3
  177. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +4 -6
  178. data/lib/active_record/relation/predicate_builder/relation_handler.rb +5 -1
  179. data/lib/active_record/relation/predicate_builder.rb +26 -14
  180. data/lib/active_record/relation/query_attribute.rb +25 -1
  181. data/lib/active_record/relation/query_methods.rb +429 -76
  182. data/lib/active_record/relation/spawn_methods.rb +18 -1
  183. data/lib/active_record/relation.rb +98 -41
  184. data/lib/active_record/result.rb +25 -9
  185. data/lib/active_record/runtime_registry.rb +10 -1
  186. data/lib/active_record/sanitization.rb +57 -16
  187. data/lib/active_record/schema.rb +36 -22
  188. data/lib/active_record/schema_dumper.rb +65 -23
  189. data/lib/active_record/schema_migration.rb +68 -33
  190. data/lib/active_record/scoping/default.rb +20 -12
  191. data/lib/active_record/scoping/named.rb +2 -2
  192. data/lib/active_record/scoping.rb +2 -1
  193. data/lib/active_record/secure_password.rb +60 -0
  194. data/lib/active_record/secure_token.rb +21 -3
  195. data/lib/active_record/serialization.rb +5 -0
  196. data/lib/active_record/signed_id.rb +9 -7
  197. data/lib/active_record/store.rb +16 -11
  198. data/lib/active_record/suppressor.rb +3 -1
  199. data/lib/active_record/table_metadata.rb +16 -3
  200. data/lib/active_record/tasks/database_tasks.rb +138 -107
  201. data/lib/active_record/tasks/mysql_database_tasks.rb +15 -6
  202. data/lib/active_record/tasks/postgresql_database_tasks.rb +17 -15
  203. data/lib/active_record/tasks/sqlite_database_tasks.rb +15 -7
  204. data/lib/active_record/test_fixtures.rb +123 -99
  205. data/lib/active_record/timestamp.rb +26 -14
  206. data/lib/active_record/token_for.rb +113 -0
  207. data/lib/active_record/touch_later.rb +11 -6
  208. data/lib/active_record/transactions.rb +39 -13
  209. data/lib/active_record/translation.rb +1 -1
  210. data/lib/active_record/type/adapter_specific_registry.rb +1 -8
  211. data/lib/active_record/type/internal/timezone.rb +7 -2
  212. data/lib/active_record/type/serialized.rb +8 -4
  213. data/lib/active_record/type/time.rb +4 -0
  214. data/lib/active_record/validations/absence.rb +1 -1
  215. data/lib/active_record/validations/associated.rb +3 -3
  216. data/lib/active_record/validations/numericality.rb +5 -4
  217. data/lib/active_record/validations/presence.rb +5 -28
  218. data/lib/active_record/validations/uniqueness.rb +50 -5
  219. data/lib/active_record/validations.rb +8 -4
  220. data/lib/active_record/version.rb +1 -1
  221. data/lib/active_record.rb +143 -16
  222. data/lib/arel/errors.rb +10 -0
  223. data/lib/arel/factory_methods.rb +4 -0
  224. data/lib/arel/filter_predications.rb +1 -1
  225. data/lib/arel/nodes/and.rb +4 -0
  226. data/lib/arel/nodes/binary.rb +6 -1
  227. data/lib/arel/nodes/bound_sql_literal.rb +61 -0
  228. data/lib/arel/nodes/cte.rb +36 -0
  229. data/lib/arel/nodes/filter.rb +1 -1
  230. data/lib/arel/nodes/fragments.rb +35 -0
  231. data/lib/arel/nodes/homogeneous_in.rb +0 -8
  232. data/lib/arel/nodes/leading_join.rb +8 -0
  233. data/lib/arel/nodes/node.rb +111 -2
  234. data/lib/arel/nodes/sql_literal.rb +6 -0
  235. data/lib/arel/nodes/table_alias.rb +4 -0
  236. data/lib/arel/nodes.rb +4 -0
  237. data/lib/arel/predications.rb +2 -0
  238. data/lib/arel/table.rb +9 -5
  239. data/lib/arel/visitors/mysql.rb +8 -1
  240. data/lib/arel/visitors/to_sql.rb +81 -17
  241. data/lib/arel/visitors/visitor.rb +2 -2
  242. data/lib/arel.rb +16 -2
  243. data/lib/rails/generators/active_record/application_record/USAGE +8 -0
  244. data/lib/rails/generators/active_record/migration.rb +3 -1
  245. data/lib/rails/generators/active_record/model/USAGE +113 -0
  246. data/lib/rails/generators/active_record/model/model_generator.rb +15 -6
  247. metadata +50 -15
  248. data/lib/active_record/connection_adapters/legacy_pool_manager.rb +0 -35
  249. data/lib/active_record/null_relation.rb +0 -63
@@ -4,6 +4,7 @@ require "set"
4
4
  require "active_record/connection_adapters/sql_type_metadata"
5
5
  require "active_record/connection_adapters/abstract/schema_dumper"
6
6
  require "active_record/connection_adapters/abstract/schema_creation"
7
+ require "active_support/concurrency/null_lock"
7
8
  require "active_support/concurrency/load_interlock_aware_monitor"
8
9
  require "arel/collectors/bind"
9
10
  require "arel/collectors/composite"
@@ -12,6 +13,8 @@ require "arel/collectors/substitute_binds"
12
13
 
13
14
  module ActiveRecord
14
15
  module ConnectionAdapters # :nodoc:
16
+ # = Active Record Abstract Adapter
17
+ #
15
18
  # Active Record supports multiple database systems. AbstractAdapter and
16
19
  # related classes form the abstraction layer which makes this possible.
17
20
  # An AbstractAdapter represents a connection to a database, and provides an
@@ -36,12 +39,20 @@ module ActiveRecord
36
39
  include Savepoints
37
40
 
38
41
  SIMPLE_INT = /\A\d+\z/
39
- COMMENT_REGEX = %r{(?:--.*\n)*|/\*(?:[^*]|\*[^/])*\*/}m
42
+ COMMENT_REGEX = %r{(?:--.*\n)|/\*(?:[^*]|\*[^/])*\*/}
40
43
 
41
- attr_accessor :pool
44
+ attr_reader :pool
42
45
  attr_reader :visitor, :owner, :logger, :lock
43
46
  alias :in_use? :owner
44
47
 
48
+ def pool=(value)
49
+ return if value.eql?(@pool)
50
+ @schema_cache = nil
51
+ @pool = value
52
+
53
+ @pool.schema_reflection.load!(self) if ActiveRecord.lazily_load_schema_cache
54
+ end
55
+
45
56
  set_callback :checkin, :after, :enable_lazy_transactions!
46
57
 
47
58
  def self.type_cast_config_to_integer(config)
@@ -62,6 +73,16 @@ module ActiveRecord
62
73
  end
63
74
  end
64
75
 
76
+ def self.validate_default_timezone(config)
77
+ case config
78
+ when nil
79
+ when "utc", "local"
80
+ config.to_sym
81
+ else
82
+ raise ArgumentError, "default_timezone must be either 'utc' or 'local'"
83
+ end
84
+ end
85
+
65
86
  DEFAULT_READ_QUERY = [:begin, :commit, :explain, :release, :rollback, :savepoint, :select, :with] # :nodoc:
66
87
  private_constant :DEFAULT_READ_QUERY
67
88
 
@@ -71,35 +92,104 @@ module ActiveRecord
71
92
  /\A(?:[(\s]|#{COMMENT_REGEX})*#{Regexp.union(*parts)}/
72
93
  end
73
94
 
74
- def self.quoted_column_names # :nodoc:
75
- @quoted_column_names ||= {}
95
+ def self.find_cmd_and_exec(commands, *args) # :doc:
96
+ commands = Array(commands)
97
+
98
+ dirs_on_path = ENV["PATH"].to_s.split(File::PATH_SEPARATOR)
99
+ unless (ext = RbConfig::CONFIG["EXEEXT"]).empty?
100
+ commands = commands.map { |cmd| "#{cmd}#{ext}" }
101
+ end
102
+
103
+ full_path_command = nil
104
+ found = commands.detect do |cmd|
105
+ dirs_on_path.detect do |path|
106
+ full_path_command = File.join(path, cmd)
107
+ begin
108
+ stat = File.stat(full_path_command)
109
+ rescue SystemCallError
110
+ else
111
+ stat.file? && stat.executable?
112
+ end
113
+ end
114
+ end
115
+
116
+ if found
117
+ exec full_path_command, *args
118
+ else
119
+ abort("Couldn't find database client: #{commands.join(', ')}. Check your $PATH and try again.")
120
+ end
76
121
  end
77
122
 
78
- def self.quoted_table_names # :nodoc:
79
- @quoted_table_names ||= {}
123
+ # Opens a database console session.
124
+ def self.dbconsole(config, options = {})
125
+ raise NotImplementedError
80
126
  end
81
127
 
82
- def initialize(connection, logger = nil, config = {}) # :nodoc:
128
+ def initialize(config_or_deprecated_connection, deprecated_logger = nil, deprecated_connection_options = nil, deprecated_config = nil) # :nodoc:
83
129
  super()
84
130
 
85
- @connection = connection
86
- @owner = nil
87
- @instrumenter = ActiveSupport::Notifications.instrumenter
88
- @logger = logger
89
- @config = config
90
- @pool = ActiveRecord::ConnectionAdapters::NullPool.new
91
- @idle_since = Process.clock_gettime(Process::CLOCK_MONOTONIC)
131
+ @raw_connection = nil
132
+ @unconfigured_connection = nil
133
+
134
+ if config_or_deprecated_connection.is_a?(Hash)
135
+ @config = config_or_deprecated_connection.symbolize_keys
136
+ @logger = ActiveRecord::Base.logger
137
+
138
+ if deprecated_logger || deprecated_connection_options || deprecated_config
139
+ raise ArgumentError, "when initializing an ActiveRecord adapter with a config hash, that should be the only argument"
140
+ end
141
+ else
142
+ # Soft-deprecated for now; we'll probably warn in future.
143
+
144
+ @unconfigured_connection = config_or_deprecated_connection
145
+ @logger = deprecated_logger || ActiveRecord::Base.logger
146
+ if deprecated_config
147
+ @config = (deprecated_config || {}).symbolize_keys
148
+ @connection_parameters = deprecated_connection_options
149
+ else
150
+ @config = (deprecated_connection_options || {}).symbolize_keys
151
+ @connection_parameters = nil
152
+ end
153
+ end
154
+
155
+ @owner = nil
156
+ @instrumenter = ActiveSupport::Notifications.instrumenter
157
+ @pool = ActiveRecord::ConnectionAdapters::NullPool.new
158
+ @idle_since = Process.clock_gettime(Process::CLOCK_MONOTONIC)
92
159
  @visitor = arel_visitor
93
160
  @statements = build_statement_pool
94
- @lock = ActiveSupport::Concurrency::LoadInterlockAwareMonitor.new
161
+ self.lock_thread = nil
95
162
 
96
- @prepared_statements = self.class.type_cast_config_to_boolean(
97
- config.fetch(:prepared_statements, true)
163
+ @prepared_statements = !ActiveRecord.disable_prepared_statements && self.class.type_cast_config_to_boolean(
164
+ @config.fetch(:prepared_statements) { default_prepared_statements }
98
165
  )
99
166
 
100
167
  @advisory_locks_enabled = self.class.type_cast_config_to_boolean(
101
- config.fetch(:advisory_locks, true)
168
+ @config.fetch(:advisory_locks, true)
102
169
  )
170
+
171
+ @default_timezone = self.class.validate_default_timezone(@config[:default_timezone])
172
+
173
+ @raw_connection_dirty = false
174
+ @verified = false
175
+ end
176
+
177
+ THREAD_LOCK = ActiveSupport::Concurrency::ThreadLoadInterlockAwareMonitor.new
178
+ private_constant :THREAD_LOCK
179
+
180
+ FIBER_LOCK = ActiveSupport::Concurrency::LoadInterlockAwareMonitor.new
181
+ private_constant :FIBER_LOCK
182
+
183
+ def lock_thread=(lock_thread) # :nodoc:
184
+ @lock =
185
+ case lock_thread
186
+ when Thread
187
+ THREAD_LOCK
188
+ when Fiber
189
+ FIBER_LOCK
190
+ else
191
+ ActiveSupport::Concurrency::NullLock
192
+ end
103
193
  end
104
194
 
105
195
  EXCEPTION_NEVER = { Exception => :never }.freeze # :nodoc:
@@ -129,18 +219,28 @@ module ActiveRecord
129
219
  @config.fetch(:use_metadata_table, true)
130
220
  end
131
221
 
222
+ def connection_retries
223
+ (@config[:connection_retries] || 1).to_i
224
+ end
225
+
226
+ def retry_deadline
227
+ if @config[:retry_deadline]
228
+ @config[:retry_deadline].to_f
229
+ else
230
+ nil
231
+ end
232
+ end
233
+
234
+ def default_timezone
235
+ @default_timezone || ActiveRecord.default_timezone
236
+ end
237
+
132
238
  # Determines whether writes are currently being prevented.
133
239
  #
134
- # Returns true if the connection is a replica.
135
- #
136
- # If the application is using legacy handling, returns
137
- # true if +connection_handler.prevent_writes+ is set.
138
- #
139
- # If the application is using the new connection handling
140
- # will return true based on +current_preventing_writes+.
240
+ # Returns true if the connection is a replica or returns
241
+ # the value of +current_preventing_writes+.
141
242
  def preventing_writes?
142
243
  return true if replica?
143
- return ActiveRecord::Base.connection_handler.prevent_writes if ActiveRecord.legacy_connection_handling
144
244
  return false if connection_class.nil?
145
245
 
146
246
  connection_class.current_preventing_writes
@@ -151,25 +251,15 @@ module ActiveRecord
151
251
  end
152
252
 
153
253
  def migration_context # :nodoc:
154
- MigrationContext.new(migrations_paths, schema_migration)
254
+ MigrationContext.new(migrations_paths, schema_migration, internal_metadata)
155
255
  end
156
256
 
157
257
  def schema_migration # :nodoc:
158
- @schema_migration ||= begin
159
- conn = self
160
- spec_name = conn.pool.pool_config.connection_specification_name
161
-
162
- return ActiveRecord::SchemaMigration if spec_name == "ActiveRecord::Base"
163
-
164
- schema_migration_name = "#{spec_name}::SchemaMigration"
165
-
166
- Class.new(ActiveRecord::SchemaMigration) do
167
- define_singleton_method(:name) { schema_migration_name }
168
- define_singleton_method(:to_s) { schema_migration_name }
258
+ SchemaMigration.new(self)
259
+ end
169
260
 
170
- self.connection_specification_name = spec_name
171
- end
172
- end
261
+ def internal_metadata # :nodoc:
262
+ InternalMetadata.new(self)
173
263
  end
174
264
 
175
265
  def prepared_statements?
@@ -208,50 +298,45 @@ module ActiveRecord
208
298
  def lease
209
299
  if in_use?
210
300
  msg = +"Cannot lease connection, "
211
- if @owner == Thread.current
301
+ if @owner == ActiveSupport::IsolatedExecutionState.context
212
302
  msg << "it is already leased by the current thread."
213
303
  else
214
304
  msg << "it is already in use by a different thread: #{@owner}. " \
215
- "Current thread: #{Thread.current}."
305
+ "Current thread: #{ActiveSupport::IsolatedExecutionState.context}."
216
306
  end
217
307
  raise ActiveRecordError, msg
218
308
  end
219
309
 
220
- @owner = Thread.current
310
+ @owner = ActiveSupport::IsolatedExecutionState.context
221
311
  end
222
312
 
223
313
  def connection_class # :nodoc:
224
314
  @pool.connection_class
225
315
  end
226
316
 
227
- # The role (ie :writing) for the current connection. In a
228
- # non-multi role application, `:writing` is returned.
317
+ # The role (e.g. +:writing+) for the current connection. In a
318
+ # non-multi role application, +:writing+ is returned.
229
319
  def role
230
320
  @pool.role
231
321
  end
232
322
 
233
- # The shard (ie :default) for the current connection. In
234
- # a non-sharded application, `:default` is returned.
323
+ # The shard (e.g. +:default+) for the current connection. In
324
+ # a non-sharded application, +:default+ is returned.
235
325
  def shard
236
326
  @pool.shard
237
327
  end
238
328
 
239
329
  def schema_cache
240
- @pool.get_schema_cache(self)
241
- end
242
-
243
- def schema_cache=(cache)
244
- cache.connection = self
245
- @pool.set_schema_cache(cache)
330
+ @schema_cache ||= BoundSchemaReflection.new(@pool.schema_reflection, self)
246
331
  end
247
332
 
248
333
  # this method must only be called while holding connection pool's mutex
249
334
  def expire
250
335
  if in_use?
251
- if @owner != Thread.current
336
+ if @owner != ActiveSupport::IsolatedExecutionState.context
252
337
  raise ActiveRecordError, "Cannot expire connection, " \
253
338
  "it is owned by a different thread: #{@owner}. " \
254
- "Current thread: #{Thread.current}."
339
+ "Current thread: #{ActiveSupport::IsolatedExecutionState.context}."
255
340
  end
256
341
 
257
342
  @idle_since = Process.clock_gettime(Process::CLOCK_MONOTONIC)
@@ -264,10 +349,10 @@ module ActiveRecord
264
349
  # this method must only be called while holding connection pool's mutex (and a desire for segfaults)
265
350
  def steal! # :nodoc:
266
351
  if in_use?
267
- if @owner != Thread.current
352
+ if @owner != ActiveSupport::IsolatedExecutionState.context
268
353
  pool.send :remove_connection_from_thread_cache, self, @owner
269
354
 
270
- @owner = Thread.current
355
+ @owner = ActiveSupport::IsolatedExecutionState.context
271
356
  end
272
357
  else
273
358
  raise ActiveRecordError, "Cannot steal connection, it is not currently leased."
@@ -295,7 +380,14 @@ module ActiveRecord
295
380
 
296
381
  # Does the database for this adapter exist?
297
382
  def self.database_exists?(config)
298
- raise NotImplementedError
383
+ new(config).database_exists?
384
+ end
385
+
386
+ def database_exists?
387
+ connect!
388
+ true
389
+ rescue ActiveRecord::NoDatabaseError
390
+ false
299
391
  end
300
392
 
301
393
  # Does this adapter support DDL rollbacks in transactions? That is, would
@@ -313,6 +405,16 @@ module ActiveRecord
313
405
  false
314
406
  end
315
407
 
408
+ # Do TransactionRollbackErrors on savepoints affect the parent
409
+ # transaction?
410
+ def savepoint_errors_invalidate_transactions?
411
+ false
412
+ end
413
+
414
+ def supports_restart_db_transaction?
415
+ false
416
+ end
417
+
316
418
  # Does this adapter support application-enforced advisory locking?
317
419
  def supports_advisory_locks?
318
420
  false
@@ -339,6 +441,11 @@ module ActiveRecord
339
441
  false
340
442
  end
341
443
 
444
+ # Does this adapter support including non-key columns?
445
+ def supports_index_include?
446
+ false
447
+ end
448
+
342
449
  # Does this adapter support expression indices?
343
450
  def supports_expression_index?
344
451
  false
@@ -385,6 +492,16 @@ module ActiveRecord
385
492
  false
386
493
  end
387
494
 
495
+ # Does this adapter support creating exclusion constraints?
496
+ def supports_exclusion_constraints?
497
+ false
498
+ end
499
+
500
+ # Does this adapter support creating unique constraints?
501
+ def supports_unique_constraints?
502
+ false
503
+ end
504
+
388
505
  # Does this adapter support views?
389
506
  def supports_views?
390
507
  false
@@ -400,7 +517,7 @@ module ActiveRecord
400
517
  false
401
518
  end
402
519
 
403
- # Does this adapter support json data type?
520
+ # Does this adapter support JSON data type?
404
521
  def supports_json?
405
522
  false
406
523
  end
@@ -458,23 +575,47 @@ module ActiveRecord
458
575
  true
459
576
  end
460
577
 
578
+ def supports_nulls_not_distinct?
579
+ false
580
+ end
581
+
582
+ def return_value_after_insert?(column) # :nodoc:
583
+ column.auto_incremented_by_db?
584
+ end
585
+
461
586
  def async_enabled? # :nodoc:
462
587
  supports_concurrent_connections? &&
463
588
  !ActiveRecord.async_query_executor.nil? && !pool.async_executor.nil?
464
589
  end
465
590
 
466
591
  # This is meant to be implemented by the adapters that support extensions
467
- def disable_extension(name)
592
+ def disable_extension(name, **)
468
593
  end
469
594
 
470
595
  # This is meant to be implemented by the adapters that support extensions
471
- def enable_extension(name)
596
+ def enable_extension(name, **)
472
597
  end
473
598
 
474
599
  # This is meant to be implemented by the adapters that support custom enum types
475
600
  def create_enum(*) # :nodoc:
476
601
  end
477
602
 
603
+ # This is meant to be implemented by the adapters that support custom enum types
604
+ def drop_enum(*) # :nodoc:
605
+ end
606
+
607
+ # This is meant to be implemented by the adapters that support custom enum types
608
+ def rename_enum(*) # :nodoc:
609
+ end
610
+
611
+ # This is meant to be implemented by the adapters that support custom enum types
612
+ def add_enum_value(*) # :nodoc:
613
+ end
614
+
615
+ # This is meant to be implemented by the adapters that support custom enum types
616
+ def rename_enum_value(*) # :nodoc:
617
+ end
618
+
478
619
  def advisory_locks_enabled? # :nodoc:
479
620
  supports_advisory_locks? && @advisory_locks_enabled
480
621
  end
@@ -512,7 +653,17 @@ module ActiveRecord
512
653
 
513
654
  # Override to check all foreign key constraints in a database.
514
655
  def all_foreign_keys_valid?
656
+ check_all_foreign_keys_valid!
515
657
  true
658
+ rescue ActiveRecord::StatementInvalid
659
+ false
660
+ end
661
+ deprecate :all_foreign_keys_valid?, deprecator: ActiveRecord.deprecator
662
+
663
+ # Override to check all foreign key constraints in a database.
664
+ # The adapter should raise a +ActiveRecord::StatementInvalid+ if foreign key
665
+ # constraints are not met.
666
+ def check_all_foreign_keys_valid!
516
667
  end
517
668
 
518
669
  # CONNECTION MANAGEMENT ====================================
@@ -523,19 +674,50 @@ module ActiveRecord
523
674
  def active?
524
675
  end
525
676
 
526
- # Disconnects from the database if already connected, and establishes a
527
- # new connection with the database. Implementors should call super if they
528
- # override the default implementation.
529
- def reconnect!
530
- clear_cache!
531
- reset_transaction
677
+ # Disconnects from the database if already connected, and establishes a new
678
+ # connection with the database. Implementors should define private #reconnect
679
+ # instead.
680
+ def reconnect!(restore_transactions: false)
681
+ retries_available = connection_retries
682
+ deadline = retry_deadline && Process.clock_gettime(Process::CLOCK_MONOTONIC) + retry_deadline
683
+
684
+ @lock.synchronize do
685
+ reconnect
686
+
687
+ enable_lazy_transactions!
688
+ @raw_connection_dirty = false
689
+ @verified = true
690
+
691
+ reset_transaction(restore: restore_transactions) do
692
+ clear_cache!(new_connection: true)
693
+ configure_connection
694
+ end
695
+ rescue => original_exception
696
+ translated_exception = translate_exception_class(original_exception, nil, nil)
697
+ retry_deadline_exceeded = deadline && deadline < Process.clock_gettime(Process::CLOCK_MONOTONIC)
698
+
699
+ if !retry_deadline_exceeded && retries_available > 0
700
+ retries_available -= 1
701
+
702
+ if retryable_connection_error?(translated_exception)
703
+ backoff(connection_retries - retries_available)
704
+ retry
705
+ end
706
+ end
707
+
708
+ @verified = false
709
+
710
+ raise translated_exception
711
+ end
532
712
  end
533
713
 
714
+
534
715
  # Disconnects from the database if already connected. Otherwise, this
535
716
  # method does nothing.
536
717
  def disconnect!
537
- clear_cache!
718
+ clear_cache!(new_connection: true)
538
719
  reset_transaction
720
+ @raw_connection_dirty = false
539
721
  end
540
722
 
541
723
  # Immediately forget this connection ever existed. Unlike disconnect!,
@@ -546,22 +728,20 @@ module ActiveRecord
546
728
  # rid of a connection that belonged to its parent.
547
729
  def discard!
548
730
  # This should be overridden by concrete adapters.
549
- #
550
- # Prevent @connection's finalizer from touching the socket, or
551
- # otherwise communicating with its server, when it is collected.
552
- if schema_cache.connection == self
553
- schema_cache.connection = nil
554
- end
555
731
  end
556
732
 
557
733
  # Reset the state of this connection, directing the DBMS to clear
558
734
  # transactions and other connection-related server-side state. Usually a
559
735
  # database-dependent operation.
560
736
  #
561
- # The default implementation does nothing; the implementation should be
562
- # overridden by concrete adapters.
737
+ # If a database driver or protocol does not support such a feature,
738
+ # implementors may alias this to #reconnect!. Otherwise, implementors
739
+ # should call super immediately after resetting the connection (and while
740
+ # still holding @lock).
563
741
  def reset!
564
- # this should be overridden by concrete adapters
742
+ clear_cache!(new_connection: true)
743
+ reset_transaction
744
+ configure_connection
565
745
  end
566
746
 
567
747
  # Removes the connection from the pool and disconnect it.
@@ -571,8 +751,16 @@ module ActiveRecord
571
751
  end
572
752
 
573
753
  # Clear any caching the database adapter may be doing.
574
- def clear_cache!
575
- @lock.synchronize { @statements.clear } if @statements
754
+ def clear_cache!(new_connection: false)
755
+ if @statements
756
+ @lock.synchronize do
757
+ if new_connection
758
+ @statements.reset
759
+ else
760
+ @statements.clear
761
+ end
762
+ end
763
+ end
576
764
  end
577
765
 
578
766
  # Returns true if its required to reload the connection between requests for development mode.
@@ -584,7 +772,33 @@ module ActiveRecord
584
772
  # This is done under the hood by calling #active?. If the connection
585
773
  # is no longer active, then this method will reconnect to the database.
586
774
  def verify!
587
- reconnect! unless active?
775
+ unless active?
776
+ if @unconfigured_connection
777
+ @lock.synchronize do
778
+ if @unconfigured_connection
779
+ @raw_connection = @unconfigured_connection
780
+ @unconfigured_connection = nil
781
+ configure_connection
782
+ @verified = true
783
+ return
784
+ end
785
+ end
786
+ end
787
+
788
+ reconnect!(restore_transactions: true)
789
+ end
790
+
791
+ @verified = true
792
+ end
793
+
794
+ def connect!
795
+ verify!
796
+ self
797
+ end
798
+
799
+ def clean! # :nodoc:
800
+ @raw_connection_dirty = false
801
+ @verified = nil
588
802
  end
589
803
 
590
804
  # Provides access to the underlying database driver for this adapter. For
@@ -593,9 +807,16 @@ module ActiveRecord
593
807
  #
594
808
  # This is useful for when you need to call a proprietary method such as
595
809
  # PostgreSQL's lo_* methods.
810
+ #
811
+ # Active Record cannot track if the database is getting modified using
812
+ # this client. If that is the case, generally you'll want to invalidate
813
+ # the query cache using +ActiveRecord::Base.clear_query_cache+.
596
814
  def raw_connection
597
- disable_lazy_transactions!
598
- @connection
815
+ with_raw_connection do |conn|
816
+ disable_lazy_transactions!
817
+ @raw_connection_dirty = true
818
+ conn
819
+ end
599
820
  end
600
821
 
601
822
  def default_uniqueness_comparison(attribute, value) # :nodoc:
@@ -661,16 +882,22 @@ module ActiveRecord
661
882
  migration_context.current_version
662
883
  end
663
884
 
664
- def field_ordered_value(column, values) # :nodoc:
665
- node = Arel::Nodes::Case.new(column)
666
- values.each.with_index(1) do |value, order|
667
- node.when(value).then(order)
885
+ class << self
886
+ def register_class_with_precision(mapping, key, klass, **kwargs) # :nodoc:
887
+ mapping.register_type(key) do |*args|
888
+ precision = extract_precision(args.last)
889
+ klass.new(precision: precision, **kwargs)
890
+ end
668
891
  end
669
892
 
670
- Arel::Nodes::Ascending.new(node.else(values.length + 1))
671
- end
893
+ def extended_type_map(default_timezone:) # :nodoc:
894
+ Type::TypeMap.new(self::TYPE_MAP).tap do |m|
895
+ register_class_with_precision m, %r(\A[^\(]*time)i, Type::Time, timezone: default_timezone
896
+ register_class_with_precision m, %r(\A[^\(]*datetime)i, Type::DateTime, timezone: default_timezone
897
+ m.alias_type %r(\A[^\(]*timestamp)i, "datetime"
898
+ end
899
+ end
672
900
 
673
- class << self
674
901
  private
675
902
  def initialize_type_map(m)
676
903
  register_class_with_limit m, %r(boolean)i, Type::Boolean
@@ -712,13 +939,6 @@ module ActiveRecord
712
939
  end
713
940
  end
714
941
 
715
- def register_class_with_precision(mapping, key, klass)
716
- mapping.register_type(key) do |*args|
717
- precision = extract_precision(args.last)
718
- klass.new(precision: precision)
719
- end
720
- end
721
-
722
942
  def extract_scale(sql_type)
723
943
  case sql_type
724
944
  when /\((\d+)\)/ then 0
@@ -736,10 +956,168 @@ module ActiveRecord
736
956
  end
737
957
 
738
958
  TYPE_MAP = Type::TypeMap.new.tap { |m| initialize_type_map(m) }
959
+ EXTENDED_TYPE_MAPS = Concurrent::Map.new
739
960
 
740
961
  private
962
+ def reconnect_can_restore_state?
963
+ transaction_manager.restorable? && !@raw_connection_dirty
964
+ end
965
+
966
+ # Lock the monitor, ensure we're properly connected and
967
+ # transactions are materialized, and then yield the underlying
968
+ # raw connection object.
969
+ #
970
+ # If +allow_retry+ is true, a connection-related exception will
971
+ # cause an automatic reconnect and re-run of the block, up to
972
+ # the connection's configured +connection_retries+ setting
973
+ # and the configured +retry_deadline+ limit.
974
+ #
975
+ # If +materialize_transactions+ is false, the block will be run without
976
+ # ensuring virtual transactions have been materialized in the DB
977
+ # server's state. The active transaction will also remain clean
978
+ # (if it is not already dirty), meaning it's able to be restored
979
+ # by reconnecting and opening an equivalent-depth set of new
980
+ # transactions. This should only be used by transaction control
981
+ # methods, and internal transaction-agnostic queries.
982
+ #
983
+ ###
984
+ #
985
+ # It's not the primary use case, so not something to optimize
986
+ # for, but note that this method does need to be re-entrant:
987
+ # +materialize_transactions+ will re-enter if it has work to do,
988
+ # and the yield block can also do so under some circumstances.
989
+ #
990
+ # In the latter case, we really ought to guarantee the inner
991
+ # call will not reconnect (which would interfere with the
992
+ # still-yielded connection in the outer block), but we currently
993
+ # provide no special enforcement there.
994
+ #
995
+ def with_raw_connection(allow_retry: false, materialize_transactions: true)
996
+ @lock.synchronize do
997
+ connect! if @raw_connection.nil? && reconnect_can_restore_state?
998
+
999
+ self.materialize_transactions if materialize_transactions
1000
+
1001
+ retries_available = allow_retry ? connection_retries : 0
1002
+ deadline = retry_deadline && Process.clock_gettime(Process::CLOCK_MONOTONIC) + retry_deadline
1003
+ reconnectable = reconnect_can_restore_state?
1004
+
1005
+ if @verified
1006
+ # Cool, we're confident the connection's ready to use. (Note this might have
1007
+ # become true during the above #materialize_transactions.)
1008
+ elsif reconnectable
1009
+ if allow_retry
1010
+ # Not sure about the connection yet, but if anything goes wrong we can
1011
+ # just reconnect and re-run our query
1012
+ else
1013
+ # We can reconnect if needed, but we don't trust the upcoming query to be
1014
+ # safely re-runnable: let's verify the connection to be sure
1015
+ verify!
1016
+ end
1017
+ else
1018
+ # We don't know whether the connection is okay, but it also doesn't matter:
1019
+ # we wouldn't be able to reconnect anyway. We're just going to run our query
1020
+ # and hope for the best.
1021
+ end
1022
+
1023
+ begin
1024
+ result = yield @raw_connection
1025
+ @verified = true
1026
+ result
1027
+ rescue => original_exception
1028
+ translated_exception = translate_exception_class(original_exception, nil, nil)
1029
+ invalidate_transaction(translated_exception)
1030
+ retry_deadline_exceeded = deadline && deadline < Process.clock_gettime(Process::CLOCK_MONOTONIC)
1031
+
1032
+ if !retry_deadline_exceeded && retries_available > 0
1033
+ retries_available -= 1
1034
+
1035
+ if retryable_query_error?(translated_exception)
1036
+ backoff(connection_retries - retries_available)
1037
+ retry
1038
+ elsif reconnectable && retryable_connection_error?(translated_exception)
1039
+ reconnect!(restore_transactions: true)
1040
+ # Only allowed to reconnect once, because reconnect! has its own retry
1041
+ # loop
1042
+ reconnectable = false
1043
+ retry
1044
+ end
1045
+ end
1046
+
1047
+ unless retryable_query_error?(translated_exception)
1048
+ # Barring a known-retryable error inside the query (regardless of
1049
+ # whether we were in a _position_ to retry it), we should infer that
1050
+ # there's likely a real problem with the connection.
1051
+ @verified = false
1052
+ end
1053
+
1054
+ raise translated_exception
1055
+ ensure
1056
+ dirty_current_transaction if materialize_transactions
1057
+ end
1058
+ end
1059
+ end
1060
+
1061
+ def retryable_connection_error?(exception)
1062
+ exception.is_a?(ConnectionNotEstablished) || exception.is_a?(ConnectionFailed)
1063
+ end
1064
+
1065
+ def invalidate_transaction(exception)
1066
+ return unless exception.is_a?(TransactionRollbackError)
1067
+ return unless savepoint_errors_invalidate_transactions?
1068
+
1069
+ current_transaction.invalidate!
1070
+ end
1071
+
1072
+ def retryable_query_error?(exception)
1073
+ # We definitely can't retry if we were inside an invalidated transaction.
1074
+ return false if current_transaction.invalidated?
1075
+
1076
+ exception.is_a?(Deadlocked) || exception.is_a?(LockWaitTimeout)
1077
+ end
1078
+
1079
+ def backoff(counter)
1080
+ sleep 0.1 * counter
1081
+ end
1082
+
1083
+ def reconnect
1084
+ raise NotImplementedError
1085
+ end
1086
+
1087
+ # Returns a raw connection for internal use with methods that are known
1088
+ # to both be thread-safe and not rely upon actual server communication.
1089
+ # This is useful for e.g. string escaping methods.
1090
+ def any_raw_connection
1091
+ @raw_connection || valid_raw_connection
1092
+ end
1093
+
1094
+ # Similar to any_raw_connection, but ensures it is validated and
1095
+ # connected. Any method called on this result still needs to be
1096
+ # independently thread-safe, so it probably shouldn't talk to the
1097
+ # server... but some drivers fail if they know the connection has gone
1098
+ # away.
1099
+ def valid_raw_connection
1100
+ (@verified && @raw_connection) ||
1101
+ # `allow_retry: false`, to force verification: the block won't
1102
+ # raise, so a retry wouldn't help us get the valid connection we
1103
+ # need.
1104
+ with_raw_connection(allow_retry: false, materialize_transactions: false) { |conn| conn }
1105
+ end
1106
+
1107
+ def extended_type_map_key
1108
+ if @default_timezone
1109
+ { default_timezone: @default_timezone }
1110
+ end
1111
+ end
1112
+
741
1113
  def type_map
742
- TYPE_MAP
1114
+ if key = extended_type_map_key
1115
+ self.class::EXTENDED_TYPE_MAPS.compute_if_absent(key) do
1116
+ self.class.extended_type_map(**key)
1117
+ end
1118
+ else
1119
+ self.class::TYPE_MAP
1120
+ end
743
1121
  end
744
1122
 
745
1123
  def translate_exception_class(e, sql, binds)
@@ -761,16 +1139,16 @@ module ActiveRecord
761
1139
  type_casted_binds: type_casted_binds,
762
1140
  statement_name: statement_name,
763
1141
  async: async,
764
- connection: self) do
765
- @lock.synchronize(&block)
766
- rescue => e
767
- raise translate_exception_class(e, sql, binds)
768
- end
1142
+ connection: self,
1143
+ &block
1144
+ )
1145
+ rescue ActiveRecord::StatementInvalid => ex
1146
+ raise ex.set_query(sql, binds)
769
1147
  end
770
1148
 
771
1149
  def transform_query(sql)
772
1150
  ActiveRecord.query_transformers.each do |transformer|
773
- sql = transformer.call(sql)
1151
+ sql = transformer.call(sql, self)
774
1152
  end
775
1153
  sql
776
1154
  end
@@ -778,10 +1156,10 @@ module ActiveRecord
778
1156
  def translate_exception(exception, message:, sql:, binds:)
779
1157
  # override in derived class
780
1158
  case exception
781
- when RuntimeError
1159
+ when RuntimeError, ActiveRecord::ActiveRecordError
782
1160
  exception
783
1161
  else
784
- ActiveRecord::StatementInvalid.new(message, sql: sql, binds: binds)
1162
+ ActiveRecord::StatementInvalid.new(message, sql: sql, binds: binds, connection_pool: @pool)
785
1163
  end
786
1164
  end
787
1165
 
@@ -828,6 +1206,26 @@ module ActiveRecord
828
1206
  def build_result(columns:, rows:, column_types: {})
829
1207
  ActiveRecord::Result.new(columns, rows, column_types)
830
1208
  end
1209
+
1210
+ # Perform any necessary initialization upon the newly-established
1211
+ # @raw_connection -- this is the place to modify the adapter's
1212
+ # connection settings, run queries to configure any application-global
1213
+ # "session" variables, etc.
1214
+ #
1215
+ # Implementations may assume this method will only be called while
1216
+ # holding @lock (or from #initialize).
1217
+ def configure_connection
1218
+ end
1219
+
1220
+ def default_prepared_statements
1221
+ true
1222
+ end
1223
+
1224
+ def warning_ignored?(warning)
1225
+ ActiveRecord.db_warnings_ignore.any? do |warning_matcher|
1226
+ warning.message.match?(warning_matcher) || warning.code.to_s.match?(warning_matcher)
1227
+ end
1228
+ end
831
1229
  end
832
1230
  end
833
1231
  end