activerecord 6.1.3.2 → 7.0.0.alpha2

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 (229) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +734 -1058
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +1 -1
  5. data/lib/active_record/aggregations.rb +1 -1
  6. data/lib/active_record/association_relation.rb +0 -10
  7. data/lib/active_record/associations/association.rb +35 -7
  8. data/lib/active_record/associations/association_scope.rb +1 -3
  9. data/lib/active_record/associations/belongs_to_association.rb +16 -6
  10. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +10 -2
  11. data/lib/active_record/associations/builder/association.rb +8 -2
  12. data/lib/active_record/associations/builder/belongs_to.rb +19 -6
  13. data/lib/active_record/associations/builder/collection_association.rb +1 -1
  14. data/lib/active_record/associations/builder/has_many.rb +3 -2
  15. data/lib/active_record/associations/builder/has_one.rb +2 -1
  16. data/lib/active_record/associations/builder/singular_association.rb +2 -2
  17. data/lib/active_record/associations/collection_association.rb +24 -25
  18. data/lib/active_record/associations/collection_proxy.rb +8 -3
  19. data/lib/active_record/associations/disable_joins_association_scope.rb +59 -0
  20. data/lib/active_record/associations/has_many_association.rb +1 -1
  21. data/lib/active_record/associations/has_many_through_association.rb +2 -1
  22. data/lib/active_record/associations/has_one_association.rb +10 -7
  23. data/lib/active_record/associations/has_one_through_association.rb +1 -1
  24. data/lib/active_record/associations/preloader/association.rb +161 -49
  25. data/lib/active_record/associations/preloader/batch.rb +51 -0
  26. data/lib/active_record/associations/preloader/branch.rb +147 -0
  27. data/lib/active_record/associations/preloader/through_association.rb +37 -11
  28. data/lib/active_record/associations/preloader.rb +46 -110
  29. data/lib/active_record/associations/singular_association.rb +8 -2
  30. data/lib/active_record/associations/through_association.rb +1 -1
  31. data/lib/active_record/associations.rb +76 -81
  32. data/lib/active_record/asynchronous_queries_tracker.rb +57 -0
  33. data/lib/active_record/attribute_assignment.rb +1 -1
  34. data/lib/active_record/attribute_methods/before_type_cast.rb +7 -2
  35. data/lib/active_record/attribute_methods/dirty.rb +41 -16
  36. data/lib/active_record/attribute_methods/primary_key.rb +2 -2
  37. data/lib/active_record/attribute_methods/query.rb +2 -2
  38. data/lib/active_record/attribute_methods/read.rb +7 -5
  39. data/lib/active_record/attribute_methods/serialization.rb +66 -12
  40. data/lib/active_record/attribute_methods/time_zone_conversion.rb +4 -3
  41. data/lib/active_record/attribute_methods/write.rb +7 -10
  42. data/lib/active_record/attribute_methods.rb +6 -9
  43. data/lib/active_record/attributes.rb +24 -35
  44. data/lib/active_record/autosave_association.rb +3 -18
  45. data/lib/active_record/base.rb +19 -1
  46. data/lib/active_record/callbacks.rb +2 -2
  47. data/lib/active_record/coders/yaml_column.rb +11 -1
  48. data/lib/active_record/connection_adapters/abstract/connection_handler.rb +312 -0
  49. data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +209 -0
  50. data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +76 -0
  51. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +31 -558
  52. data/lib/active_record/connection_adapters/abstract/database_statements.rb +45 -21
  53. data/lib/active_record/connection_adapters/abstract/query_cache.rb +24 -12
  54. data/lib/active_record/connection_adapters/abstract/quoting.rb +14 -7
  55. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +5 -18
  56. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +30 -9
  57. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +60 -16
  58. data/lib/active_record/connection_adapters/abstract/transaction.rb +17 -6
  59. data/lib/active_record/connection_adapters/abstract_adapter.rb +115 -69
  60. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +96 -81
  61. data/lib/active_record/connection_adapters/legacy_pool_manager.rb +6 -2
  62. data/lib/active_record/connection_adapters/mysql/database_statements.rb +33 -21
  63. data/lib/active_record/connection_adapters/mysql/quoting.rb +16 -1
  64. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +3 -0
  65. data/lib/active_record/connection_adapters/mysql2_adapter.rb +12 -6
  66. data/lib/active_record/connection_adapters/pool_config.rb +1 -3
  67. data/lib/active_record/connection_adapters/pool_manager.rb +5 -1
  68. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +19 -12
  69. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +8 -0
  70. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +5 -0
  71. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +53 -14
  72. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +1 -1
  73. data/lib/active_record/connection_adapters/postgresql/oid/timestamp.rb +15 -0
  74. data/lib/active_record/connection_adapters/postgresql/oid/timestamp_with_time_zone.rb +28 -0
  75. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +18 -6
  76. data/lib/active_record/connection_adapters/postgresql/oid.rb +2 -0
  77. data/lib/active_record/connection_adapters/postgresql/quoting.rb +6 -6
  78. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +32 -0
  79. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +5 -1
  80. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +12 -12
  81. data/lib/active_record/connection_adapters/postgresql_adapter.rb +157 -100
  82. data/lib/active_record/connection_adapters/schema_cache.rb +35 -4
  83. data/lib/active_record/connection_adapters/sql_type_metadata.rb +0 -2
  84. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +23 -17
  85. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +4 -2
  86. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +61 -30
  87. data/lib/active_record/connection_adapters.rb +8 -5
  88. data/lib/active_record/connection_handling.rb +20 -38
  89. data/lib/active_record/core.rb +129 -117
  90. data/lib/active_record/database_configurations/database_config.rb +12 -0
  91. data/lib/active_record/database_configurations/hash_config.rb +27 -1
  92. data/lib/active_record/database_configurations/url_config.rb +2 -2
  93. data/lib/active_record/database_configurations.rb +18 -9
  94. data/lib/active_record/delegated_type.rb +33 -11
  95. data/lib/active_record/destroy_association_async_job.rb +1 -1
  96. data/lib/active_record/disable_joins_association_relation.rb +39 -0
  97. data/lib/active_record/dynamic_matchers.rb +1 -1
  98. data/lib/active_record/encryption/cipher/aes256_gcm.rb +98 -0
  99. data/lib/active_record/encryption/cipher.rb +53 -0
  100. data/lib/active_record/encryption/config.rb +44 -0
  101. data/lib/active_record/encryption/configurable.rb +61 -0
  102. data/lib/active_record/encryption/context.rb +35 -0
  103. data/lib/active_record/encryption/contexts.rb +72 -0
  104. data/lib/active_record/encryption/derived_secret_key_provider.rb +12 -0
  105. data/lib/active_record/encryption/deterministic_key_provider.rb +14 -0
  106. data/lib/active_record/encryption/encryptable_record.rb +208 -0
  107. data/lib/active_record/encryption/encrypted_attribute_type.rb +140 -0
  108. data/lib/active_record/encryption/encrypted_fixtures.rb +38 -0
  109. data/lib/active_record/encryption/encrypting_only_encryptor.rb +12 -0
  110. data/lib/active_record/encryption/encryptor.rb +155 -0
  111. data/lib/active_record/encryption/envelope_encryption_key_provider.rb +55 -0
  112. data/lib/active_record/encryption/errors.rb +15 -0
  113. data/lib/active_record/encryption/extended_deterministic_queries.rb +160 -0
  114. data/lib/active_record/encryption/extended_deterministic_uniqueness_validator.rb +29 -0
  115. data/lib/active_record/encryption/key.rb +28 -0
  116. data/lib/active_record/encryption/key_generator.rb +42 -0
  117. data/lib/active_record/encryption/key_provider.rb +46 -0
  118. data/lib/active_record/encryption/message.rb +33 -0
  119. data/lib/active_record/encryption/message_serializer.rb +80 -0
  120. data/lib/active_record/encryption/null_encryptor.rb +21 -0
  121. data/lib/active_record/encryption/properties.rb +76 -0
  122. data/lib/active_record/encryption/read_only_null_encryptor.rb +24 -0
  123. data/lib/active_record/encryption/scheme.rb +99 -0
  124. data/lib/active_record/encryption.rb +55 -0
  125. data/lib/active_record/enum.rb +44 -46
  126. data/lib/active_record/errors.rb +66 -3
  127. data/lib/active_record/fixture_set/file.rb +15 -1
  128. data/lib/active_record/fixture_set/table_row.rb +40 -5
  129. data/lib/active_record/fixture_set/table_rows.rb +4 -4
  130. data/lib/active_record/fixtures.rb +16 -11
  131. data/lib/active_record/future_result.rb +139 -0
  132. data/lib/active_record/gem_version.rb +4 -4
  133. data/lib/active_record/inheritance.rb +55 -17
  134. data/lib/active_record/insert_all.rb +39 -6
  135. data/lib/active_record/integration.rb +1 -1
  136. data/lib/active_record/internal_metadata.rb +3 -5
  137. data/lib/active_record/legacy_yaml_adapter.rb +1 -1
  138. data/lib/active_record/locking/optimistic.rb +10 -9
  139. data/lib/active_record/log_subscriber.rb +6 -2
  140. data/lib/active_record/middleware/database_selector/resolver.rb +6 -10
  141. data/lib/active_record/middleware/database_selector.rb +8 -3
  142. data/lib/active_record/migration/command_recorder.rb +4 -4
  143. data/lib/active_record/migration/compatibility.rb +83 -1
  144. data/lib/active_record/migration/join_table.rb +1 -1
  145. data/lib/active_record/migration.rb +109 -79
  146. data/lib/active_record/model_schema.rb +46 -32
  147. data/lib/active_record/nested_attributes.rb +3 -3
  148. data/lib/active_record/no_touching.rb +2 -2
  149. data/lib/active_record/null_relation.rb +2 -6
  150. data/lib/active_record/persistence.rb +134 -45
  151. data/lib/active_record/query_cache.rb +2 -2
  152. data/lib/active_record/query_logs.rb +203 -0
  153. data/lib/active_record/querying.rb +15 -5
  154. data/lib/active_record/railtie.rb +117 -17
  155. data/lib/active_record/railties/controller_runtime.rb +1 -1
  156. data/lib/active_record/railties/databases.rake +83 -58
  157. data/lib/active_record/readonly_attributes.rb +11 -0
  158. data/lib/active_record/reflection.rb +45 -44
  159. data/lib/active_record/relation/batches/batch_enumerator.rb +19 -5
  160. data/lib/active_record/relation/batches.rb +3 -3
  161. data/lib/active_record/relation/calculations.rb +42 -25
  162. data/lib/active_record/relation/delegation.rb +6 -6
  163. data/lib/active_record/relation/finder_methods.rb +32 -23
  164. data/lib/active_record/relation/merger.rb +20 -13
  165. data/lib/active_record/relation/predicate_builder.rb +1 -6
  166. data/lib/active_record/relation/query_attribute.rb +5 -11
  167. data/lib/active_record/relation/query_methods.rb +233 -50
  168. data/lib/active_record/relation/record_fetch_warning.rb +2 -2
  169. data/lib/active_record/relation/spawn_methods.rb +2 -2
  170. data/lib/active_record/relation/where_clause.rb +22 -15
  171. data/lib/active_record/relation.rb +170 -87
  172. data/lib/active_record/result.rb +17 -2
  173. data/lib/active_record/runtime_registry.rb +2 -4
  174. data/lib/active_record/sanitization.rb +11 -7
  175. data/lib/active_record/schema_dumper.rb +3 -3
  176. data/lib/active_record/schema_migration.rb +0 -4
  177. data/lib/active_record/scoping/default.rb +62 -15
  178. data/lib/active_record/scoping/named.rb +3 -11
  179. data/lib/active_record/scoping.rb +40 -22
  180. data/lib/active_record/serialization.rb +1 -1
  181. data/lib/active_record/signed_id.rb +1 -1
  182. data/lib/active_record/statement_cache.rb +2 -2
  183. data/lib/active_record/tasks/database_tasks.rb +107 -23
  184. data/lib/active_record/tasks/mysql_database_tasks.rb +1 -1
  185. data/lib/active_record/tasks/postgresql_database_tasks.rb +14 -11
  186. data/lib/active_record/test_databases.rb +1 -1
  187. data/lib/active_record/test_fixtures.rb +45 -4
  188. data/lib/active_record/timestamp.rb +3 -4
  189. data/lib/active_record/transactions.rb +9 -14
  190. data/lib/active_record/translation.rb +2 -2
  191. data/lib/active_record/type/adapter_specific_registry.rb +32 -7
  192. data/lib/active_record/type/hash_lookup_type_map.rb +34 -1
  193. data/lib/active_record/type/internal/timezone.rb +2 -2
  194. data/lib/active_record/type/serialized.rb +1 -1
  195. data/lib/active_record/type/type_map.rb +17 -20
  196. data/lib/active_record/type.rb +1 -2
  197. data/lib/active_record/validations/associated.rb +1 -1
  198. data/lib/active_record/validations/numericality.rb +1 -1
  199. data/lib/active_record.rb +170 -2
  200. data/lib/arel/attributes/attribute.rb +0 -8
  201. data/lib/arel/collectors/bind.rb +2 -2
  202. data/lib/arel/collectors/composite.rb +3 -3
  203. data/lib/arel/collectors/sql_string.rb +1 -1
  204. data/lib/arel/collectors/substitute_binds.rb +1 -1
  205. data/lib/arel/crud.rb +18 -22
  206. data/lib/arel/delete_manager.rb +2 -4
  207. data/lib/arel/insert_manager.rb +2 -3
  208. data/lib/arel/nodes/casted.rb +1 -1
  209. data/lib/arel/nodes/delete_statement.rb +8 -13
  210. data/lib/arel/nodes/homogeneous_in.rb +4 -0
  211. data/lib/arel/nodes/insert_statement.rb +2 -2
  212. data/lib/arel/nodes/select_core.rb +2 -2
  213. data/lib/arel/nodes/select_statement.rb +2 -2
  214. data/lib/arel/nodes/update_statement.rb +3 -2
  215. data/lib/arel/predications.rb +3 -3
  216. data/lib/arel/select_manager.rb +10 -4
  217. data/lib/arel/table.rb +0 -1
  218. data/lib/arel/tree_manager.rb +0 -12
  219. data/lib/arel/update_manager.rb +2 -4
  220. data/lib/arel/visitors/dot.rb +80 -90
  221. data/lib/arel/visitors/mysql.rb +6 -1
  222. data/lib/arel/visitors/postgresql.rb +0 -10
  223. data/lib/arel/visitors/to_sql.rb +44 -3
  224. data/lib/arel.rb +1 -1
  225. data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +1 -1
  226. data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +1 -1
  227. data/lib/rails/generators/active_record/model/templates/model.rb.tt +1 -1
  228. data/lib/rails/generators/active_record/model/templates/module.rb.tt +2 -2
  229. metadata +55 -16
