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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +734 -1058
- data/MIT-LICENSE +1 -1
- data/README.rdoc +1 -1
- data/lib/active_record/aggregations.rb +1 -1
- data/lib/active_record/association_relation.rb +0 -10
- data/lib/active_record/associations/association.rb +35 -7
- data/lib/active_record/associations/association_scope.rb +1 -3
- data/lib/active_record/associations/belongs_to_association.rb +16 -6
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +10 -2
- data/lib/active_record/associations/builder/association.rb +8 -2
- data/lib/active_record/associations/builder/belongs_to.rb +19 -6
- data/lib/active_record/associations/builder/collection_association.rb +1 -1
- data/lib/active_record/associations/builder/has_many.rb +3 -2
- data/lib/active_record/associations/builder/has_one.rb +2 -1
- data/lib/active_record/associations/builder/singular_association.rb +2 -2
- data/lib/active_record/associations/collection_association.rb +24 -25
- data/lib/active_record/associations/collection_proxy.rb +8 -3
- data/lib/active_record/associations/disable_joins_association_scope.rb +59 -0
- data/lib/active_record/associations/has_many_association.rb +1 -1
- data/lib/active_record/associations/has_many_through_association.rb +2 -1
- data/lib/active_record/associations/has_one_association.rb +10 -7
- data/lib/active_record/associations/has_one_through_association.rb +1 -1
- data/lib/active_record/associations/preloader/association.rb +161 -49
- data/lib/active_record/associations/preloader/batch.rb +51 -0
- data/lib/active_record/associations/preloader/branch.rb +147 -0
- data/lib/active_record/associations/preloader/through_association.rb +37 -11
- data/lib/active_record/associations/preloader.rb +46 -110
- data/lib/active_record/associations/singular_association.rb +8 -2
- data/lib/active_record/associations/through_association.rb +1 -1
- data/lib/active_record/associations.rb +76 -81
- data/lib/active_record/asynchronous_queries_tracker.rb +57 -0
- data/lib/active_record/attribute_assignment.rb +1 -1
- data/lib/active_record/attribute_methods/before_type_cast.rb +7 -2
- data/lib/active_record/attribute_methods/dirty.rb +41 -16
- data/lib/active_record/attribute_methods/primary_key.rb +2 -2
- data/lib/active_record/attribute_methods/query.rb +2 -2
- data/lib/active_record/attribute_methods/read.rb +7 -5
- data/lib/active_record/attribute_methods/serialization.rb +66 -12
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +4 -3
- data/lib/active_record/attribute_methods/write.rb +7 -10
- data/lib/active_record/attribute_methods.rb +6 -9
- data/lib/active_record/attributes.rb +24 -35
- data/lib/active_record/autosave_association.rb +3 -18
- data/lib/active_record/base.rb +19 -1
- data/lib/active_record/callbacks.rb +2 -2
- data/lib/active_record/coders/yaml_column.rb +11 -1
- data/lib/active_record/connection_adapters/abstract/connection_handler.rb +312 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +209 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +76 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +31 -558
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +45 -21
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +24 -12
- data/lib/active_record/connection_adapters/abstract/quoting.rb +14 -7
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +5 -18
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +30 -9
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +60 -16
- data/lib/active_record/connection_adapters/abstract/transaction.rb +17 -6
- data/lib/active_record/connection_adapters/abstract_adapter.rb +115 -69
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +96 -81
- data/lib/active_record/connection_adapters/legacy_pool_manager.rb +6 -2
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +33 -21
- data/lib/active_record/connection_adapters/mysql/quoting.rb +16 -1
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +3 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +12 -6
- data/lib/active_record/connection_adapters/pool_config.rb +1 -3
- data/lib/active_record/connection_adapters/pool_manager.rb +5 -1
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +19 -12
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +8 -0
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +5 -0
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +53 -14
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/timestamp.rb +15 -0
- data/lib/active_record/connection_adapters/postgresql/oid/timestamp_with_time_zone.rb +28 -0
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +18 -6
- data/lib/active_record/connection_adapters/postgresql/oid.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +6 -6
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +32 -0
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +5 -1
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +12 -12
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +157 -100
- data/lib/active_record/connection_adapters/schema_cache.rb +35 -4
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +0 -2
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +23 -17
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +4 -2
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +61 -30
- data/lib/active_record/connection_adapters.rb +8 -5
- data/lib/active_record/connection_handling.rb +20 -38
- data/lib/active_record/core.rb +129 -117
- data/lib/active_record/database_configurations/database_config.rb +12 -0
- data/lib/active_record/database_configurations/hash_config.rb +27 -1
- data/lib/active_record/database_configurations/url_config.rb +2 -2
- data/lib/active_record/database_configurations.rb +18 -9
- data/lib/active_record/delegated_type.rb +33 -11
- data/lib/active_record/destroy_association_async_job.rb +1 -1
- data/lib/active_record/disable_joins_association_relation.rb +39 -0
- data/lib/active_record/dynamic_matchers.rb +1 -1
- data/lib/active_record/encryption/cipher/aes256_gcm.rb +98 -0
- data/lib/active_record/encryption/cipher.rb +53 -0
- data/lib/active_record/encryption/config.rb +44 -0
- data/lib/active_record/encryption/configurable.rb +61 -0
- data/lib/active_record/encryption/context.rb +35 -0
- data/lib/active_record/encryption/contexts.rb +72 -0
- data/lib/active_record/encryption/derived_secret_key_provider.rb +12 -0
- data/lib/active_record/encryption/deterministic_key_provider.rb +14 -0
- data/lib/active_record/encryption/encryptable_record.rb +208 -0
- data/lib/active_record/encryption/encrypted_attribute_type.rb +140 -0
- data/lib/active_record/encryption/encrypted_fixtures.rb +38 -0
- data/lib/active_record/encryption/encrypting_only_encryptor.rb +12 -0
- data/lib/active_record/encryption/encryptor.rb +155 -0
- data/lib/active_record/encryption/envelope_encryption_key_provider.rb +55 -0
- data/lib/active_record/encryption/errors.rb +15 -0
- data/lib/active_record/encryption/extended_deterministic_queries.rb +160 -0
- data/lib/active_record/encryption/extended_deterministic_uniqueness_validator.rb +29 -0
- data/lib/active_record/encryption/key.rb +28 -0
- data/lib/active_record/encryption/key_generator.rb +42 -0
- data/lib/active_record/encryption/key_provider.rb +46 -0
- data/lib/active_record/encryption/message.rb +33 -0
- data/lib/active_record/encryption/message_serializer.rb +80 -0
- data/lib/active_record/encryption/null_encryptor.rb +21 -0
- data/lib/active_record/encryption/properties.rb +76 -0
- data/lib/active_record/encryption/read_only_null_encryptor.rb +24 -0
- data/lib/active_record/encryption/scheme.rb +99 -0
- data/lib/active_record/encryption.rb +55 -0
- data/lib/active_record/enum.rb +44 -46
- data/lib/active_record/errors.rb +66 -3
- data/lib/active_record/fixture_set/file.rb +15 -1
- data/lib/active_record/fixture_set/table_row.rb +40 -5
- data/lib/active_record/fixture_set/table_rows.rb +4 -4
- data/lib/active_record/fixtures.rb +16 -11
- data/lib/active_record/future_result.rb +139 -0
- data/lib/active_record/gem_version.rb +4 -4
- data/lib/active_record/inheritance.rb +55 -17
- data/lib/active_record/insert_all.rb +39 -6
- data/lib/active_record/integration.rb +1 -1
- data/lib/active_record/internal_metadata.rb +3 -5
- data/lib/active_record/legacy_yaml_adapter.rb +1 -1
- data/lib/active_record/locking/optimistic.rb +10 -9
- data/lib/active_record/log_subscriber.rb +6 -2
- data/lib/active_record/middleware/database_selector/resolver.rb +6 -10
- data/lib/active_record/middleware/database_selector.rb +8 -3
- data/lib/active_record/migration/command_recorder.rb +4 -4
- data/lib/active_record/migration/compatibility.rb +83 -1
- data/lib/active_record/migration/join_table.rb +1 -1
- data/lib/active_record/migration.rb +109 -79
- data/lib/active_record/model_schema.rb +46 -32
- data/lib/active_record/nested_attributes.rb +3 -3
- data/lib/active_record/no_touching.rb +2 -2
- data/lib/active_record/null_relation.rb +2 -6
- data/lib/active_record/persistence.rb +134 -45
- data/lib/active_record/query_cache.rb +2 -2
- data/lib/active_record/query_logs.rb +203 -0
- data/lib/active_record/querying.rb +15 -5
- data/lib/active_record/railtie.rb +117 -17
- data/lib/active_record/railties/controller_runtime.rb +1 -1
- data/lib/active_record/railties/databases.rake +83 -58
- data/lib/active_record/readonly_attributes.rb +11 -0
- data/lib/active_record/reflection.rb +45 -44
- data/lib/active_record/relation/batches/batch_enumerator.rb +19 -5
- data/lib/active_record/relation/batches.rb +3 -3
- data/lib/active_record/relation/calculations.rb +42 -25
- data/lib/active_record/relation/delegation.rb +6 -6
- data/lib/active_record/relation/finder_methods.rb +32 -23
- data/lib/active_record/relation/merger.rb +20 -13
- data/lib/active_record/relation/predicate_builder.rb +1 -6
- data/lib/active_record/relation/query_attribute.rb +5 -11
- data/lib/active_record/relation/query_methods.rb +233 -50
- data/lib/active_record/relation/record_fetch_warning.rb +2 -2
- data/lib/active_record/relation/spawn_methods.rb +2 -2
- data/lib/active_record/relation/where_clause.rb +22 -15
- data/lib/active_record/relation.rb +170 -87
- data/lib/active_record/result.rb +17 -2
- data/lib/active_record/runtime_registry.rb +2 -4
- data/lib/active_record/sanitization.rb +11 -7
- data/lib/active_record/schema_dumper.rb +3 -3
- data/lib/active_record/schema_migration.rb +0 -4
- data/lib/active_record/scoping/default.rb +62 -15
- data/lib/active_record/scoping/named.rb +3 -11
- data/lib/active_record/scoping.rb +40 -22
- data/lib/active_record/serialization.rb +1 -1
- data/lib/active_record/signed_id.rb +1 -1
- data/lib/active_record/statement_cache.rb +2 -2
- data/lib/active_record/tasks/database_tasks.rb +107 -23
- data/lib/active_record/tasks/mysql_database_tasks.rb +1 -1
- data/lib/active_record/tasks/postgresql_database_tasks.rb +14 -11
- data/lib/active_record/test_databases.rb +1 -1
- data/lib/active_record/test_fixtures.rb +45 -4
- data/lib/active_record/timestamp.rb +3 -4
- data/lib/active_record/transactions.rb +9 -14
- data/lib/active_record/translation.rb +2 -2
- data/lib/active_record/type/adapter_specific_registry.rb +32 -7
- data/lib/active_record/type/hash_lookup_type_map.rb +34 -1
- data/lib/active_record/type/internal/timezone.rb +2 -2
- data/lib/active_record/type/serialized.rb +1 -1
- data/lib/active_record/type/type_map.rb +17 -20
- data/lib/active_record/type.rb +1 -2
- data/lib/active_record/validations/associated.rb +1 -1
- data/lib/active_record/validations/numericality.rb +1 -1
- data/lib/active_record.rb +170 -2
- data/lib/arel/attributes/attribute.rb +0 -8
- data/lib/arel/collectors/bind.rb +2 -2
- data/lib/arel/collectors/composite.rb +3 -3
- data/lib/arel/collectors/sql_string.rb +1 -1
- data/lib/arel/collectors/substitute_binds.rb +1 -1
- data/lib/arel/crud.rb +18 -22
- data/lib/arel/delete_manager.rb +2 -4
- data/lib/arel/insert_manager.rb +2 -3
- data/lib/arel/nodes/casted.rb +1 -1
- data/lib/arel/nodes/delete_statement.rb +8 -13
- data/lib/arel/nodes/homogeneous_in.rb +4 -0
- data/lib/arel/nodes/insert_statement.rb +2 -2
- data/lib/arel/nodes/select_core.rb +2 -2
- data/lib/arel/nodes/select_statement.rb +2 -2
- data/lib/arel/nodes/update_statement.rb +3 -2
- data/lib/arel/predications.rb +3 -3
- data/lib/arel/select_manager.rb +10 -4
- data/lib/arel/table.rb +0 -1
- data/lib/arel/tree_manager.rb +0 -12
- data/lib/arel/update_manager.rb +2 -4
- data/lib/arel/visitors/dot.rb +80 -90
- data/lib/arel/visitors/mysql.rb +6 -1
- data/lib/arel/visitors/postgresql.rb +0 -10
- data/lib/arel/visitors/to_sql.rb +44 -3
- data/lib/arel.rb +1 -1
- data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +1 -1
- data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +1 -1
- data/lib/rails/generators/active_record/model/templates/model.rb.tt +1 -1
- data/lib/rails/generators/active_record/model/templates/module.rb.tt +2 -2
- metadata +55 -16
@@ -59,17 +59,13 @@ module ActiveRecord
|
|
59
59
|
end
|
60
60
|
|
61
61
|
# Returns an ActiveRecord::Result instance.
|
62
|
-
def select_all(arel, name = nil, binds = [], preparable: nil)
|
62
|
+
def select_all(arel, name = nil, binds = [], preparable: nil, async: false)
|
63
63
|
arel = arel_from_relation(arel)
|
64
64
|
sql, binds, preparable = to_sql_and_binds(arel, binds, preparable)
|
65
65
|
|
66
|
-
|
67
|
-
select_prepared(sql, name, binds)
|
68
|
-
else
|
69
|
-
select(sql, name, binds)
|
70
|
-
end
|
66
|
+
select(sql, name, binds, prepare: prepared_statements && preparable, async: async && FutureResult::SelectAll)
|
71
67
|
rescue ::RangeError
|
72
|
-
ActiveRecord::Result.
|
68
|
+
ActiveRecord::Result.empty
|
73
69
|
end
|
74
70
|
|
75
71
|
# Returns a record hash with the column names as keys and column values
|
@@ -310,20 +306,20 @@ module ActiveRecord
|
|
310
306
|
#
|
311
307
|
# The mysql2 and postgresql adapters support setting the transaction
|
312
308
|
# isolation level.
|
313
|
-
def transaction(requires_new: nil, isolation: nil, joinable: true)
|
309
|
+
def transaction(requires_new: nil, isolation: nil, joinable: true, &block)
|
314
310
|
if !requires_new && current_transaction.joinable?
|
315
311
|
if isolation
|
316
312
|
raise ActiveRecord::TransactionIsolationError, "cannot set isolation when joining a transaction"
|
317
313
|
end
|
318
314
|
yield
|
319
315
|
else
|
320
|
-
transaction_manager.within_new_transaction(isolation: isolation, joinable: joinable)
|
316
|
+
transaction_manager.within_new_transaction(isolation: isolation, joinable: joinable, &block)
|
321
317
|
end
|
322
318
|
rescue ActiveRecord::Rollback
|
323
319
|
# rollbacks are silently swallowed
|
324
320
|
end
|
325
321
|
|
326
|
-
attr_reader :transaction_manager
|
322
|
+
attr_reader :transaction_manager # :nodoc:
|
327
323
|
|
328
324
|
delegate :within_new_transaction, :open_transactions, :current_transaction, :begin_transaction,
|
329
325
|
:commit_transaction, :rollback_transaction, :materialize_transactions,
|
@@ -340,7 +336,7 @@ module ActiveRecord
|
|
340
336
|
current_transaction.open?
|
341
337
|
end
|
342
338
|
|
343
|
-
def reset_transaction
|
339
|
+
def reset_transaction # :nodoc:
|
344
340
|
@transaction_manager = ConnectionAdapters::TransactionManager.new(self)
|
345
341
|
end
|
346
342
|
|
@@ -378,7 +374,7 @@ module ActiveRecord
|
|
378
374
|
exec_rollback_db_transaction
|
379
375
|
end
|
380
376
|
|
381
|
-
def exec_rollback_db_transaction() end
|
377
|
+
def exec_rollback_db_transaction() end # :nodoc:
|
382
378
|
|
383
379
|
def rollback_to_savepoint(name = nil)
|
384
380
|
exec_rollback_to_savepoint(name)
|
@@ -445,6 +441,19 @@ module ActiveRecord
|
|
445
441
|
end
|
446
442
|
end
|
447
443
|
|
444
|
+
# This is a safe default, even if not high precision on all databases
|
445
|
+
HIGH_PRECISION_CURRENT_TIMESTAMP = Arel.sql("CURRENT_TIMESTAMP").freeze # :nodoc:
|
446
|
+
private_constant :HIGH_PRECISION_CURRENT_TIMESTAMP
|
447
|
+
|
448
|
+
# Returns an Arel SQL literal for the CURRENT_TIMESTAMP for usage with
|
449
|
+
# arbitrary precision date/time columns.
|
450
|
+
#
|
451
|
+
# Adapters supporting datetime with precision should override this to
|
452
|
+
# provide as much precision as is available.
|
453
|
+
def high_precision_current_timestamp
|
454
|
+
HIGH_PRECISION_CURRENT_TIMESTAMP
|
455
|
+
end
|
456
|
+
|
448
457
|
private
|
449
458
|
def execute_batch(statements, name = nil)
|
450
459
|
statements.each do |statement|
|
@@ -481,8 +490,7 @@ module ActiveRecord
|
|
481
490
|
end
|
482
491
|
|
483
492
|
table = Arel::Table.new(table_name)
|
484
|
-
manager = Arel::InsertManager.new
|
485
|
-
manager.into(table)
|
493
|
+
manager = Arel::InsertManager.new(table)
|
486
494
|
|
487
495
|
if values_list.size == 1
|
488
496
|
values = values_list.shift
|
@@ -503,10 +511,10 @@ module ActiveRecord
|
|
503
511
|
end
|
504
512
|
|
505
513
|
def build_fixture_statements(fixture_set)
|
506
|
-
fixture_set.
|
514
|
+
fixture_set.filter_map do |table_name, fixtures|
|
507
515
|
next if fixtures.empty?
|
508
516
|
build_fixture_sql(fixtures, table_name)
|
509
|
-
end
|
517
|
+
end
|
510
518
|
end
|
511
519
|
|
512
520
|
def build_truncate_statement(table_name)
|
@@ -528,12 +536,28 @@ module ActiveRecord
|
|
528
536
|
end
|
529
537
|
|
530
538
|
# Returns an ActiveRecord::Result instance.
|
531
|
-
def select(sql, name = nil, binds = [])
|
532
|
-
|
533
|
-
|
539
|
+
def select(sql, name = nil, binds = [], prepare: false, async: false)
|
540
|
+
if async && async_enabled?
|
541
|
+
if current_transaction.joinable?
|
542
|
+
raise AsynchronousQueryInsideTransactionError, "Asynchronous queries are not allowed inside transactions"
|
543
|
+
end
|
544
|
+
|
545
|
+
future_result = async.new(
|
546
|
+
pool,
|
547
|
+
sql,
|
548
|
+
name,
|
549
|
+
binds,
|
550
|
+
prepare: prepare,
|
551
|
+
)
|
552
|
+
if supports_concurrent_connections? && current_transaction.closed?
|
553
|
+
future_result.schedule!(ActiveRecord::Base.asynchronous_queries_session)
|
554
|
+
else
|
555
|
+
future_result.execute!(self)
|
556
|
+
end
|
557
|
+
return future_result
|
558
|
+
end
|
534
559
|
|
535
|
-
|
536
|
-
exec_query(sql, name, binds, prepare: true)
|
560
|
+
exec_query(sql, name, binds, prepare: prepare)
|
537
561
|
end
|
538
562
|
|
539
563
|
def sql_for_insert(sql, pk, binds)
|
@@ -6,7 +6,7 @@ module ActiveRecord
|
|
6
6
|
module ConnectionAdapters # :nodoc:
|
7
7
|
module QueryCache
|
8
8
|
class << self
|
9
|
-
def included(base)
|
9
|
+
def included(base) # :nodoc:
|
10
10
|
dirties_query_cache base, :create, :insert, :update, :delete, :truncate, :truncate_tables,
|
11
11
|
:rollback_to_savepoint, :rollback_db_transaction, :exec_insert_all
|
12
12
|
|
@@ -93,18 +93,37 @@ module ActiveRecord
|
|
93
93
|
end
|
94
94
|
end
|
95
95
|
|
96
|
-
def select_all(arel, name = nil, binds = [], preparable: nil)
|
97
|
-
|
98
|
-
|
96
|
+
def select_all(arel, name = nil, binds = [], preparable: nil, async: false)
|
97
|
+
arel = arel_from_relation(arel)
|
98
|
+
|
99
|
+
# If arel is locked this is a SELECT ... FOR UPDATE or somesuch.
|
100
|
+
# Such queries should not be cached.
|
101
|
+
if @query_cache_enabled && !(arel.respond_to?(:locked) && arel.locked)
|
99
102
|
sql, binds, preparable = to_sql_and_binds(arel, binds, preparable)
|
100
103
|
|
101
|
-
|
104
|
+
if async
|
105
|
+
lookup_sql_cache(sql, name, binds) || super(sql, name, binds, preparable: preparable, async: async)
|
106
|
+
else
|
107
|
+
cache_sql(sql, name, binds) { super(sql, name, binds, preparable: preparable, async: async) }
|
108
|
+
end
|
102
109
|
else
|
103
110
|
super
|
104
111
|
end
|
105
112
|
end
|
106
113
|
|
107
114
|
private
|
115
|
+
def lookup_sql_cache(sql, name, binds)
|
116
|
+
@lock.synchronize do
|
117
|
+
if @query_cache[sql].key?(binds)
|
118
|
+
ActiveSupport::Notifications.instrument(
|
119
|
+
"sql.active_record",
|
120
|
+
cache_notification_info(sql, name, binds)
|
121
|
+
)
|
122
|
+
@query_cache[sql][binds]
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
108
127
|
def cache_sql(sql, name, binds)
|
109
128
|
@lock.synchronize do
|
110
129
|
result =
|
@@ -134,13 +153,6 @@ module ActiveRecord
|
|
134
153
|
}
|
135
154
|
end
|
136
155
|
|
137
|
-
# If arel is locked this is a SELECT ... FOR UPDATE or somesuch. Such
|
138
|
-
# queries should not be cached.
|
139
|
-
def locked?(arel)
|
140
|
-
arel = arel.arel if arel.is_a?(Relation)
|
141
|
-
arel.respond_to?(:locked) && arel.locked
|
142
|
-
end
|
143
|
-
|
144
156
|
def configure_query_cache!
|
145
157
|
enable_query_cache! if pool.query_cache_enabled
|
146
158
|
end
|
@@ -12,7 +12,7 @@ module ActiveRecord
|
|
12
12
|
if value.is_a?(Base)
|
13
13
|
ActiveSupport::Deprecation.warn(<<~MSG)
|
14
14
|
Passing an Active Record object to `quote` directly is deprecated
|
15
|
-
and will be no longer quoted as id value in Rails
|
15
|
+
and will be no longer quoted as id value in Rails 7.0.
|
16
16
|
MSG
|
17
17
|
value = value.id_for_database
|
18
18
|
end
|
@@ -27,14 +27,14 @@ module ActiveRecord
|
|
27
27
|
if value.is_a?(Base)
|
28
28
|
ActiveSupport::Deprecation.warn(<<~MSG)
|
29
29
|
Passing an Active Record object to `type_cast` directly is deprecated
|
30
|
-
and will be no longer type casted as id value in Rails
|
30
|
+
and will be no longer type casted as id value in Rails 7.0.
|
31
31
|
MSG
|
32
32
|
value = value.id_for_database
|
33
33
|
end
|
34
34
|
|
35
35
|
if column
|
36
36
|
ActiveSupport::Deprecation.warn(<<~MSG)
|
37
|
-
Passing a column to `type_cast` is deprecated and will be removed in Rails
|
37
|
+
Passing a column to `type_cast` is deprecated and will be removed in Rails 7.0.
|
38
38
|
MSG
|
39
39
|
type = lookup_cast_type_from_column(column)
|
40
40
|
value = type.serialize(value)
|
@@ -43,6 +43,13 @@ module ActiveRecord
|
|
43
43
|
_type_cast(value)
|
44
44
|
end
|
45
45
|
|
46
|
+
# Quote a value to be used as a bound parameter of unknown type. For example,
|
47
|
+
# MySQL might perform dangerous castings when comparing a string to a number,
|
48
|
+
# so this method will cast numbers to string.
|
49
|
+
def quote_bound_value(value)
|
50
|
+
_quote(value)
|
51
|
+
end
|
52
|
+
|
46
53
|
# If you are having to call this function, you are likely doing something
|
47
54
|
# wrong. The column does not have sufficient type information if the user
|
48
55
|
# provided a custom type on the class level either explicitly (via
|
@@ -59,7 +66,7 @@ module ActiveRecord
|
|
59
66
|
# Quotes a string, escaping any ' (single quote) and \ (backslash)
|
60
67
|
# characters.
|
61
68
|
def quote_string(s)
|
62
|
-
s.gsub(
|
69
|
+
s.gsub("\\", '\&\&').gsub("'", "''") # ' (for ruby-mode)
|
63
70
|
end
|
64
71
|
|
65
72
|
# Quotes the column name. Defaults to no quoting.
|
@@ -113,10 +120,10 @@ module ActiveRecord
|
|
113
120
|
# if the value is a Time responding to usec.
|
114
121
|
def quoted_date(value)
|
115
122
|
if value.acts_like?(:time)
|
116
|
-
if ActiveRecord
|
117
|
-
value = value.getutc if
|
123
|
+
if ActiveRecord.default_timezone == :utc
|
124
|
+
value = value.getutc if !value.utc?
|
118
125
|
else
|
119
|
-
value = value.getlocal
|
126
|
+
value = value.getlocal
|
120
127
|
end
|
121
128
|
end
|
122
129
|
|
@@ -14,8 +14,8 @@ module ActiveRecord
|
|
14
14
|
end
|
15
15
|
|
16
16
|
delegate :quote_column_name, :quote_table_name, :quote_default_expression, :type_to_sql,
|
17
|
-
:options_include_default?, :supports_indexes_in_create?, :supports_foreign_keys?,
|
18
|
-
:quoted_columns_for_index, :supports_partial_index?, :supports_check_constraints?,
|
17
|
+
:options_include_default?, :supports_indexes_in_create?, :supports_foreign_keys?,
|
18
|
+
:quoted_columns_for_index, :supports_partial_index?, :supports_check_constraints?,
|
19
19
|
to: :@conn, private: true
|
20
20
|
|
21
21
|
private
|
@@ -52,11 +52,11 @@ module ActiveRecord
|
|
52
52
|
end
|
53
53
|
|
54
54
|
if supports_foreign_keys?
|
55
|
-
statements.concat(o.foreign_keys.map { |
|
55
|
+
statements.concat(o.foreign_keys.map { |fk| accept fk })
|
56
56
|
end
|
57
57
|
|
58
58
|
if supports_check_constraints?
|
59
|
-
statements.concat(o.check_constraints.map { |
|
59
|
+
statements.concat(o.check_constraints.map { |chk| accept chk })
|
60
60
|
end
|
61
61
|
|
62
62
|
create_sql << "(#{statements.join(', ')})" if statements.present?
|
@@ -94,8 +94,8 @@ module ActiveRecord
|
|
94
94
|
sql = ["CREATE"]
|
95
95
|
sql << "UNIQUE" if index.unique
|
96
96
|
sql << "INDEX"
|
97
|
-
sql << "IF NOT EXISTS" if o.if_not_exists
|
98
97
|
sql << o.algorithm if o.algorithm
|
98
|
+
sql << "IF NOT EXISTS" if o.if_not_exists
|
99
99
|
sql << index.type if index.type
|
100
100
|
sql << "#{quote_column_name(index.name)} ON #{quote_table_name(index.table)}"
|
101
101
|
sql << "USING #{index.using}" if supports_index_using? && index.using
|
@@ -159,19 +159,6 @@ module ActiveRecord
|
|
159
159
|
" TEMPORARY" if o.temporary
|
160
160
|
end
|
161
161
|
|
162
|
-
def foreign_key_in_create(from_table, to_table, options)
|
163
|
-
prefix = ActiveRecord::Base.table_name_prefix
|
164
|
-
suffix = ActiveRecord::Base.table_name_suffix
|
165
|
-
to_table = "#{prefix}#{to_table}#{suffix}"
|
166
|
-
options = foreign_key_options(from_table, to_table, options)
|
167
|
-
accept ForeignKeyDefinition.new(from_table, to_table, options)
|
168
|
-
end
|
169
|
-
|
170
|
-
def check_constraint_in_create(table_name, expression, options)
|
171
|
-
options = check_constraint_options(table_name, expression, options)
|
172
|
-
accept CheckConstraintDefinition.new(table_name, expression, options)
|
173
|
-
end
|
174
|
-
|
175
162
|
def action_sql(action, dependency)
|
176
163
|
case dependency
|
177
164
|
when :nullify then "ON #{action} SET NULL"
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module ActiveRecord
|
4
|
-
module ConnectionAdapters
|
4
|
+
module ConnectionAdapters # :nodoc:
|
5
5
|
# Abstract representation of an index definition on a table. Instances of
|
6
6
|
# this type are typically created and returned by methods in database
|
7
7
|
# adapters. e.g. ActiveRecord::ConnectionAdapters::MySQL::SchemaStatements#indexes
|
@@ -79,13 +79,13 @@ module ActiveRecord
|
|
79
79
|
|
80
80
|
AddColumnDefinition = Struct.new(:column) # :nodoc:
|
81
81
|
|
82
|
-
ChangeColumnDefinition = Struct.new(:column, :name)
|
82
|
+
ChangeColumnDefinition = Struct.new(:column, :name) # :nodoc:
|
83
83
|
|
84
84
|
CreateIndexDefinition = Struct.new(:index, :algorithm, :if_not_exists) # :nodoc:
|
85
85
|
|
86
86
|
PrimaryKeyDefinition = Struct.new(:name) # :nodoc:
|
87
87
|
|
88
|
-
ForeignKeyDefinition = Struct.new(:from_table, :to_table, :options) do
|
88
|
+
ForeignKeyDefinition = Struct.new(:from_table, :to_table, :options) do # :nodoc:
|
89
89
|
def name
|
90
90
|
options[:name]
|
91
91
|
end
|
@@ -253,6 +253,7 @@ module ActiveRecord
|
|
253
253
|
define_column_methods :bigint, :binary, :boolean, :date, :datetime, :decimal,
|
254
254
|
:float, :integer, :json, :string, :text, :time, :timestamp, :virtual
|
255
255
|
|
256
|
+
alias :blob :binary
|
256
257
|
alias :numeric :decimal
|
257
258
|
end
|
258
259
|
|
@@ -277,7 +278,7 @@ module ActiveRecord
|
|
277
278
|
# Inside migration files, the +t+ object in {create_table}[rdoc-ref:SchemaStatements#create_table]
|
278
279
|
# is actually of this type:
|
279
280
|
#
|
280
|
-
# class SomeMigration < ActiveRecord::Migration[
|
281
|
+
# class SomeMigration < ActiveRecord::Migration[7.0]
|
281
282
|
# def up
|
282
283
|
# create_table :foo do |t|
|
283
284
|
# puts t.class # => "ActiveRecord::ConnectionAdapters::TableDefinition"
|
@@ -410,6 +411,12 @@ module ActiveRecord
|
|
410
411
|
end
|
411
412
|
end
|
412
413
|
|
414
|
+
if @conn.supports_datetime_with_precision?
|
415
|
+
if type == :datetime && !options.key?(:precision)
|
416
|
+
options[:precision] = 6
|
417
|
+
end
|
418
|
+
end
|
419
|
+
|
413
420
|
@columns_hash[name] = new_column_definition(name, type, **options)
|
414
421
|
|
415
422
|
if index
|
@@ -434,12 +441,12 @@ module ActiveRecord
|
|
434
441
|
indexes << [column_name, options]
|
435
442
|
end
|
436
443
|
|
437
|
-
def foreign_key(
|
438
|
-
foreign_keys <<
|
444
|
+
def foreign_key(to_table, **options)
|
445
|
+
foreign_keys << new_foreign_key_definition(to_table, options)
|
439
446
|
end
|
440
447
|
|
441
448
|
def check_constraint(expression, **options)
|
442
|
-
check_constraints <<
|
449
|
+
check_constraints << new_check_constraint_definition(expression, options)
|
443
450
|
end
|
444
451
|
|
445
452
|
# Appends <tt>:datetime</tt> columns <tt>:created_at</tt> and
|
@@ -481,6 +488,19 @@ module ActiveRecord
|
|
481
488
|
create_column_definition(name, type, options)
|
482
489
|
end
|
483
490
|
|
491
|
+
def new_foreign_key_definition(to_table, options) # :nodoc:
|
492
|
+
prefix = ActiveRecord::Base.table_name_prefix
|
493
|
+
suffix = ActiveRecord::Base.table_name_suffix
|
494
|
+
to_table = "#{prefix}#{to_table}#{suffix}"
|
495
|
+
options = @conn.foreign_key_options(name, to_table, options)
|
496
|
+
ForeignKeyDefinition.new(name, to_table, options)
|
497
|
+
end
|
498
|
+
|
499
|
+
def new_check_constraint_definition(expression, options) # :nodoc:
|
500
|
+
options = @conn.check_constraint_options(name, expression, options)
|
501
|
+
CheckConstraintDefinition.new(name, expression, options)
|
502
|
+
end
|
503
|
+
|
484
504
|
private
|
485
505
|
def create_column_definition(name, type, options)
|
486
506
|
ColumnDefinition.new(name, type, options)
|
@@ -516,7 +536,7 @@ module ActiveRecord
|
|
516
536
|
def name; @td.name; end
|
517
537
|
|
518
538
|
def add_foreign_key(to_table, options)
|
519
|
-
@foreign_key_adds <<
|
539
|
+
@foreign_key_adds << @td.new_foreign_key_definition(to_table, options)
|
520
540
|
end
|
521
541
|
|
522
542
|
def drop_foreign_key(name)
|
@@ -524,7 +544,7 @@ module ActiveRecord
|
|
524
544
|
end
|
525
545
|
|
526
546
|
def add_check_constraint(expression, options)
|
527
|
-
@check_constraint_adds <<
|
547
|
+
@check_constraint_adds << @td.new_check_constraint_definition(expression, options)
|
528
548
|
end
|
529
549
|
|
530
550
|
def drop_check_constraint(constraint_name)
|
@@ -568,6 +588,7 @@ module ActiveRecord
|
|
568
588
|
# t.time
|
569
589
|
# t.date
|
570
590
|
# t.binary
|
591
|
+
# t.blob
|
571
592
|
# t.boolean
|
572
593
|
# t.foreign_key
|
573
594
|
# t.json
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "active_support/core_ext/string/access"
|
4
|
-
require "
|
4
|
+
require "openssl"
|
5
5
|
|
6
6
|
module ActiveRecord
|
7
7
|
module ConnectionAdapters # :nodoc:
|
@@ -29,7 +29,7 @@ module ActiveRecord
|
|
29
29
|
table_name[0...table_alias_length].tr(".", "_")
|
30
30
|
end
|
31
31
|
|
32
|
-
# Returns the relation names
|
32
|
+
# Returns the relation names usable to back Active Record models.
|
33
33
|
# For most adapters this means all #tables and #views.
|
34
34
|
def data_sources
|
35
35
|
query_values(data_source_sql, "SCHEMA")
|
@@ -518,24 +518,31 @@ module ActiveRecord
|
|
518
518
|
|
519
519
|
# Add a new +type+ column named +column_name+ to +table_name+.
|
520
520
|
#
|
521
|
+
# See {ActiveRecord::ConnectionAdapters::TableDefinition.column}[rdoc-ref:ActiveRecord::ConnectionAdapters::TableDefinition#column].
|
522
|
+
#
|
521
523
|
# The +type+ parameter is normally one of the migrations native types,
|
522
524
|
# which is one of the following:
|
523
525
|
# <tt>:primary_key</tt>, <tt>:string</tt>, <tt>:text</tt>,
|
524
526
|
# <tt>:integer</tt>, <tt>:bigint</tt>, <tt>:float</tt>, <tt>:decimal</tt>, <tt>:numeric</tt>,
|
525
527
|
# <tt>:datetime</tt>, <tt>:time</tt>, <tt>:date</tt>,
|
526
|
-
# <tt>:binary</tt>, <tt>:boolean</tt>.
|
528
|
+
# <tt>:binary</tt>, <tt>:blob</tt>, <tt>:boolean</tt>.
|
527
529
|
#
|
528
530
|
# You may use a type not in this list as long as it is supported by your
|
529
531
|
# database (for example, "polygon" in MySQL), but this will not be database
|
530
532
|
# agnostic and should usually be avoided.
|
531
533
|
#
|
532
534
|
# Available options are (none of these exists by default):
|
535
|
+
# * <tt>:comment</tt> -
|
536
|
+
# Specifies the comment for the column. This option is ignored by some backends.
|
537
|
+
# * <tt>:collation</tt> -
|
538
|
+
# Specifies the collation for a <tt>:string</tt> or <tt>:text</tt> column.
|
539
|
+
# If not specified, the column will have the same collation as the table.
|
540
|
+
# * <tt>:default</tt> -
|
541
|
+
# The column's default value. Use +nil+ for +NULL+.
|
533
542
|
# * <tt>:limit</tt> -
|
534
543
|
# Requests a maximum column length. This is the number of characters for a <tt>:string</tt> column
|
535
|
-
# and number of bytes for <tt>:text</tt>, <tt>:binary</tt>, and <tt>:integer</tt> columns.
|
544
|
+
# and number of bytes for <tt>:text</tt>, <tt>:binary</tt>, <tt>:blob</tt>, and <tt>:integer</tt> columns.
|
536
545
|
# This option is ignored by some backends.
|
537
|
-
# * <tt>:default</tt> -
|
538
|
-
# The column's default value. Use +nil+ for +NULL+.
|
539
546
|
# * <tt>:null</tt> -
|
540
547
|
# Allows or disallows +NULL+ values in the column.
|
541
548
|
# * <tt>:precision</tt> -
|
@@ -604,7 +611,13 @@ module ActiveRecord
|
|
604
611
|
# # Ignores the method call if the column exists
|
605
612
|
# add_column(:shapes, :triangle, 'polygon', if_not_exists: true)
|
606
613
|
def add_column(table_name, column_name, type, **options)
|
607
|
-
return if options[:if_not_exists] == true && column_exists?(table_name, column_name
|
614
|
+
return if options[:if_not_exists] == true && column_exists?(table_name, column_name)
|
615
|
+
|
616
|
+
if supports_datetime_with_precision?
|
617
|
+
if type == :datetime && !options.key?(:precision)
|
618
|
+
options[:precision] = 6
|
619
|
+
end
|
620
|
+
end
|
608
621
|
|
609
622
|
at = create_alter_table table_name
|
610
623
|
at.add_column(column_name, type, **options)
|
@@ -629,9 +642,8 @@ module ActiveRecord
|
|
629
642
|
raise ArgumentError.new("You must specify at least one column name. Example: remove_columns(:people, :first_name)")
|
630
643
|
end
|
631
644
|
|
632
|
-
column_names
|
633
|
-
|
634
|
-
end
|
645
|
+
remove_column_fragments = remove_columns_for_alter(table_name, *column_names, type: type, **options)
|
646
|
+
execute "ALTER TABLE #{quote_table_name(table_name)} #{remove_column_fragments.join(', ')}"
|
635
647
|
end
|
636
648
|
|
637
649
|
# Removes the column from the table definition.
|
@@ -901,7 +913,7 @@ module ActiveRecord
|
|
901
913
|
remove_index(table_name, name: old_name)
|
902
914
|
end
|
903
915
|
|
904
|
-
def index_name(table_name, options)
|
916
|
+
def index_name(table_name, options) # :nodoc:
|
905
917
|
if Hash === options
|
906
918
|
if options[:column]
|
907
919
|
"index_#{table_name}_on_#{Array(options[:column]) * '_and_'}"
|
@@ -1027,6 +1039,10 @@ module ActiveRecord
|
|
1027
1039
|
#
|
1028
1040
|
# ALTER TABLE "articles" ADD CONSTRAINT fk_rails_e74ce85cbc FOREIGN KEY ("author_id") REFERENCES "authors" ("id")
|
1029
1041
|
#
|
1042
|
+
# ====== Creating a foreign key, ignoring method call if the foreign key exists
|
1043
|
+
#
|
1044
|
+
# add_foreign_key(:articles, :authors, if_not_exists: true)
|
1045
|
+
#
|
1030
1046
|
# ====== Creating a foreign key on a specific column
|
1031
1047
|
#
|
1032
1048
|
# add_foreign_key :articles, :users, column: :author_id, primary_key: "lng_id"
|
@@ -1054,10 +1070,14 @@ module ActiveRecord
|
|
1054
1070
|
# Action that happens <tt>ON DELETE</tt>. Valid values are +:nullify+, +:cascade+ and +:restrict+
|
1055
1071
|
# [<tt>:on_update</tt>]
|
1056
1072
|
# Action that happens <tt>ON UPDATE</tt>. Valid values are +:nullify+, +:cascade+ and +:restrict+
|
1073
|
+
# [<tt>:if_not_exists</tt>]
|
1074
|
+
# Specifies if the foreign key already exists to not try to re-add it. This will avoid
|
1075
|
+
# duplicate column errors.
|
1057
1076
|
# [<tt>:validate</tt>]
|
1058
1077
|
# (PostgreSQL only) Specify whether or not the constraint should be validated. Defaults to +true+.
|
1059
1078
|
def add_foreign_key(from_table, to_table, **options)
|
1060
1079
|
return unless supports_foreign_keys?
|
1080
|
+
return if options[:if_not_exists] == true && foreign_key_exists?(from_table, to_table)
|
1061
1081
|
|
1062
1082
|
options = foreign_key_options(from_table, to_table, options)
|
1063
1083
|
at = create_alter_table from_table
|
@@ -1087,12 +1107,18 @@ module ActiveRecord
|
|
1087
1107
|
#
|
1088
1108
|
# remove_foreign_key :accounts, name: :special_fk_name
|
1089
1109
|
#
|
1110
|
+
# Checks if the foreign key exists before trying to remove it. Will silently ignore indexes that
|
1111
|
+
# don't exist.
|
1112
|
+
#
|
1113
|
+
# remove_foreign_key :accounts, :branches, if_exists: true
|
1114
|
+
#
|
1090
1115
|
# The +options+ hash accepts the same keys as SchemaStatements#add_foreign_key
|
1091
1116
|
# with an addition of
|
1092
1117
|
# [<tt>:to_table</tt>]
|
1093
1118
|
# The name of the table that contains the referenced primary key.
|
1094
1119
|
def remove_foreign_key(from_table, to_table = nil, **options)
|
1095
1120
|
return unless supports_foreign_keys?
|
1121
|
+
return if options[:if_exists] == true && !foreign_key_exists?(from_table, to_table)
|
1096
1122
|
|
1097
1123
|
fk_name_to_delete = foreign_key_for!(from_table, to_table: to_table, **options).name
|
1098
1124
|
|
@@ -1256,6 +1282,25 @@ module ActiveRecord
|
|
1256
1282
|
columns
|
1257
1283
|
end
|
1258
1284
|
|
1285
|
+
def distinct_relation_for_primary_key(relation) # :nodoc:
|
1286
|
+
values = columns_for_distinct(
|
1287
|
+
visitor.compile(relation.table[relation.primary_key]),
|
1288
|
+
relation.order_values
|
1289
|
+
)
|
1290
|
+
|
1291
|
+
limited = relation.reselect(values).distinct!
|
1292
|
+
limited_ids = select_rows(limited.arel, "SQL").map(&:last)
|
1293
|
+
|
1294
|
+
if limited_ids.empty?
|
1295
|
+
relation.none!
|
1296
|
+
else
|
1297
|
+
relation.where!(relation.primary_key => limited_ids)
|
1298
|
+
end
|
1299
|
+
|
1300
|
+
relation.limit_value = relation.offset_value = nil
|
1301
|
+
relation
|
1302
|
+
end
|
1303
|
+
|
1259
1304
|
# Adds timestamps (+created_at+ and +updated_at+) columns to +table_name+.
|
1260
1305
|
# Additional options (like +:null+) are forwarded to #add_column.
|
1261
1306
|
#
|
@@ -1277,11 +1322,10 @@ module ActiveRecord
|
|
1277
1322
|
# remove_timestamps(:suppliers)
|
1278
1323
|
#
|
1279
1324
|
def remove_timestamps(table_name, **options)
|
1280
|
-
|
1281
|
-
remove_column table_name, :created_at
|
1325
|
+
remove_columns table_name, :updated_at, :created_at
|
1282
1326
|
end
|
1283
1327
|
|
1284
|
-
def update_table_definition(table_name, base)
|
1328
|
+
def update_table_definition(table_name, base) # :nodoc:
|
1285
1329
|
Table.new(table_name, base)
|
1286
1330
|
end
|
1287
1331
|
|
@@ -1488,7 +1532,7 @@ module ActiveRecord
|
|
1488
1532
|
def foreign_key_name(table_name, options)
|
1489
1533
|
options.fetch(:name) do
|
1490
1534
|
identifier = "#{table_name}_#{options.fetch(:column)}_fk"
|
1491
|
-
hashed_identifier = Digest::SHA256.hexdigest(identifier).first(10)
|
1535
|
+
hashed_identifier = OpenSSL::Digest::SHA256.hexdigest(identifier).first(10)
|
1492
1536
|
|
1493
1537
|
"fk_rails_#{hashed_identifier}"
|
1494
1538
|
end
|
@@ -1516,7 +1560,7 @@ module ActiveRecord
|
|
1516
1560
|
options.fetch(:name) do
|
1517
1561
|
expression = options.fetch(:expression)
|
1518
1562
|
identifier = "#{table_name}_#{expression}_chk"
|
1519
|
-
hashed_identifier = Digest::SHA256.hexdigest(identifier).first(10)
|
1563
|
+
hashed_identifier = OpenSSL::Digest::SHA256.hexdigest(identifier).first(10)
|
1520
1564
|
|
1521
1565
|
"chk_rails_#{hashed_identifier}"
|
1522
1566
|
end
|