activerecord 5.2.7 → 6.0.0.beta1
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +299 -778
- data/MIT-LICENSE +3 -1
- data/README.rdoc +1 -1
- data/examples/performance.rb +1 -1
- data/lib/active_record/aggregations.rb +4 -2
- data/lib/active_record/associations/association.rb +35 -19
- data/lib/active_record/associations/association_scope.rb +4 -6
- data/lib/active_record/associations/belongs_to_association.rb +36 -42
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +0 -4
- data/lib/active_record/associations/builder/belongs_to.rb +14 -50
- data/lib/active_record/associations/builder/collection_association.rb +3 -3
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +17 -38
- data/lib/active_record/associations/collection_association.rb +11 -25
- data/lib/active_record/associations/collection_proxy.rb +32 -6
- data/lib/active_record/associations/foreign_association.rb +7 -0
- data/lib/active_record/associations/has_many_association.rb +1 -1
- data/lib/active_record/associations/has_many_through_association.rb +25 -18
- data/lib/active_record/associations/has_one_association.rb +28 -30
- data/lib/active_record/associations/has_one_through_association.rb +5 -5
- data/lib/active_record/associations/join_dependency/join_association.rb +11 -26
- data/lib/active_record/associations/join_dependency/join_part.rb +2 -2
- data/lib/active_record/associations/join_dependency.rb +15 -20
- data/lib/active_record/associations/preloader/association.rb +1 -2
- data/lib/active_record/associations/preloader.rb +32 -29
- data/lib/active_record/associations/singular_association.rb +2 -16
- data/lib/active_record/associations.rb +16 -12
- data/lib/active_record/attribute_assignment.rb +7 -10
- data/lib/active_record/attribute_methods/dirty.rb +64 -26
- data/lib/active_record/attribute_methods/primary_key.rb +8 -7
- data/lib/active_record/attribute_methods/read.rb +16 -48
- data/lib/active_record/attribute_methods/serialization.rb +1 -1
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +1 -1
- data/lib/active_record/attribute_methods/write.rb +15 -16
- data/lib/active_record/attribute_methods.rb +34 -56
- data/lib/active_record/autosave_association.rb +7 -21
- data/lib/active_record/base.rb +2 -2
- data/lib/active_record/callbacks.rb +3 -17
- data/lib/active_record/collection_cache_key.rb +1 -1
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +13 -36
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +9 -0
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +25 -84
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +17 -14
- data/lib/active_record/connection_adapters/abstract/quoting.rb +5 -11
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +15 -11
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +30 -13
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +0 -2
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +41 -27
- data/lib/active_record/connection_adapters/abstract/transaction.rb +81 -52
- data/lib/active_record/connection_adapters/abstract_adapter.rb +95 -31
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +65 -90
- data/lib/active_record/connection_adapters/connection_specification.rb +52 -42
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +5 -9
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +29 -7
- data/lib/active_record/connection_adapters/mysql/quoting.rb +1 -1
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +3 -4
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +65 -10
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +8 -4
- data/lib/active_record/connection_adapters/postgresql/column.rb +1 -2
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +16 -1
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +1 -4
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +9 -7
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +4 -4
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +11 -36
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +9 -2
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +38 -20
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +2 -1
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +75 -56
- data/lib/active_record/connection_adapters/schema_cache.rb +5 -0
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +5 -5
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +14 -9
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +95 -62
- data/lib/active_record/connection_handling.rb +132 -26
- data/lib/active_record/core.rb +76 -43
- data/lib/active_record/counter_cache.rb +4 -29
- data/lib/active_record/database_configurations/database_config.rb +37 -0
- data/lib/active_record/database_configurations/hash_config.rb +50 -0
- data/lib/active_record/database_configurations/url_config.rb +74 -0
- data/lib/active_record/database_configurations.rb +184 -0
- data/lib/active_record/enum.rb +22 -7
- data/lib/active_record/errors.rb +24 -21
- data/lib/active_record/explain.rb +1 -1
- data/lib/active_record/fixture_set/model_metadata.rb +33 -0
- data/lib/active_record/fixture_set/render_context.rb +17 -0
- data/lib/active_record/fixture_set/table_row.rb +153 -0
- data/lib/active_record/fixture_set/table_rows.rb +47 -0
- data/lib/active_record/fixtures.rb +140 -472
- data/lib/active_record/gem_version.rb +4 -4
- data/lib/active_record/inheritance.rb +12 -2
- data/lib/active_record/integration.rb +56 -16
- data/lib/active_record/internal_metadata.rb +5 -1
- data/lib/active_record/locking/optimistic.rb +2 -2
- data/lib/active_record/locking/pessimistic.rb +3 -3
- data/lib/active_record/log_subscriber.rb +7 -26
- data/lib/active_record/migration/command_recorder.rb +35 -5
- data/lib/active_record/migration/compatibility.rb +34 -16
- data/lib/active_record/migration.rb +38 -37
- data/lib/active_record/model_schema.rb +30 -9
- data/lib/active_record/nested_attributes.rb +2 -2
- data/lib/active_record/no_touching.rb +7 -0
- data/lib/active_record/persistence.rb +18 -7
- data/lib/active_record/query_cache.rb +11 -4
- data/lib/active_record/querying.rb +19 -11
- data/lib/active_record/railtie.rb +71 -42
- data/lib/active_record/railties/collection_cache_association_loading.rb +34 -0
- data/lib/active_record/railties/controller_runtime.rb +30 -35
- data/lib/active_record/railties/databases.rake +94 -43
- data/lib/active_record/reflection.rb +60 -44
- data/lib/active_record/relation/batches.rb +13 -10
- data/lib/active_record/relation/calculations.rb +38 -28
- data/lib/active_record/relation/delegation.rb +4 -13
- data/lib/active_record/relation/finder_methods.rb +12 -25
- data/lib/active_record/relation/merger.rb +2 -6
- data/lib/active_record/relation/predicate_builder/array_handler.rb +5 -4
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +1 -4
- data/lib/active_record/relation/predicate_builder/base_handler.rb +1 -2
- data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +1 -2
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +1 -4
- data/lib/active_record/relation/predicate_builder/range_handler.rb +3 -23
- data/lib/active_record/relation/predicate_builder.rb +4 -6
- data/lib/active_record/relation/query_attribute.rb +15 -12
- data/lib/active_record/relation/query_methods.rb +29 -52
- data/lib/active_record/relation/where_clause.rb +4 -0
- data/lib/active_record/relation/where_clause_factory.rb +1 -2
- data/lib/active_record/relation.rb +150 -69
- data/lib/active_record/result.rb +30 -11
- data/lib/active_record/sanitization.rb +2 -39
- data/lib/active_record/schema.rb +1 -10
- data/lib/active_record/schema_dumper.rb +12 -6
- data/lib/active_record/schema_migration.rb +4 -0
- data/lib/active_record/scoping/default.rb +10 -3
- data/lib/active_record/scoping/named.rb +10 -14
- data/lib/active_record/scoping.rb +9 -8
- data/lib/active_record/statement_cache.rb +32 -5
- data/lib/active_record/store.rb +39 -8
- data/lib/active_record/table_metadata.rb +1 -4
- data/lib/active_record/tasks/database_tasks.rb +89 -23
- data/lib/active_record/tasks/mysql_database_tasks.rb +2 -4
- data/lib/active_record/tasks/postgresql_database_tasks.rb +5 -7
- data/lib/active_record/tasks/sqlite_database_tasks.rb +2 -8
- data/lib/active_record/test_databases.rb +38 -0
- data/lib/active_record/test_fixtures.rb +224 -0
- data/lib/active_record/timestamp.rb +4 -6
- data/lib/active_record/transactions.rb +3 -22
- data/lib/active_record/translation.rb +1 -1
- data/lib/active_record/type/adapter_specific_registry.rb +1 -8
- data/lib/active_record/type.rb +3 -4
- data/lib/active_record/type_caster/connection.rb +1 -6
- data/lib/active_record/type_caster/map.rb +1 -4
- data/lib/active_record/validations/uniqueness.rb +13 -25
- data/lib/active_record.rb +2 -1
- data/lib/arel/alias_predication.rb +9 -0
- data/lib/arel/attributes/attribute.rb +37 -0
- data/lib/arel/attributes.rb +22 -0
- data/lib/arel/collectors/bind.rb +24 -0
- data/lib/arel/collectors/composite.rb +31 -0
- data/lib/arel/collectors/plain_string.rb +20 -0
- data/lib/arel/collectors/sql_string.rb +20 -0
- data/lib/arel/collectors/substitute_binds.rb +28 -0
- data/lib/arel/crud.rb +42 -0
- data/lib/arel/delete_manager.rb +18 -0
- data/lib/arel/errors.rb +9 -0
- data/lib/arel/expressions.rb +29 -0
- data/lib/arel/factory_methods.rb +49 -0
- data/lib/arel/insert_manager.rb +49 -0
- data/lib/arel/math.rb +45 -0
- data/lib/arel/nodes/and.rb +32 -0
- data/lib/arel/nodes/ascending.rb +23 -0
- data/lib/arel/nodes/binary.rb +52 -0
- data/lib/arel/nodes/bind_param.rb +36 -0
- data/lib/arel/nodes/case.rb +55 -0
- data/lib/arel/nodes/casted.rb +50 -0
- data/lib/arel/nodes/count.rb +12 -0
- data/lib/arel/nodes/delete_statement.rb +45 -0
- data/lib/arel/nodes/descending.rb +23 -0
- data/lib/arel/nodes/equality.rb +18 -0
- data/lib/arel/nodes/extract.rb +24 -0
- data/lib/arel/nodes/false.rb +16 -0
- data/lib/arel/nodes/full_outer_join.rb +8 -0
- data/lib/arel/nodes/function.rb +44 -0
- data/lib/arel/nodes/grouping.rb +8 -0
- data/lib/arel/nodes/in.rb +8 -0
- data/lib/arel/nodes/infix_operation.rb +80 -0
- data/lib/arel/nodes/inner_join.rb +8 -0
- data/lib/arel/nodes/insert_statement.rb +37 -0
- data/lib/arel/nodes/join_source.rb +20 -0
- data/lib/arel/nodes/matches.rb +18 -0
- data/lib/arel/nodes/named_function.rb +23 -0
- data/lib/arel/nodes/node.rb +50 -0
- data/lib/arel/nodes/node_expression.rb +13 -0
- data/lib/arel/nodes/outer_join.rb +8 -0
- data/lib/arel/nodes/over.rb +15 -0
- data/lib/arel/nodes/regexp.rb +16 -0
- data/lib/arel/nodes/right_outer_join.rb +8 -0
- data/lib/arel/nodes/select_core.rb +63 -0
- data/lib/arel/nodes/select_statement.rb +41 -0
- data/lib/arel/nodes/sql_literal.rb +16 -0
- data/lib/arel/nodes/string_join.rb +11 -0
- data/lib/arel/nodes/table_alias.rb +27 -0
- data/lib/arel/nodes/terminal.rb +16 -0
- data/lib/arel/nodes/true.rb +16 -0
- data/lib/arel/nodes/unary.rb +44 -0
- data/lib/arel/nodes/unary_operation.rb +20 -0
- data/lib/arel/nodes/unqualified_column.rb +22 -0
- data/lib/arel/nodes/update_statement.rb +41 -0
- data/lib/arel/nodes/values.rb +16 -0
- data/lib/arel/nodes/values_list.rb +24 -0
- data/lib/arel/nodes/window.rb +126 -0
- data/lib/arel/nodes/with.rb +11 -0
- data/lib/arel/nodes.rb +67 -0
- data/lib/arel/order_predications.rb +13 -0
- data/lib/arel/predications.rb +257 -0
- data/lib/arel/select_manager.rb +271 -0
- data/lib/arel/table.rb +110 -0
- data/lib/arel/tree_manager.rb +72 -0
- data/lib/arel/update_manager.rb +34 -0
- data/lib/arel/visitors/depth_first.rb +199 -0
- data/lib/arel/visitors/dot.rb +292 -0
- data/lib/arel/visitors/ibm_db.rb +21 -0
- data/lib/arel/visitors/informix.rb +56 -0
- data/lib/arel/visitors/mssql.rb +143 -0
- data/lib/arel/visitors/mysql.rb +83 -0
- data/lib/arel/visitors/oracle.rb +159 -0
- data/lib/arel/visitors/oracle12.rb +67 -0
- data/lib/arel/visitors/postgresql.rb +116 -0
- data/lib/arel/visitors/sqlite.rb +39 -0
- data/lib/arel/visitors/to_sql.rb +913 -0
- data/lib/arel/visitors/visitor.rb +42 -0
- data/lib/arel/visitors/where_sql.rb +23 -0
- data/lib/arel/visitors.rb +20 -0
- data/lib/arel/window_predications.rb +9 -0
- data/lib/arel.rb +44 -0
- data/lib/rails/generators/active_record/migration/migration_generator.rb +2 -5
- data/lib/rails/generators/active_record/migration.rb +14 -1
- data/lib/rails/generators/active_record/model/model_generator.rb +1 -0
- metadata +104 -26
data/lib/active_record/base.rb
CHANGED
@@ -9,7 +9,6 @@ require "active_support/core_ext/module/attribute_accessors"
|
|
9
9
|
require "active_support/core_ext/array/extract_options"
|
10
10
|
require "active_support/core_ext/hash/deep_merge"
|
11
11
|
require "active_support/core_ext/hash/slice"
|
12
|
-
require "active_support/core_ext/hash/transform_values"
|
13
12
|
require "active_support/core_ext/string/behavior"
|
14
13
|
require "active_support/core_ext/kernel/singleton_class"
|
15
14
|
require "active_support/core_ext/module/introspection"
|
@@ -23,6 +22,7 @@ require "active_record/explain_subscriber"
|
|
23
22
|
require "active_record/relation/delegation"
|
24
23
|
require "active_record/attributes"
|
25
24
|
require "active_record/type_caster"
|
25
|
+
require "active_record/database_configurations"
|
26
26
|
|
27
27
|
module ActiveRecord #:nodoc:
|
28
28
|
# = Active Record
|
@@ -289,6 +289,7 @@ module ActiveRecord #:nodoc:
|
|
289
289
|
extend Enum
|
290
290
|
extend Delegation::DelegateCache
|
291
291
|
extend CollectionCacheKey
|
292
|
+
extend Aggregations::ClassMethods
|
292
293
|
|
293
294
|
include Core
|
294
295
|
include Persistence
|
@@ -314,7 +315,6 @@ module ActiveRecord #:nodoc:
|
|
314
315
|
include ActiveModel::SecurePassword
|
315
316
|
include AutosaveAssociation
|
316
317
|
include NestedAttributes
|
317
|
-
include Aggregations
|
318
318
|
include Transactions
|
319
319
|
include TouchLater
|
320
320
|
include NoTouching
|
@@ -75,21 +75,7 @@ module ActiveRecord
|
|
75
75
|
# end
|
76
76
|
#
|
77
77
|
# Now, when <tt>Topic#destroy</tt> is run only +destroy_author+ is called. When <tt>Reply#destroy</tt> is
|
78
|
-
# run, both +destroy_author+ and +destroy_readers+ are called.
|
79
|
-
# where the +before_destroy+ method is overridden:
|
80
|
-
#
|
81
|
-
# class Topic < ActiveRecord::Base
|
82
|
-
# def before_destroy() destroy_author end
|
83
|
-
# end
|
84
|
-
#
|
85
|
-
# class Reply < Topic
|
86
|
-
# def before_destroy() destroy_readers end
|
87
|
-
# end
|
88
|
-
#
|
89
|
-
# In that case, <tt>Reply#destroy</tt> would only run +destroy_readers+ and _not_ +destroy_author+.
|
90
|
-
# So, use the callback macros when you want to ensure that a certain callback is called for the entire
|
91
|
-
# hierarchy, and use the regular overwritable methods when you want to leave it up to each descendant
|
92
|
-
# to decide whether they want to call +super+ and trigger the inherited callbacks.
|
78
|
+
# run, both +destroy_author+ and +destroy_readers+ are called.
|
93
79
|
#
|
94
80
|
# *IMPORTANT:* In order for inheritance to work for the callback queues, you must specify the
|
95
81
|
# callbacks before specifying the associations. Otherwise, you might trigger the loading of a
|
@@ -109,7 +95,7 @@ module ActiveRecord
|
|
109
95
|
#
|
110
96
|
# private
|
111
97
|
# def delete_parents
|
112
|
-
# self.class.
|
98
|
+
# self.class.where(parent_id: id).delete_all
|
113
99
|
# end
|
114
100
|
# end
|
115
101
|
#
|
@@ -142,7 +128,7 @@ module ActiveRecord
|
|
142
128
|
# end
|
143
129
|
# end
|
144
130
|
#
|
145
|
-
# So you specify the object you want messaged on a given callback. When that callback is triggered, the object has
|
131
|
+
# So you specify the object you want to be messaged on a given callback. When that callback is triggered, the object has
|
146
132
|
# a method by the name of the callback messaged. You can make these callbacks more flexible by passing in other
|
147
133
|
# initialization data such as the name of the attribute to work with:
|
148
134
|
#
|
@@ -16,7 +16,7 @@ module ActiveRecord
|
|
16
16
|
collection = collection.send(:apply_join_dependency)
|
17
17
|
end
|
18
18
|
column_type = type_for_attribute(timestamp_column)
|
19
|
-
column = connection.
|
19
|
+
column = connection.visitor.compile(collection.arel_attribute(timestamp_column))
|
20
20
|
select_values = "COUNT(*) AS #{connection.quote_column_name("size")}, MAX(%s) AS timestamp"
|
21
21
|
|
22
22
|
if collection.has_limit_or_offset?
|
@@ -310,7 +310,7 @@ module ActiveRecord
|
|
310
310
|
include QueryCache::ConnectionPoolConfiguration
|
311
311
|
|
312
312
|
attr_accessor :automatic_reconnect, :checkout_timeout, :schema_cache
|
313
|
-
attr_reader :spec, :size, :reaper
|
313
|
+
attr_reader :spec, :connections, :size, :reaper
|
314
314
|
|
315
315
|
# Creates a new ConnectionPool object. +spec+ is a ConnectionSpecification
|
316
316
|
# object which describes database connection information (e.g. adapter,
|
@@ -379,7 +379,7 @@ module ActiveRecord
|
|
379
379
|
# #connection can be called any number of times; the connection is
|
380
380
|
# held in a cache keyed by a thread.
|
381
381
|
def connection
|
382
|
-
@thread_cached_conns[connection_cache_key(
|
382
|
+
@thread_cached_conns[connection_cache_key(@lock_thread || Thread.current)] ||= checkout
|
383
383
|
end
|
384
384
|
|
385
385
|
# Returns true if there is an open connection being used for the current thread.
|
@@ -388,7 +388,7 @@ module ActiveRecord
|
|
388
388
|
# #connection or #with_connection methods. Connections obtained through
|
389
389
|
# #checkout will not be detected by #active_connection?
|
390
390
|
def active_connection?
|
391
|
-
@thread_cached_conns[connection_cache_key(
|
391
|
+
@thread_cached_conns[connection_cache_key(Thread.current)]
|
392
392
|
end
|
393
393
|
|
394
394
|
# Signal that the thread is finished with the current connection.
|
@@ -423,21 +423,6 @@ module ActiveRecord
|
|
423
423
|
synchronize { @connections.any? }
|
424
424
|
end
|
425
425
|
|
426
|
-
# Returns an array containing the connections currently in the pool.
|
427
|
-
# Access to the array does not require synchronization on the pool because
|
428
|
-
# the array is newly created and not retained by the pool.
|
429
|
-
#
|
430
|
-
# However; this method bypasses the ConnectionPool's thread-safe connection
|
431
|
-
# access pattern. A returned connection may be owned by another thread,
|
432
|
-
# unowned, or by happen-stance owned by the calling thread.
|
433
|
-
#
|
434
|
-
# Calling methods on a connection without ownership is subject to the
|
435
|
-
# thread-safety guarantees of the underlying method. Many of the methods
|
436
|
-
# on connection adapter classes are inherently multi-thread unsafe.
|
437
|
-
def connections
|
438
|
-
synchronize { @connections.dup }
|
439
|
-
end
|
440
|
-
|
441
426
|
# Disconnects all connections in the pool, and clears the pool.
|
442
427
|
#
|
443
428
|
# Raises:
|
@@ -683,10 +668,6 @@ module ActiveRecord
|
|
683
668
|
thread
|
684
669
|
end
|
685
670
|
|
686
|
-
def current_thread
|
687
|
-
@lock_thread || Thread.current
|
688
|
-
end
|
689
|
-
|
690
671
|
# Take control of all existing connections so a "group" action such as
|
691
672
|
# reload/disconnect can be performed safely. It is no longer enough to
|
692
673
|
# wrap it in +synchronize+ because some pool's actions are allowed
|
@@ -750,7 +731,7 @@ module ActiveRecord
|
|
750
731
|
# this block can't be easily moved into attempt_to_checkout_all_existing_connections's
|
751
732
|
# rescue block, because doing so would put it outside of synchronize section, without
|
752
733
|
# being in a critical section thread_report might become inaccurate
|
753
|
-
msg = "could not obtain ownership of all database connections in #{checkout_timeout} seconds"
|
734
|
+
msg = +"could not obtain ownership of all database connections in #{checkout_timeout} seconds"
|
754
735
|
|
755
736
|
thread_report = []
|
756
737
|
@connections.each do |conn|
|
@@ -934,16 +915,6 @@ module ActiveRecord
|
|
934
915
|
# about the model. The model needs to pass a specification name to the handler,
|
935
916
|
# in order to look up the correct connection pool.
|
936
917
|
class ConnectionHandler
|
937
|
-
def self.create_owner_to_pool # :nodoc:
|
938
|
-
Concurrent::Map.new(initial_capacity: 2) do |h, k|
|
939
|
-
# Discard the parent's connection pools immediately; we have no need
|
940
|
-
# of them
|
941
|
-
discard_unowned_pools(h)
|
942
|
-
|
943
|
-
h[k] = Concurrent::Map.new(initial_capacity: 2)
|
944
|
-
end
|
945
|
-
end
|
946
|
-
|
947
918
|
def self.unowned_pool_finalizer(pid_map) # :nodoc:
|
948
919
|
lambda do |_|
|
949
920
|
discard_unowned_pools(pid_map)
|
@@ -958,7 +929,13 @@ module ActiveRecord
|
|
958
929
|
|
959
930
|
def initialize
|
960
931
|
# These caches are keyed by spec.name (ConnectionSpecification#name).
|
961
|
-
@owner_to_pool =
|
932
|
+
@owner_to_pool = Concurrent::Map.new(initial_capacity: 2) do |h, k|
|
933
|
+
# Discard the parent's connection pools immediately; we have no need
|
934
|
+
# of them
|
935
|
+
ConnectionHandler.discard_unowned_pools(h)
|
936
|
+
|
937
|
+
h[k] = Concurrent::Map.new(initial_capacity: 2)
|
938
|
+
end
|
962
939
|
|
963
940
|
# Backup finalizer: if the forked child never needed a pool, the above
|
964
941
|
# early discard has not occurred
|
@@ -1036,8 +1013,8 @@ module ActiveRecord
|
|
1036
1013
|
# Returns true if a connection that's accessible to this class has
|
1037
1014
|
# already been opened.
|
1038
1015
|
def connected?(spec_name)
|
1039
|
-
|
1040
|
-
|
1016
|
+
pool = retrieve_connection_pool(spec_name)
|
1017
|
+
pool && pool.connected?
|
1041
1018
|
end
|
1042
1019
|
|
1043
1020
|
# Remove the connection for this class. This will close the active
|
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "active_support/deprecation"
|
4
|
+
|
3
5
|
module ActiveRecord
|
4
6
|
module ConnectionAdapters # :nodoc:
|
5
7
|
module DatabaseLimits
|
@@ -12,11 +14,13 @@ module ActiveRecord
|
|
12
14
|
def column_name_length
|
13
15
|
64
|
14
16
|
end
|
17
|
+
deprecate :column_name_length
|
15
18
|
|
16
19
|
# Returns the maximum length of a table name.
|
17
20
|
def table_name_length
|
18
21
|
64
|
19
22
|
end
|
23
|
+
deprecate :table_name_length
|
20
24
|
|
21
25
|
# Returns the maximum allowed length for an index name. This
|
22
26
|
# limit is enforced by \Rails and is less than or equal to
|
@@ -36,16 +40,19 @@ module ActiveRecord
|
|
36
40
|
def columns_per_table
|
37
41
|
1024
|
38
42
|
end
|
43
|
+
deprecate :columns_per_table
|
39
44
|
|
40
45
|
# Returns the maximum number of indexes per table.
|
41
46
|
def indexes_per_table
|
42
47
|
16
|
43
48
|
end
|
49
|
+
deprecate :indexes_per_table
|
44
50
|
|
45
51
|
# Returns the maximum number of columns in a multicolumn index.
|
46
52
|
def columns_per_multicolumn_index
|
47
53
|
16
|
48
54
|
end
|
55
|
+
deprecate :columns_per_multicolumn_index
|
49
56
|
|
50
57
|
# Returns the maximum number of elements in an IN (x,y,z) clause.
|
51
58
|
# +nil+ means no limit.
|
@@ -57,11 +64,13 @@ module ActiveRecord
|
|
57
64
|
def sql_query_length
|
58
65
|
1048575
|
59
66
|
end
|
67
|
+
deprecate :sql_query_length
|
60
68
|
|
61
69
|
# Returns maximum number of joins in a single query.
|
62
70
|
def joins_per_query
|
63
71
|
256
|
64
72
|
end
|
73
|
+
deprecate :joins_per_query
|
65
74
|
|
66
75
|
private
|
67
76
|
def bind_params_length
|
@@ -20,22 +20,9 @@ module ActiveRecord
|
|
20
20
|
raise "Passing bind parameters with an arel AST is forbidden. " \
|
21
21
|
"The values must be stored on the AST directly"
|
22
22
|
end
|
23
|
-
|
24
|
-
|
25
|
-
sql, binds = visitor.accept(arel_or_sql_string.ast, collector).value
|
26
|
-
|
27
|
-
if binds.length > bind_params_length
|
28
|
-
unprepared_statement do
|
29
|
-
sql, binds = to_sql_and_binds(arel_or_sql_string)
|
30
|
-
visitor.preparable = false
|
31
|
-
end
|
32
|
-
end
|
33
|
-
else
|
34
|
-
sql = visitor.accept(arel_or_sql_string.ast, collector).value
|
35
|
-
end
|
36
|
-
[sql.freeze, binds]
|
23
|
+
sql, binds = visitor.compile(arel_or_sql_string.ast, collector)
|
24
|
+
[sql.freeze, binds || []]
|
37
25
|
else
|
38
|
-
visitor.preparable = false if prepared_statements
|
39
26
|
[arel_or_sql_string.dup.freeze, binds]
|
40
27
|
end
|
41
28
|
end
|
@@ -45,11 +32,11 @@ module ActiveRecord
|
|
45
32
|
# can be used to query the database repeatedly.
|
46
33
|
def cacheable_query(klass, arel) # :nodoc:
|
47
34
|
if prepared_statements
|
48
|
-
sql, binds = visitor.
|
35
|
+
sql, binds = visitor.compile(arel.ast, collector)
|
49
36
|
query = klass.query(sql)
|
50
37
|
else
|
51
|
-
collector =
|
52
|
-
parts, binds = visitor.
|
38
|
+
collector = klass.partial_query_collector
|
39
|
+
parts, binds = visitor.compile(arel.ast, collector)
|
53
40
|
query = klass.partial_query(parts)
|
54
41
|
end
|
55
42
|
[query, binds]
|
@@ -60,8 +47,13 @@ module ActiveRecord
|
|
60
47
|
arel = arel_from_relation(arel)
|
61
48
|
sql, binds = to_sql_and_binds(arel, binds)
|
62
49
|
|
63
|
-
if preparable.nil?
|
64
|
-
preparable =
|
50
|
+
if !prepared_statements || (arel.is_a?(String) && preparable.nil?)
|
51
|
+
preparable = false
|
52
|
+
elsif binds.length > bind_params_length
|
53
|
+
sql, binds = unprepared_statement { to_sql_and_binds(arel) }
|
54
|
+
preparable = false
|
55
|
+
else
|
56
|
+
preparable = visitor.preparable
|
65
57
|
end
|
66
58
|
|
67
59
|
if prepared_statements && preparable
|
@@ -106,6 +98,11 @@ module ActiveRecord
|
|
106
98
|
exec_query(sql, name).rows
|
107
99
|
end
|
108
100
|
|
101
|
+
# Determines whether the SQL statement is a write query.
|
102
|
+
def write_query?(sql)
|
103
|
+
raise NotImplementedError
|
104
|
+
end
|
105
|
+
|
109
106
|
# Executes the SQL statement in the context of this connection and returns
|
110
107
|
# the raw result from the connection adapter.
|
111
108
|
# Note: depending on your database connector, the result returned by this
|
@@ -126,7 +123,7 @@ module ActiveRecord
|
|
126
123
|
# +binds+ as the bind substitutes. +name+ is logged along with
|
127
124
|
# the executed +sql+ statement.
|
128
125
|
def exec_insert(sql, name = nil, binds = [], pk = nil, sequence_name = nil)
|
129
|
-
sql, binds = sql_for_insert(sql, pk,
|
126
|
+
sql, binds = sql_for_insert(sql, pk, sequence_name, binds)
|
130
127
|
exec_query(sql, name, binds)
|
131
128
|
end
|
132
129
|
|
@@ -176,13 +173,6 @@ module ActiveRecord
|
|
176
173
|
exec_delete(sql, name, binds)
|
177
174
|
end
|
178
175
|
|
179
|
-
# Returns +true+ when the connection adapter supports prepared statement
|
180
|
-
# caching, otherwise returns +false+
|
181
|
-
def supports_statement_cache? # :nodoc:
|
182
|
-
true
|
183
|
-
end
|
184
|
-
deprecate :supports_statement_cache?
|
185
|
-
|
186
176
|
# Runs the given block in a database transaction, and returns the result
|
187
177
|
# of the block.
|
188
178
|
#
|
@@ -272,7 +262,9 @@ module ActiveRecord
|
|
272
262
|
|
273
263
|
attr_reader :transaction_manager #:nodoc:
|
274
264
|
|
275
|
-
delegate :within_new_transaction, :open_transactions, :current_transaction, :begin_transaction,
|
265
|
+
delegate :within_new_transaction, :open_transactions, :current_transaction, :begin_transaction,
|
266
|
+
:commit_transaction, :rollback_transaction, :materialize_transactions,
|
267
|
+
:disable_lazy_transactions!, :enable_lazy_transactions!, to: :transaction_manager
|
276
268
|
|
277
269
|
def transaction_open?
|
278
270
|
current_transaction.open?
|
@@ -337,7 +329,7 @@ module ActiveRecord
|
|
337
329
|
|
338
330
|
# Inserts the given fixture into the table. Overridden in adapters that require
|
339
331
|
# something beyond a simple insert (eg. Oracle).
|
340
|
-
# Most of adapters should implement `
|
332
|
+
# Most of adapters should implement `insert_fixtures_set` that leverages bulk SQL insert.
|
341
333
|
# We keep this method to provide fallback
|
342
334
|
# for databases like sqlite that do not support bulk inserts.
|
343
335
|
def insert_fixture(fixture, table_name)
|
@@ -366,18 +358,6 @@ module ActiveRecord
|
|
366
358
|
execute manager.to_sql, "Fixture Insert"
|
367
359
|
end
|
368
360
|
|
369
|
-
# Inserts a set of fixtures into the table. Overridden in adapters that require
|
370
|
-
# something beyond a simple insert (eg. Oracle).
|
371
|
-
def insert_fixtures(fixtures, table_name)
|
372
|
-
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
373
|
-
`insert_fixtures` is deprecated and will be removed in the next version of Rails.
|
374
|
-
Consider using `insert_fixtures_set` for performance improvement.
|
375
|
-
MSG
|
376
|
-
return if fixtures.empty?
|
377
|
-
|
378
|
-
execute(build_fixture_sql(fixtures, table_name), "Fixtures Insert")
|
379
|
-
end
|
380
|
-
|
381
361
|
def insert_fixtures_set(fixture_set, tables_to_delete = [])
|
382
362
|
fixture_inserts = fixture_set.map do |table_name, fixtures|
|
383
363
|
next if fixtures.empty?
|
@@ -385,7 +365,7 @@ module ActiveRecord
|
|
385
365
|
build_fixture_sql(fixtures, table_name)
|
386
366
|
end.compact
|
387
367
|
|
388
|
-
table_deletes = tables_to_delete.map { |table| "DELETE FROM #{quote_table_name table}"
|
368
|
+
table_deletes = tables_to_delete.map { |table| +"DELETE FROM #{quote_table_name table}" }
|
389
369
|
total_sql = Array.wrap(combine_multi_statements(table_deletes + fixture_inserts))
|
390
370
|
|
391
371
|
disable_referential_integrity do
|
@@ -398,7 +378,7 @@ module ActiveRecord
|
|
398
378
|
end
|
399
379
|
end
|
400
380
|
|
401
|
-
def empty_insert_statement_value
|
381
|
+
def empty_insert_statement_value(primary_key = nil)
|
402
382
|
"DEFAULT VALUES"
|
403
383
|
end
|
404
384
|
|
@@ -416,16 +396,6 @@ module ActiveRecord
|
|
416
396
|
end
|
417
397
|
end
|
418
398
|
|
419
|
-
# The default strategy for an UPDATE with joins is to use a subquery. This doesn't work
|
420
|
-
# on MySQL (even when aliasing the tables), but MySQL allows using JOIN directly in
|
421
|
-
# an UPDATE statement, so in the MySQL adapters we redefine this to do that.
|
422
|
-
def join_to_update(update, select, key) # :nodoc:
|
423
|
-
subselect = subquery_for(key, select)
|
424
|
-
|
425
|
-
update.where key.in(subselect)
|
426
|
-
end
|
427
|
-
alias join_to_delete join_to_update
|
428
|
-
|
429
399
|
private
|
430
400
|
def default_insert_value(column)
|
431
401
|
Arel.sql("DEFAULT")
|
@@ -466,13 +436,6 @@ module ActiveRecord
|
|
466
436
|
total_sql.join(";\n")
|
467
437
|
end
|
468
438
|
|
469
|
-
# Returns a subquery for the given key using the join information.
|
470
|
-
def subquery_for(key, select)
|
471
|
-
subselect = select.clone
|
472
|
-
subselect.projections = [key]
|
473
|
-
subselect
|
474
|
-
end
|
475
|
-
|
476
439
|
# Returns an ActiveRecord::Result instance.
|
477
440
|
def select(sql, name = nil, binds = [])
|
478
441
|
exec_query(sql, name, binds, prepare: false)
|
@@ -482,7 +445,7 @@ module ActiveRecord
|
|
482
445
|
exec_query(sql, name, binds, prepare: true)
|
483
446
|
end
|
484
447
|
|
485
|
-
def sql_for_insert(sql, pk,
|
448
|
+
def sql_for_insert(sql, pk, sequence_name, binds)
|
486
449
|
[sql, binds]
|
487
450
|
end
|
488
451
|
|
@@ -513,28 +476,6 @@ module ActiveRecord
|
|
513
476
|
value
|
514
477
|
end
|
515
478
|
end
|
516
|
-
|
517
|
-
class PartialQueryCollector
|
518
|
-
def initialize
|
519
|
-
@parts = []
|
520
|
-
@binds = []
|
521
|
-
end
|
522
|
-
|
523
|
-
def <<(str)
|
524
|
-
@parts << str
|
525
|
-
self
|
526
|
-
end
|
527
|
-
|
528
|
-
def add_bind(obj)
|
529
|
-
@binds << obj
|
530
|
-
@parts << Arel::Nodes::BindParam.new(1)
|
531
|
-
self
|
532
|
-
end
|
533
|
-
|
534
|
-
def value
|
535
|
-
[@parts, @binds]
|
536
|
-
end
|
537
|
-
end
|
538
479
|
end
|
539
480
|
end
|
540
481
|
end
|
@@ -32,17 +32,17 @@ module ActiveRecord
|
|
32
32
|
end
|
33
33
|
|
34
34
|
def enable_query_cache!
|
35
|
-
@query_cache_enabled[connection_cache_key(
|
35
|
+
@query_cache_enabled[connection_cache_key(Thread.current)] = true
|
36
36
|
connection.enable_query_cache! if active_connection?
|
37
37
|
end
|
38
38
|
|
39
39
|
def disable_query_cache!
|
40
|
-
@query_cache_enabled.delete connection_cache_key(
|
40
|
+
@query_cache_enabled.delete connection_cache_key(Thread.current)
|
41
41
|
connection.disable_query_cache! if active_connection?
|
42
42
|
end
|
43
43
|
|
44
44
|
def query_cache_enabled
|
45
|
-
@query_cache_enabled[connection_cache_key(
|
45
|
+
@query_cache_enabled[connection_cache_key(Thread.current)]
|
46
46
|
end
|
47
47
|
end
|
48
48
|
|
@@ -96,11 +96,6 @@ module ActiveRecord
|
|
96
96
|
if @query_cache_enabled && !locked?(arel)
|
97
97
|
arel = arel_from_relation(arel)
|
98
98
|
sql, binds = to_sql_and_binds(arel, binds)
|
99
|
-
|
100
|
-
if preparable.nil?
|
101
|
-
preparable = prepared_statements ? visitor.preparable : false
|
102
|
-
end
|
103
|
-
|
104
99
|
cache_sql(sql, name, binds) { super(sql, name, binds, preparable: preparable) }
|
105
100
|
else
|
106
101
|
super
|
@@ -115,12 +110,7 @@ module ActiveRecord
|
|
115
110
|
if @query_cache[sql].key?(binds)
|
116
111
|
ActiveSupport::Notifications.instrument(
|
117
112
|
"sql.active_record",
|
118
|
-
sql
|
119
|
-
binds: binds,
|
120
|
-
type_casted_binds: -> { type_casted_binds(binds) },
|
121
|
-
name: name,
|
122
|
-
connection_id: object_id,
|
123
|
-
cached: true,
|
113
|
+
cache_notification_info(sql, name, binds)
|
124
114
|
)
|
125
115
|
@query_cache[sql][binds]
|
126
116
|
else
|
@@ -130,6 +120,19 @@ module ActiveRecord
|
|
130
120
|
end
|
131
121
|
end
|
132
122
|
|
123
|
+
# Database adapters can override this method to
|
124
|
+
# provide custom cache information.
|
125
|
+
def cache_notification_info(sql, name, binds)
|
126
|
+
{
|
127
|
+
sql: sql,
|
128
|
+
binds: binds,
|
129
|
+
type_casted_binds: -> { type_casted_binds(binds) },
|
130
|
+
name: name,
|
131
|
+
connection_id: object_id,
|
132
|
+
cached: true
|
133
|
+
}
|
134
|
+
end
|
135
|
+
|
133
136
|
# If arel is locked this is a SELECT ... FOR UPDATE or somesuch. Such
|
134
137
|
# queries should not be cached.
|
135
138
|
def locked?(arel)
|
@@ -60,7 +60,7 @@ module ActiveRecord
|
|
60
60
|
# Quotes a string, escaping any ' (single quote) and \ (backslash)
|
61
61
|
# characters.
|
62
62
|
def quote_string(s)
|
63
|
-
s.gsub('\\'
|
63
|
+
s.gsub('\\', '\&\&').gsub("'", "''") # ' (for ruby-mode)
|
64
64
|
end
|
65
65
|
|
66
66
|
# Quotes the column name. Defaults to no quoting.
|
@@ -95,7 +95,7 @@ module ActiveRecord
|
|
95
95
|
end
|
96
96
|
|
97
97
|
def quoted_true
|
98
|
-
"TRUE"
|
98
|
+
"TRUE"
|
99
99
|
end
|
100
100
|
|
101
101
|
def unquoted_true
|
@@ -103,7 +103,7 @@ module ActiveRecord
|
|
103
103
|
end
|
104
104
|
|
105
105
|
def quoted_false
|
106
|
-
"FALSE"
|
106
|
+
"FALSE"
|
107
107
|
end
|
108
108
|
|
109
109
|
def unquoted_false
|
@@ -157,13 +157,9 @@ module ActiveRecord
|
|
157
157
|
end
|
158
158
|
end
|
159
159
|
|
160
|
-
def types_which_need_no_typecasting
|
161
|
-
[nil, Numeric, String]
|
162
|
-
end
|
163
|
-
|
164
160
|
def _quote(value)
|
165
161
|
case value
|
166
|
-
when String, ActiveSupport::Multibyte::Chars
|
162
|
+
when String, Symbol, ActiveSupport::Multibyte::Chars
|
167
163
|
"'#{quote_string(value.to_s)}'"
|
168
164
|
when true then quoted_true
|
169
165
|
when false then quoted_false
|
@@ -174,7 +170,6 @@ module ActiveRecord
|
|
174
170
|
when Type::Binary::Data then quoted_binary(value)
|
175
171
|
when Type::Time::Value then "'#{quoted_time(value)}'"
|
176
172
|
when Date, Time then "'#{quoted_date(value)}'"
|
177
|
-
when Symbol then "'#{quote_string(value.to_s)}'"
|
178
173
|
when Class then "'#{value}'"
|
179
174
|
else raise TypeError, "can't quote #{value.class.name}"
|
180
175
|
end
|
@@ -188,10 +183,9 @@ module ActiveRecord
|
|
188
183
|
when false then unquoted_false
|
189
184
|
# BigDecimals need to be put in a non-normalized form and quoted.
|
190
185
|
when BigDecimal then value.to_s("F")
|
186
|
+
when nil, Numeric, String then value
|
191
187
|
when Type::Time::Value then quoted_time(value)
|
192
188
|
when Date, Time then quoted_date(value)
|
193
|
-
when *types_which_need_no_typecasting
|
194
|
-
value
|
195
189
|
else raise TypeError
|
196
190
|
end
|
197
191
|
end
|
@@ -1,7 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "active_support/core_ext/string/strip"
|
4
|
-
|
5
3
|
module ActiveRecord
|
6
4
|
module ConnectionAdapters
|
7
5
|
class AbstractAdapter
|
@@ -17,14 +15,13 @@ module ActiveRecord
|
|
17
15
|
end
|
18
16
|
|
19
17
|
delegate :quote_column_name, :quote_table_name, :quote_default_expression, :type_to_sql,
|
20
|
-
:options_include_default?, :supports_indexes_in_create?, :supports_foreign_keys_in_create?, :foreign_key_options,
|
21
|
-
|
22
|
-
:options_include_default?, :supports_indexes_in_create?, :supports_foreign_keys_in_create?, :foreign_key_options
|
18
|
+
:options_include_default?, :supports_indexes_in_create?, :supports_foreign_keys_in_create?, :foreign_key_options,
|
19
|
+
to: :@conn, private: true
|
23
20
|
|
24
21
|
private
|
25
22
|
|
26
23
|
def visit_AlterTable(o)
|
27
|
-
sql = "ALTER TABLE #{quote_table_name(o.name)} "
|
24
|
+
sql = +"ALTER TABLE #{quote_table_name(o.name)} "
|
28
25
|
sql << o.adds.map { |col| accept col }.join(" ")
|
29
26
|
sql << o.foreign_key_adds.map { |fk| visit_AddForeignKey fk }.join(" ")
|
30
27
|
sql << o.foreign_key_drops.map { |fk| visit_DropForeignKey fk }.join(" ")
|
@@ -32,17 +29,19 @@ module ActiveRecord
|
|
32
29
|
|
33
30
|
def visit_ColumnDefinition(o)
|
34
31
|
o.sql_type = type_to_sql(o.type, o.options)
|
35
|
-
column_sql = "#{quote_column_name(o.name)} #{o.sql_type}"
|
32
|
+
column_sql = +"#{quote_column_name(o.name)} #{o.sql_type}"
|
36
33
|
add_column_options!(column_sql, column_options(o)) unless o.type == :primary_key
|
37
34
|
column_sql
|
38
35
|
end
|
39
36
|
|
40
37
|
def visit_AddColumnDefinition(o)
|
41
|
-
"ADD #{accept(o.column)}"
|
38
|
+
+"ADD #{accept(o.column)}"
|
42
39
|
end
|
43
40
|
|
44
41
|
def visit_TableDefinition(o)
|
45
|
-
create_sql = "CREATE#{
|
42
|
+
create_sql = +"CREATE#{table_modifier_in_create(o)} TABLE "
|
43
|
+
create_sql << "IF NOT EXISTS " if o.if_not_exists
|
44
|
+
create_sql << "#{quote_table_name(o.name)} "
|
46
45
|
|
47
46
|
statements = o.columns.map { |c| accept c }
|
48
47
|
statements << accept(o.primary_keys) if o.primary_keys
|
@@ -66,7 +65,7 @@ module ActiveRecord
|
|
66
65
|
end
|
67
66
|
|
68
67
|
def visit_ForeignKeyDefinition(o)
|
69
|
-
sql =
|
68
|
+
sql = +<<~SQL
|
70
69
|
CONSTRAINT #{quote_column_name(o.name)}
|
71
70
|
FOREIGN KEY (#{quote_column_name(o.column)})
|
72
71
|
REFERENCES #{quote_table_name(o.to_table)} (#{quote_column_name(o.primary_key)})
|
@@ -122,6 +121,11 @@ module ActiveRecord
|
|
122
121
|
sql
|
123
122
|
end
|
124
123
|
|
124
|
+
# Returns any SQL string to go between CREATE and TABLE. May be nil.
|
125
|
+
def table_modifier_in_create(o)
|
126
|
+
" TEMPORARY" if o.temporary
|
127
|
+
end
|
128
|
+
|
125
129
|
def foreign_key_in_create(from_table, to_table, options)
|
126
130
|
options = foreign_key_options(from_table, to_table, options)
|
127
131
|
accept ForeignKeyDefinition.new(from_table, to_table, options)
|
@@ -133,7 +137,7 @@ module ActiveRecord
|
|
133
137
|
when :cascade then "ON #{action} CASCADE"
|
134
138
|
when :restrict then "ON #{action} RESTRICT"
|
135
139
|
else
|
136
|
-
raise ArgumentError,
|
140
|
+
raise ArgumentError, <<~MSG
|
137
141
|
'#{dependency}' is not supported for :on_update or :on_delete.
|
138
142
|
Supported values are: :nullify, :cascade, :restrict
|
139
143
|
MSG
|