@@ -6,7 +6,7 @@ require "active_record/fixture_set/model_metadata"
6
6
  module ActiveRecord
7
7
  class FixtureSet
8
8
  class TableRows # :nodoc:
9
- def initialize(table_name, model_class:, fixtures:, config:)
9
+ def initialize(table_name, model_class:, fixtures:)
10
10
  @model_class = model_class
11
11
 
12
12
  # track any join tables we need to insert later
@@ -15,7 +15,7 @@ module ActiveRecord
15
15
  # ensure this table is loaded before any HABTM associations
16
16
  @tables[table_name] = nil
17
17
 
18
- build_table_rows_from(table_name, fixtures, config)
18
+ build_table_rows_from(table_name, fixtures)
19
19
  end
20
20
 
21
21
  attr_reader :tables, :model_class
@@ -29,8 +29,8 @@ module ActiveRecord
29
29
  end
30
30
 
31
31
  private
32
- def build_table_rows_from(table_name, fixtures, config)
33
- now = config.default_timezone == :utc ? Time.now.utc : Time.now
32
+ def build_table_rows_from(table_name, fixtures)
33
+ now = ActiveRecord.default_timezone == :utc ? Time.now.utc : Time.now
34
34
 
35
35
  @tables[table_name] = fixtures.map do |label, fixture|
