activerecord 6.1.4 → 7.0.0.rc1
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 +1049 -977
- 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 +33 -17
- data/lib/active_record/associations/association_scope.rb +1 -3
- data/lib/active_record/associations/belongs_to_association.rb +15 -4
- 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 +10 -3
- 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 +34 -27
- 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 +187 -55
- data/lib/active_record/associations/preloader/batch.rb +48 -0
- data/lib/active_record/associations/preloader/branch.rb +147 -0
- data/lib/active_record/associations/preloader/through_association.rb +49 -13
- data/lib/active_record/associations/preloader.rb +39 -113
- data/lib/active_record/associations/singular_association.rb +8 -2
- data/lib/active_record/associations/through_association.rb +3 -3
- data/lib/active_record/associations.rb +90 -82
- data/lib/active_record/asynchronous_queries_tracker.rb +60 -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 +49 -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 +13 -14
- data/lib/active_record/attributes.rb +24 -35
- data/lib/active_record/autosave_association.rb +6 -21
- data/lib/active_record/base.rb +19 -1
- data/lib/active_record/callbacks.rb +2 -2
- data/lib/active_record/connection_adapters/abstract/connection_handler.rb +292 -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 +47 -561
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +0 -17
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +46 -22
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +24 -12
- data/lib/active_record/connection_adapters/abstract/quoting.rb +42 -72
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +4 -17
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +34 -9
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +69 -18
- data/lib/active_record/connection_adapters/abstract/transaction.rb +15 -22
- data/lib/active_record/connection_adapters/abstract_adapter.rb +149 -74
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +97 -81
- data/lib/active_record/connection_adapters/column.rb +4 -0
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +35 -23
- data/lib/active_record/connection_adapters/mysql/quoting.rb +35 -21
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +4 -1
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +12 -6
- data/lib/active_record/connection_adapters/pool_config.rb +7 -7
- data/lib/active_record/connection_adapters/postgresql/column.rb +17 -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 +50 -50
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +32 -0
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +21 -1
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +22 -1
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +25 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +27 -16
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +205 -105
- data/lib/active_record/connection_adapters/schema_cache.rb +29 -4
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +25 -19
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +15 -16
- 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 +6 -5
- data/lib/active_record/connection_handling.rb +47 -53
- data/lib/active_record/core.rb +122 -132
- data/lib/active_record/database_configurations/connection_url_resolver.rb +2 -1
- data/lib/active_record/database_configurations/database_config.rb +12 -9
- data/lib/active_record/database_configurations/hash_config.rb +63 -5
- data/lib/active_record/database_configurations/url_config.rb +2 -2
- data/lib/active_record/database_configurations.rb +16 -32
- data/lib/active_record/delegated_type.rb +52 -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 +28 -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 +90 -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 +49 -42
- data/lib/active_record/errors.rb +67 -4
- data/lib/active_record/explain_registry.rb +11 -6
- data/lib/active_record/fixture_set/file.rb +15 -1
- data/lib/active_record/fixture_set/table_row.rb +41 -6
- data/lib/active_record/fixture_set/table_rows.rb +4 -4
- data/lib/active_record/fixtures.rb +17 -20
- 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 +80 -14
- data/lib/active_record/integration.rb +4 -3
- data/lib/active_record/internal_metadata.rb +3 -5
- data/lib/active_record/legacy_yaml_adapter.rb +2 -39
- data/lib/active_record/locking/optimistic.rb +10 -9
- data/lib/active_record/locking/pessimistic.rb +9 -3
- data/lib/active_record/log_subscriber.rb +14 -3
- 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/middleware/shard_selector.rb +60 -0
- 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 +45 -58
- data/lib/active_record/nested_attributes.rb +13 -12
- data/lib/active_record/no_touching.rb +3 -3
- data/lib/active_record/null_relation.rb +2 -6
- data/lib/active_record/persistence.rb +219 -52
- data/lib/active_record/query_cache.rb +2 -2
- data/lib/active_record/query_logs.rb +138 -0
- data/lib/active_record/querying.rb +15 -5
- data/lib/active_record/railtie.rb +127 -17
- data/lib/active_record/railties/controller_runtime.rb +1 -1
- data/lib/active_record/railties/databases.rake +66 -129
- data/lib/active_record/readonly_attributes.rb +11 -0
- data/lib/active_record/reflection.rb +67 -50
- 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 +40 -36
- data/lib/active_record/relation/delegation.rb +6 -6
- data/lib/active_record/relation/finder_methods.rb +31 -35
- 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 +235 -61
- data/lib/active_record/relation/record_fetch_warning.rb +7 -9
- data/lib/active_record/relation/spawn_methods.rb +2 -2
- data/lib/active_record/relation/where_clause.rb +10 -19
- data/lib/active_record/relation.rb +171 -84
- data/lib/active_record/result.rb +17 -7
- data/lib/active_record/runtime_registry.rb +9 -13
- data/lib/active_record/sanitization.rb +11 -7
- data/lib/active_record/schema_dumper.rb +10 -3
- data/lib/active_record/schema_migration.rb +0 -4
- data/lib/active_record/scoping/default.rb +61 -12
- data/lib/active_record/scoping/named.rb +3 -11
- data/lib/active_record/scoping.rb +64 -34
- data/lib/active_record/serialization.rb +1 -1
- data/lib/active_record/signed_id.rb +1 -1
- data/lib/active_record/suppressor.rb +11 -15
- data/lib/active_record/tasks/database_tasks.rb +116 -58
- data/lib/active_record/tasks/mysql_database_tasks.rb +1 -1
- data/lib/active_record/tasks/postgresql_database_tasks.rb +19 -12
- data/lib/active_record/test_databases.rb +1 -1
- data/lib/active_record/test_fixtures.rb +4 -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/uniqueness.rb +1 -1
- data/lib/active_record.rb +204 -28
- data/lib/arel/attributes/attribute.rb +0 -8
- data/lib/arel/crud.rb +28 -22
- data/lib/arel/delete_manager.rb +18 -4
- data/lib/arel/filter_predications.rb +9 -0
- data/lib/arel/insert_manager.rb +2 -3
- data/lib/arel/nodes/casted.rb +1 -1
- data/lib/arel/nodes/delete_statement.rb +12 -13
- data/lib/arel/nodes/filter.rb +10 -0
- data/lib/arel/nodes/function.rb +1 -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 +8 -3
- data/lib/arel/nodes.rb +1 -0
- data/lib/arel/predications.rb +11 -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 +18 -4
- data/lib/arel/visitors/dot.rb +80 -90
- data/lib/arel/visitors/mysql.rb +8 -2
- data/lib/arel/visitors/postgresql.rb +0 -10
- data/lib/arel/visitors/to_sql.rb +58 -2
- data/lib/arel.rb +2 -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 +56 -13
@@ -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|
|
@@ -460,7 +469,7 @@ module ActiveRecord
|
|
460
469
|
end
|
461
470
|
|
462
471
|
def build_fixture_sql(fixtures, table_name)
|
463
|
-
columns = schema_cache.columns_hash(table_name)
|
472
|
+
columns = schema_cache.columns_hash(table_name).reject { |_, column| supports_virtual_columns? && column.virtual? }
|
464
473
|
|
465
474
|
values_list = fixtures.map do |fixture|
|
466
475
|
fixture = fixture.stringify_keys
|
@@ -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
|
@@ -9,38 +9,46 @@ module ActiveRecord
|
|
9
9
|
# Quotes the column value to help prevent
|
10
10
|
# {SQL injection attacks}[https://en.wikipedia.org/wiki/SQL_injection].
|
11
11
|
def quote(value)
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
12
|
+
case value
|
13
|
+
when String, Symbol, ActiveSupport::Multibyte::Chars
|
14
|
+
"'#{quote_string(value.to_s)}'"
|
15
|
+
when true then quoted_true
|
16
|
+
when false then quoted_false
|
17
|
+
when nil then "NULL"
|
18
|
+
# BigDecimals need to be put in a non-normalized form and quoted.
|
19
|
+
when BigDecimal then value.to_s("F")
|
20
|
+
when Numeric, ActiveSupport::Duration then value.to_s
|
21
|
+
when Type::Binary::Data then quoted_binary(value)
|
22
|
+
when Type::Time::Value then "'#{quoted_time(value)}'"
|
23
|
+
when Date, Time then "'#{quoted_date(value)}'"
|
24
|
+
when Class then "'#{value}'"
|
25
|
+
else raise TypeError, "can't quote #{value.class.name}"
|
18
26
|
end
|
19
|
-
|
20
|
-
_quote(value)
|
21
27
|
end
|
22
28
|
|
23
29
|
# Cast a +value+ to a type that the database understands. For example,
|
24
30
|
# SQLite does not understand dates, so this method will convert a Date
|
25
31
|
# to a String.
|
26
|
-
def type_cast(value
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
MSG
|
39
|
-
type = lookup_cast_type_from_column(column)
|
40
|
-
value = type.serialize(value)
|
32
|
+
def type_cast(value)
|
33
|
+
case value
|
34
|
+
when Symbol, ActiveSupport::Multibyte::Chars, Type::Binary::Data
|
35
|
+
value.to_s
|
36
|
+
when true then unquoted_true
|
37
|
+
when false then unquoted_false
|
38
|
+
# BigDecimals need to be put in a non-normalized form and quoted.
|
39
|
+
when BigDecimal then value.to_s("F")
|
40
|
+
when nil, Numeric, String then value
|
41
|
+
when Type::Time::Value then quoted_time(value)
|
42
|
+
when Date, Time then quoted_date(value)
|
43
|
+
else raise TypeError, "can't cast #{value.class.name}"
|
41
44
|
end
|
45
|
+
end
|
42
46
|
|
43
|
-
|
47
|
+
# Quote a value to be used as a bound parameter of unknown type. For example,
|
48
|
+
# MySQL might perform dangerous castings when comparing a string to a number,
|
49
|
+
# so this method will cast numbers to string.
|
50
|
+
def quote_bound_value(value)
|
51
|
+
quote(value)
|
44
52
|
end
|
45
53
|
|
46
54
|
# If you are having to call this function, you are likely doing something
|
@@ -59,7 +67,7 @@ module ActiveRecord
|
|
59
67
|
# Quotes a string, escaping any ' (single quote) and \ (backslash)
|
60
68
|
# characters.
|
61
69
|
def quote_string(s)
|
62
|
-
s.gsub(
|
70
|
+
s.gsub("\\", '\&\&').gsub("'", "''") # ' (for ruby-mode)
|
63
71
|
end
|
64
72
|
|
65
73
|
# Quotes the column name. Defaults to no quoting.
|
@@ -113,14 +121,14 @@ module ActiveRecord
|
|
113
121
|
# if the value is a Time responding to usec.
|
114
122
|
def quoted_date(value)
|
115
123
|
if value.acts_like?(:time)
|
116
|
-
if ActiveRecord
|
117
|
-
value = value.getutc if
|
124
|
+
if ActiveRecord.default_timezone == :utc
|
125
|
+
value = value.getutc if !value.utc?
|
118
126
|
else
|
119
|
-
value = value.getlocal
|
127
|
+
value = value.getlocal
|
120
128
|
end
|
121
129
|
end
|
122
130
|
|
123
|
-
result = value.
|
131
|
+
result = value.to_formatted_s(:db)
|
124
132
|
if value.respond_to?(:usec) && value.usec > 0
|
125
133
|
result << "." << sprintf("%06d", value.usec)
|
126
134
|
else
|
@@ -196,16 +204,11 @@ module ActiveRecord
|
|
196
204
|
|
197
205
|
private
|
198
206
|
def type_casted_binds(binds)
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
if ActiveModel::Attribute === value
|
205
|
-
type_cast(value.value_for_database)
|
206
|
-
else
|
207
|
-
type_cast(value)
|
208
|
-
end
|
207
|
+
binds.map do |value|
|
208
|
+
if ActiveModel::Attribute === value
|
209
|
+
type_cast(value.value_for_database)
|
210
|
+
else
|
211
|
+
type_cast(value)
|
209
212
|
end
|
210
213
|
end
|
211
214
|
end
|
@@ -213,39 +216,6 @@ module ActiveRecord
|
|
213
216
|
def lookup_cast_type(sql_type)
|
214
217
|
type_map.lookup(sql_type)
|
215
218
|
end
|
216
|
-
|
217
|
-
def _quote(value)
|
218
|
-
case value
|
219
|
-
when String, Symbol, ActiveSupport::Multibyte::Chars
|
220
|
-
"'#{quote_string(value.to_s)}'"
|
221
|
-
when true then quoted_true
|
222
|
-
when false then quoted_false
|
223
|
-
when nil then "NULL"
|
224
|
-
# BigDecimals need to be put in a non-normalized form and quoted.
|
225
|
-
when BigDecimal then value.to_s("F")
|
226
|
-
when Numeric, ActiveSupport::Duration then value.to_s
|
227
|
-
when Type::Binary::Data then quoted_binary(value)
|
228
|
-
when Type::Time::Value then "'#{quoted_time(value)}'"
|
229
|
-
when Date, Time then "'#{quoted_date(value)}'"
|
230
|
-
when Class then "'#{value}'"
|
231
|
-
else raise TypeError, "can't quote #{value.class.name}"
|
232
|
-
end
|
233
|
-
end
|
234
|
-
|
235
|
-
def _type_cast(value)
|
236
|
-
case value
|
237
|
-
when Symbol, ActiveSupport::Multibyte::Chars, Type::Binary::Data
|
238
|
-
value.to_s
|
239
|
-
when true then unquoted_true
|
240
|
-
when false then unquoted_false
|
241
|
-
# BigDecimals need to be put in a non-normalized form and quoted.
|
242
|
-
when BigDecimal then value.to_s("F")
|
243
|
-
when nil, Numeric, String then value
|
244
|
-
when Type::Time::Value then quoted_time(value)
|
245
|
-
when Date, Time then quoted_date(value)
|
246
|
-
else raise TypeError, "can't cast #{value.class.name}"
|
247
|
-
end
|
248
|
-
end
|
249
219
|
end
|
250
220
|
end
|
251
221
|
end
|
@@ -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?
|
@@ -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
|
@@ -106,6 +106,10 @@ module ActiveRecord
|
|
106
106
|
options[:on_update]
|
107
107
|
end
|
108
108
|
|
109
|
+
def deferrable
|
110
|
+
options[:deferrable]
|
111
|
+
end
|
112
|
+
|
109
113
|
def custom_primary_key?
|
110
114
|
options[:primary_key] != default_primary_key
|
111
115
|
end
|
@@ -253,6 +257,7 @@ module ActiveRecord
|
|
253
257
|
define_column_methods :bigint, :binary, :boolean, :date, :datetime, :decimal,
|
254
258
|
:float, :integer, :json, :string, :text, :time, :timestamp, :virtual
|
255
259
|
|
260
|
+
alias :blob :binary
|
256
261
|
alias :numeric :decimal
|
257
262
|
end
|
258
263
|
|
@@ -277,7 +282,7 @@ module ActiveRecord
|
|
277
282
|
# Inside migration files, the +t+ object in {create_table}[rdoc-ref:SchemaStatements#create_table]
|
278
283
|
# is actually of this type:
|
279
284
|
#
|
280
|
-
# class SomeMigration < ActiveRecord::Migration[
|
285
|
+
# class SomeMigration < ActiveRecord::Migration[7.0]
|
281
286
|
# def up
|
282
287
|
# create_table :foo do |t|
|
283
288
|
# puts t.class # => "ActiveRecord::ConnectionAdapters::TableDefinition"
|
@@ -410,6 +415,12 @@ module ActiveRecord
|
|
410
415
|
end
|
411
416
|
end
|
412
417
|
|
418
|
+
if @conn.supports_datetime_with_precision?
|
419
|
+
if type == :datetime && !options.key?(:precision)
|
420
|
+
options[:precision] = 6
|
421
|
+
end
|
422
|
+
end
|
423
|
+
|
413
424
|
@columns_hash[name] = new_column_definition(name, type, **options)
|
414
425
|
|
415
426
|
if index
|
@@ -434,12 +445,12 @@ module ActiveRecord
|
|
434
445
|
indexes << [column_name, options]
|
435
446
|
end
|
436
447
|
|
437
|
-
def foreign_key(
|
438
|
-
foreign_keys <<
|
448
|
+
def foreign_key(to_table, **options)
|
449
|
+
foreign_keys << new_foreign_key_definition(to_table, options)
|
439
450
|
end
|
440
451
|
|
441
452
|
def check_constraint(expression, **options)
|
442
|
-
check_constraints <<
|
453
|
+
check_constraints << new_check_constraint_definition(expression, options)
|
443
454
|
end
|
444
455
|
|
445
456
|
# Appends <tt>:datetime</tt> columns <tt>:created_at</tt> and
|
@@ -481,6 +492,19 @@ module ActiveRecord
|
|
481
492
|
create_column_definition(name, type, options)
|
482
493
|
end
|
483
494
|
|
495
|
+
def new_foreign_key_definition(to_table, options) # :nodoc:
|
496
|
+
prefix = ActiveRecord::Base.table_name_prefix
|
497
|
+
suffix = ActiveRecord::Base.table_name_suffix
|
498
|
+
to_table = "#{prefix}#{to_table}#{suffix}"
|
499
|
+
options = @conn.foreign_key_options(name, to_table, options)
|
500
|
+
ForeignKeyDefinition.new(name, to_table, options)
|
501
|
+
end
|
502
|
+
|
503
|
+
def new_check_constraint_definition(expression, options) # :nodoc:
|
504
|
+
options = @conn.check_constraint_options(name, expression, options)
|
505
|
+
CheckConstraintDefinition.new(name, expression, options)
|
506
|
+
end
|
507
|
+
|
484
508
|
private
|
485
509
|
def create_column_definition(name, type, options)
|
486
510
|
ColumnDefinition.new(name, type, options)
|
@@ -516,7 +540,7 @@ module ActiveRecord
|
|
516
540
|
def name; @td.name; end
|
517
541
|
|
518
542
|
def add_foreign_key(to_table, options)
|
519
|
-
@foreign_key_adds <<
|
543
|
+
@foreign_key_adds << @td.new_foreign_key_definition(to_table, options)
|
520
544
|
end
|
521
545
|
|
522
546
|
def drop_foreign_key(name)
|
@@ -524,7 +548,7 @@ module ActiveRecord
|
|
524
548
|
end
|
525
549
|
|
526
550
|
def add_check_constraint(expression, options)
|
527
|
-
@check_constraint_adds <<
|
551
|
+
@check_constraint_adds << @td.new_check_constraint_definition(expression, options)
|
528
552
|
end
|
529
553
|
|
530
554
|
def drop_check_constraint(constraint_name)
|
@@ -568,6 +592,7 @@ module ActiveRecord
|
|
568
592
|
# t.time
|
569
593
|
# t.date
|
570
594
|
# t.binary
|
595
|
+
# t.blob
|
571
596
|
# t.boolean
|
572
597
|
# t.foreign_key
|
573
598
|
# t.json
|