36
36
  TableRow.new(
@@ -12,7 +12,7 @@ require "active_record/fixture_set/table_rows"
12
12
  require "active_record/test_fixtures"
13
13
 
14
14
  module ActiveRecord
15
- class FixtureClassNotFound < ActiveRecord::ActiveRecordError #:nodoc:
15
+ class FixtureClassNotFound < ActiveRecord::ActiveRecordError # :nodoc:
16
16
  end
17
17
 
18
18
  # \Fixtures are a way of organizing data that you want to test against; in short, sample data.
@@ -35,7 +35,7 @@ module ActiveRecord
35
35
  # name: Google
36
36
  # url: http://www.google.com
37
37
  #
38
- # This fixture file includes two fixtures. Each YAML fixture (ie. record) is given a name and
38
+ # This fixture file includes two fixtures. Each YAML fixture (i.e. record) is given a name and
39
39
  # is followed by an indented list of key/value pairs in the "key: value" format. Records are
40
40
  # separated by a blank line for your viewing pleasure.
41
41
  #
@@ -152,7 +152,7 @@ module ActiveRecord
152
152
  # - define a helper method in <tt>test_helper.rb</tt>
153
153
  # module FixtureFileHelpers
154
154
  # def file_sha(path)
155
- # Digest::SHA2.hexdigest(File.read(Rails.root.join('test/fixtures', path)))
155
+ # OpenSSL::Digest::SHA256.hexdigest(File.read(Rails.root.join('test/fixtures', path)))
156
156
  # end
157
157
  # end
158
158
  # ActiveRecord::FixtureSet.context_class.include FixtureFileHelpers
@@ -311,7 +311,7 @@ module ActiveRecord
311
311
  #
312
312
  # Just provide the polymorphic target type and Active Record will take care of the rest.
313
313
  #
314
- # === has_and_belongs_to_many
314
+ # === has_and_belongs_to_many or has_many :through
315
315
  #
316
316
  # Time to give our monkey some fruit.
317
317
  #
@@ -426,7 +426,7 @@ module ActiveRecord
426
426
  # _fixture:
427
427
  # ignore:
428
428
  # - base
429
- # # or use "ignore: base" when there is only one fixture needs to be ignored.
429
+ # # or use "ignore: base" when there is only one fixture that needs to be ignored.
430
430
  #
431
431
  # base: &base
432
432
  # admin: false
@@ -637,6 +637,10 @@ module ActiveRecord
637
637
 
638
638
  conn.insert_fixtures_set(table_rows_for_connection, table_rows_for_connection.keys)
639
639
 
640
+ if ActiveRecord.verify_foreign_keys_for_fixtures && !conn.all_foreign_keys_valid?
641
+ raise "Foreign key violations found in your fixture data. Ensure you aren't referring to labels that don't exist on associations."
642
+ end
643
+
640
644
  # Cap primary key sequences to max(pk).
641
645
  if conn.respond_to?(:reset_pk_sequence!)
642
646
  set.each { |fs| conn.reset_pk_sequence!(fs.table_name) }
@@ -689,7 +693,6 @@ module ActiveRecord
689
693
  table_name,
690
694
  model_class: model_class,
691
695
  fixtures: fixtures,
692
- config: config,
693
696
  ).to_hash
694
697
  end
695
698
 
@@ -741,13 +744,13 @@ module ActiveRecord
741
744
  end
742
745
  end
743
746
 
744
- class Fixture #:nodoc:
747
+ class Fixture # :nodoc:
745
748
  include Enumerable
746
749
 
747
- class FixtureError < StandardError #:nodoc:
750
+ class FixtureError < StandardError # :nodoc:
748
751
  end
749
752
 
750
- class FormatError < FixtureError #:nodoc:
753
+ class FormatError < FixtureError # :nodoc:
751
754
  end
752
755
 
753
756
  attr_reader :model_class, :fixture
@@ -761,8 +764,8 @@ module ActiveRecord
761
764
  model_class.name if model_class
762
765
  end
763
766
 
764
- def each
765
- fixture.each { |item| yield item }
767
+ def each(&block)
768
+ fixture.each(&block)
766
769
  end
767
770
 
768
771
  def [](key)
@@ -782,3 +785,5 @@ module ActiveRecord
782
785
  end
783
786
  end
784
787
  end
788
+
789
+ ActiveSupport.run_load_hooks :active_record_fixture_set, ActiveRecord::FixtureSet
@@ -0,0 +1,139 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord
4
+ class FutureResult # :nodoc:
5
+ class EventBuffer
6
+ def initialize(future_result, instrumenter)
7
+ @future_result = future_result
8
+ @instrumenter = instrumenter
9
+ @events = []
10
+ end
11
+
12
+ def instrument(name, payload = {}, &block)
13
+ event = @instrumenter.new_event(name, payload)
14
+ @events << event
15
+ event.record(&block)
16
+ end
17
+
18
+ def flush
19
+ events, @events = @events, []
20
+ events.each do |event|
21
+ event.payload[:lock_wait] = @future_result.lock_wait
22
+ ActiveSupport::Notifications.publish_event(event)
23
+ end
24
+ end
25
+ end
26
+
27
+ Canceled = Class.new(ActiveRecordError)
28
+
29
+ delegate :empty?, :to_a, to: :result
30
+
31
+ attr_reader :lock_wait
32
+
33
+ def initialize(pool, *args, **kwargs)
34
+ @mutex = Mutex.new
35
+
36
+ @session = nil
37
+ @pool = pool
38
+ @args = args
39
+ @kwargs = kwargs
40
+
41
+ @pending = true
42
+ @error = nil
43
+ @result = nil
44
+ @instrumenter = ActiveSupport::Notifications.instrumenter
45
+ @event_buffer = nil
46
+ end
47
+
48
+ def schedule!(session)
49
+ @session = session
50
+ @pool.schedule_query(self)
51
+ end
52
+
53
+ def execute!(connection)
54
+ execute_query(connection)
55
+ end
56
+
57
+ def cancel
58
+ @pending = false
59
+ @error = Canceled
60
+ self
61
+ end
62
+
63
+ def execute_or_skip
64
+ return unless pending?
65
+
66
+ @pool.with_connection do |connection|
67
+ return unless @mutex.try_lock
68
+ begin
69
+ if pending?
70
+ @event_buffer = EventBuffer.new(self, @instrumenter)
71
+ connection.with_instrumenter(@event_buffer) do
72
+ execute_query(connection, async: true)
73
+ end
74
+ end
75
+ ensure
76
+ @mutex.unlock
77
+ end
78
+ end
79
+ end
80
+
81
+ def result
82
+ execute_or_wait
83
+ @event_buffer&.flush
84
+
85
+ if canceled?
86
+ raise Canceled
87
+ elsif @error
88
+ raise @error
89
+ else
90
+ @result
91
+ end
92
+ end
93
+
94
+ def pending?
95
+ @pending && (!@session || @session.active?)
96
+ end
97
+
98
+ private
99
+ def canceled?
100
+ @session && !@session.active?
101
+ end
102
+
103
+ def execute_or_wait
104
+ if pending?
105
+ start = Concurrent.monotonic_time
106
+ @mutex.synchronize do
107
+ if pending?
108
+ execute_query(@pool.connection)
109
+ else
110
+ @lock_wait = (Concurrent.monotonic_time - start) * 1_000
111
+ end
112
+ end
113
+ else
114
+ @lock_wait = 0.0
115
+ end
116
+ end
117
+
118
+ def execute_query(connection, async: false)
119
+ @result = exec_query(connection, *@args, **@kwargs, async: async)
120
+ rescue => error
121
+ @error = error
122
+ ensure
123
+ @pending = false
124
+ end
125
+
126
+ def exec_query(connection, *args, **kwargs)
127
+ connection.exec_query(*args, **kwargs)
128
+ end
129
+
130
+ class SelectAll < FutureResult # :nodoc:
131
+ private
132
+ def exec_query(*, **)
133
+ super
134
+ rescue ::RangeError
135
+ ActiveRecord::Result.empty
136
+ end
137
+ end
138
+ end
139
+ end
@@ -7,10 +7,10 @@ module ActiveRecord
7
7
  end
8
8
 
9
9
  module VERSION
10
- MAJOR = 6
11
- MINOR = 1
12
- TINY = 3
13
- PRE = "2"
10
+ MAJOR = 7
11
+ MINOR = 0
12
+ TINY = 0
13
+ PRE = "alpha2"
14
14
 
15
15
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
16
16
  end
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "active_support/inflector"
3
4
  require "active_support/core_ext/hash/indifferent_access"
4
5
 
5
6
  module ActiveRecord
@@ -43,6 +44,8 @@ module ActiveRecord
43
44
  # Determines whether to store the full constant name including namespace when using STI.
44
45
  # This is true, by default.
45
46
  class_attribute :store_full_sti_class, instance_writer: false, default: true
47
+
48
+ set_base_class
46
49
  end
47
50
 
48
51
  module ClassMethods
@@ -85,7 +88,7 @@ module ActiveRecord
85
88
  end
86
89
  end
87
90
 
88
- def finder_needs_type_condition? #:nodoc:
91
+ def finder_needs_type_condition? # :nodoc:
89
92
  # This is like this because benchmarking justifies the strange :false stuff
90
93
  :true == (@finder_needs_type_condition ||= descends_from_active_record? ? :false : :true)
91
94
  end
@@ -98,17 +101,7 @@ module ActiveRecord
98
101
  #
99
102
  # If B < A and C < B and if A is an abstract_class then both B.base_class
100
103
  # and C.base_class would return B as the answer since A is an abstract_class.
101
- def base_class
102
- unless self < Base
103
- raise ActiveRecordError, "#{name} doesn't belong in a hierarchy descending from ActiveRecord"
104
- end
105
-
106
- if superclass == Base || superclass.abstract_class?
107
- self
108
- else
109
- superclass.base_class
110
- end
111
- end
104
+ attr_reader :base_class
112
105
 
113
106
  # Returns whether the class is a base class.
114
107
  # See #base_class for more information.
@@ -164,6 +157,21 @@ module ActiveRecord
164
157
  defined?(@abstract_class) && @abstract_class == true
165
158
  end
166
159
 
160
+ # Sets the application record class for Active Record
161
+ #
162
+ # This is useful if your application uses a different class than
163
+ # ApplicationRecord for your primary abstract class. This class
164
+ # will share a database connection with Active Record. It is the class
165
+ # that connects to your primary database.
166
+ def primary_abstract_class
167
+ if ActiveRecord.application_record_class && ActiveRecord.application_record_class.name != name
168
+ raise ArgumentError, "The `primary_abstract_class` is already set to #{ActiveRecord.application_record_class.inspect}. There can only be one `primary_abstract_class` in an application."
169
+ end
170
+
171
+ self.abstract_class = true
172
+ ActiveRecord.application_record_class = self
173
+ end
174
+
167
175
  # Returns the value to be stored in the inheritance column for STI.
168
176
  def sti_name
169
177
  store_full_sti_class && store_full_class_name ? name : name.demodulize
@@ -174,7 +182,7 @@ module ActiveRecord
174
182
  # It is used to find the class correspondent to the value stored in the inheritance column.
175
183
  def sti_class_for(type_name)
176
184
  if store_full_sti_class && store_full_class_name
177
- ActiveSupport::Dependencies.constantize(type_name)
185
+ type_name.constantize
178
186
  else
179
187
  compute_type(type_name)
180
188
  end
@@ -196,17 +204,31 @@ module ActiveRecord
196
204
  # It is used to find the class correspondent to the value stored in the polymorphic type column.
197
205
  def polymorphic_class_for(name)
198
206
  if store_full_class_name
199
- ActiveSupport::Dependencies.constantize(name)
207
+ name.constantize
200
208
  else
201
209
  compute_type(name)
202
210
  end
203
211
  end
204
212
 
205
213
  def inherited(subclass)
214
+ subclass.set_base_class
206
215
  subclass.instance_variable_set(:@_type_candidates_cache, Concurrent::Map.new)
207
216
  super
208
217
  end
209
218
 
219
+ def dup # :nodoc:
220
+ # `initialize_dup` / `initialize_copy` don't work when defined
221
+ # in the `singleton_class`.
222
+ other = super
223
+ other.set_base_class
224
+ other
225
+ end
226
+
227
+ def initialize_clone(other) # :nodoc:
228
+ super
229
+ set_base_class
230
+ end
231
+
210
232
  protected
211
233
  # Returns the class type of the record using the current module as a prefix. So descendants of
212
234
  # MyApp::Business::Account would appear as MyApp::Business::AccountSubclass.
@@ -214,10 +236,10 @@ module ActiveRecord
214
236
  if type_name.start_with?("::")
215
237
  # If the type is prefixed with a scope operator then we assume that
216
238
  # the type_name is an absolute reference.
217
- ActiveSupport::Dependencies.constantize(type_name)
239
+ type_name.constantize
218
240
  else
219
241
  type_candidate = @_type_candidates_cache[type_name]
220
- if type_candidate && type_constant = ActiveSupport::Dependencies.safe_constantize(type_candidate)
242
+ if type_candidate && type_constant = type_candidate.safe_constantize
221
243
  return type_constant
222
244
  end
223
245
 
@@ -227,7 +249,7 @@ module ActiveRecord
227
249
  candidates << type_name
228
250
 
229
251
  candidates.each do |candidate|
230
- constant = ActiveSupport::Dependencies.safe_constantize(candidate)
252
+ constant = candidate.safe_constantize
231
253
  if candidate == constant.to_s
232
254
  @_type_candidates_cache[type_name] = candidate
233
255
  return constant
@@ -238,6 +260,22 @@ module ActiveRecord
238
260
  end
239
261
  end
240
262
 
263
+ def set_base_class # :nodoc:
264
+ @base_class = if self == Base
265
+ self
266
+ else
267
+ unless self < Base
268
+ raise ActiveRecordError, "#{name} doesn't belong in a hierarchy descending from ActiveRecord"
269
+ end
270
+
271
+ if superclass == Base || superclass.abstract_class?
272
+ self
273
+ else
274
+ superclass.base_class
275
+ end
276
+ end
277
+ end
278
+
241
279
  private
242
280
  # Called by +instantiate+ to decide which class to use for a new
243
281
  # record instance. For single-table inheritance, we check the record
@@ -5,7 +5,7 @@ require "active_support/core_ext/enumerable"
5
5
  module ActiveRecord
6
6
  class InsertAll # :nodoc:
7
7
  attr_reader :model, :connection, :inserts, :keys
8
- attr_reader :on_duplicate, :returning, :unique_by
8
+ attr_reader :on_duplicate, :returning, :unique_by, :update_sql
9
9
 
10
10
  def initialize(model, inserts, on_duplicate:, returning: nil, unique_by: nil)
11
11
  raise ArgumentError, "Empty list of attributes passed" if inserts.blank?
@@ -13,6 +13,14 @@ module ActiveRecord
13
13
  @model, @connection, @inserts, @keys = model, model.connection, inserts, inserts.first.keys.map(&:to_s)
14
14
  @on_duplicate, @returning, @unique_by = on_duplicate, returning, unique_by
15
15
 
16
+ disallow_raw_sql!(returning)
17
+ disallow_raw_sql!(on_duplicate)
18
+
19
+ if Arel.arel_node?(on_duplicate)
20
+ @update_sql = on_duplicate
21
+ @on_duplicate = :update
22
+ end
23
+
16
24
  if model.scope_attributes?
17
25
  @scope_attributes = model.scope_attributes
18
26
  @keys |= @scope_attributes.keys
@@ -69,7 +77,11 @@ module ActiveRecord
69
77
  attr_reader :scope_attributes
70
78
 
71
79
  def find_unique_index_for(unique_by)
72
- return unique_by if !connection.supports_insert_conflict_target?
80
+ if !connection.supports_insert_conflict_target?
81
+ return if unique_by.nil?
82
+
83
+ raise ArgumentError, "#{connection.class} does not support :unique_by"
84
+ end
73
85
 
74
86
  name_or_columns = unique_by || model.primary_key
75
87
  match = Array(name_or_columns).map(&:to_s)
@@ -127,6 +139,15 @@ module ActiveRecord
127
139
  end
128
140
  end
129
141
 
142
+ def disallow_raw_sql!(value)
143
+ return if !value.is_a?(String) || Arel.arel_node?(value)
144
+
145
+ raise ArgumentError, "Dangerous query method (method whose arguments are used as raw " \
146
+ "SQL) called: #{value}. " \
147
+ "Known-safe values can be passed " \
148
+ "by wrapping them in Arel.sql()."
149
+ end
150
+
130
151
  class Builder # :nodoc:
131
152
  attr_reader :model
132
153
 
@@ -151,7 +172,13 @@ module ActiveRecord
151
172
  end
152
173
 
153
174
  def returning
154
- format_columns(insert_all.returning) if insert_all.returning
175
+ return unless insert_all.returning
176
+
177
+ if insert_all.returning.is_a?(String)
178
+ insert_all.returning
179
+ else
180
+ format_columns(insert_all.returning)
181
+ end
155
182
  end
156
183
 
157
184
  def conflict_target
@@ -169,13 +196,19 @@ module ActiveRecord
169
196
  end
170
197
 
171
198
  def touch_model_timestamps_unless(&block)
172
- model.send(:timestamp_attributes_for_update_in_model).map do |column_name|
199
+ model.timestamp_attributes_for_update_in_model.filter_map do |column_name|
173
200
  if touch_timestamp_attribute?(column_name)
174
- "#{column_name}=(CASE WHEN (#{updatable_columns.map(&block).join(" AND ")}) THEN #{model.quoted_table_name}.#{column_name} ELSE CURRENT_TIMESTAMP END),"
201
+ "#{column_name}=(CASE WHEN (#{updatable_columns.map(&block).join(" AND ")}) THEN #{model.quoted_table_name}.#{column_name} ELSE #{connection.high_precision_current_timestamp} END),"
175
202
  end
176
- end.compact.join
203
+ end.join
177
204
  end
178
205
 
206
+ def raw_update_sql
207
+ insert_all.update_sql
208
+ end
209
+
210
+ alias raw_update_sql? raw_update_sql
211
+
179
212
  private
180
213
  attr_reader :connection, :insert_all
181
214