activerecord 7.2.3 → 8.0.0.beta1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of activerecord might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +192 -1261
- data/README.rdoc +2 -2
- data/lib/active_record/associations/alias_tracker.rb +4 -6
- data/lib/active_record/associations/association.rb +25 -5
- data/lib/active_record/associations/belongs_to_association.rb +2 -18
- data/lib/active_record/associations/builder/association.rb +7 -6
- data/lib/active_record/associations/collection_association.rb +4 -4
- data/lib/active_record/associations/disable_joins_association_scope.rb +1 -1
- data/lib/active_record/associations/has_many_through_association.rb +4 -9
- data/lib/active_record/associations/join_dependency/join_association.rb +27 -25
- data/lib/active_record/associations/preloader/association.rb +2 -2
- data/lib/active_record/associations/singular_association.rb +8 -3
- data/lib/active_record/associations.rb +50 -32
- data/lib/active_record/asynchronous_queries_tracker.rb +28 -24
- data/lib/active_record/attribute_methods/serialization.rb +1 -1
- data/lib/active_record/attribute_methods.rb +19 -24
- data/lib/active_record/attributes.rb +26 -37
- data/lib/active_record/autosave_association.rb +81 -49
- data/lib/active_record/base.rb +2 -2
- data/lib/active_record/callbacks.rb +1 -1
- data/lib/active_record/connection_adapters/abstract/connection_handler.rb +16 -10
- data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +0 -1
- data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +0 -1
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +31 -75
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +90 -43
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +14 -19
- data/lib/active_record/connection_adapters/abstract/quoting.rb +1 -1
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +2 -6
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +27 -9
- data/lib/active_record/connection_adapters/abstract/transaction.rb +15 -5
- data/lib/active_record/connection_adapters/abstract_adapter.rb +27 -57
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +28 -58
- data/lib/active_record/connection_adapters/mysql/quoting.rb +1 -15
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +2 -8
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +43 -45
- data/lib/active_record/connection_adapters/mysql2/database_statements.rb +42 -98
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +2 -16
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +64 -42
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +10 -0
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +12 -14
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +51 -9
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +44 -101
- data/lib/active_record/connection_adapters/schema_cache.rb +1 -3
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +76 -100
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +0 -13
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +0 -6
- data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +13 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +8 -2
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +60 -22
- data/lib/active_record/connection_adapters/trilogy/database_statements.rb +37 -67
- data/lib/active_record/connection_adapters/trilogy_adapter.rb +1 -18
- data/lib/active_record/connection_handling.rb +29 -11
- data/lib/active_record/core.rb +15 -60
- data/lib/active_record/counter_cache.rb +1 -1
- data/lib/active_record/database_configurations/connection_url_resolver.rb +1 -3
- data/lib/active_record/delegated_type.rb +18 -18
- data/lib/active_record/encryption/config.rb +3 -1
- data/lib/active_record/encryption/encryptable_record.rb +5 -5
- data/lib/active_record/encryption/encrypted_attribute_type.rb +11 -2
- data/lib/active_record/encryption/encryptor.rb +35 -29
- data/lib/active_record/encryption/extended_deterministic_queries.rb +4 -2
- data/lib/active_record/encryption/scheme.rb +8 -1
- data/lib/active_record/enum.rb +12 -13
- data/lib/active_record/errors.rb +16 -8
- data/lib/active_record/fixture_set/table_row.rb +2 -19
- data/lib/active_record/fixtures.rb +0 -1
- data/lib/active_record/future_result.rb +14 -10
- data/lib/active_record/gem_version.rb +4 -4
- data/lib/active_record/insert_all.rb +1 -1
- data/lib/active_record/marshalling.rb +1 -4
- data/lib/active_record/migration/command_recorder.rb +22 -5
- data/lib/active_record/migration/compatibility.rb +5 -2
- data/lib/active_record/migration.rb +36 -35
- data/lib/active_record/model_schema.rb +1 -1
- data/lib/active_record/nested_attributes.rb +4 -6
- data/lib/active_record/persistence.rb +128 -130
- data/lib/active_record/query_cache.rb +5 -4
- data/lib/active_record/query_logs.rb +98 -44
- data/lib/active_record/query_logs_formatter.rb +17 -28
- data/lib/active_record/querying.rb +10 -10
- data/lib/active_record/railtie.rb +5 -6
- data/lib/active_record/railties/databases.rake +1 -2
- data/lib/active_record/reflection.rb +9 -7
- data/lib/active_record/relation/batches/batch_enumerator.rb +4 -3
- data/lib/active_record/relation/batches.rb +132 -72
- data/lib/active_record/relation/calculations.rb +55 -55
- data/lib/active_record/relation/delegation.rb +25 -14
- data/lib/active_record/relation/finder_methods.rb +31 -32
- data/lib/active_record/relation/merger.rb +8 -8
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +0 -2
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +1 -1
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +4 -3
- data/lib/active_record/relation/predicate_builder.rb +5 -0
- data/lib/active_record/relation/query_attribute.rb +1 -1
- data/lib/active_record/relation/query_methods.rb +90 -91
- data/lib/active_record/relation/record_fetch_warning.rb +2 -2
- data/lib/active_record/relation/spawn_methods.rb +1 -1
- data/lib/active_record/relation/where_clause.rb +2 -8
- data/lib/active_record/relation.rb +77 -76
- data/lib/active_record/result.rb +68 -7
- data/lib/active_record/sanitization.rb +7 -6
- data/lib/active_record/schema_dumper.rb +16 -29
- data/lib/active_record/schema_migration.rb +2 -1
- data/lib/active_record/scoping/named.rb +5 -2
- data/lib/active_record/secure_token.rb +3 -3
- data/lib/active_record/signed_id.rb +6 -7
- data/lib/active_record/statement_cache.rb +12 -12
- data/lib/active_record/store.rb +7 -3
- data/lib/active_record/tasks/database_tasks.rb +24 -15
- data/lib/active_record/tasks/mysql_database_tasks.rb +0 -2
- data/lib/active_record/tasks/postgresql_database_tasks.rb +0 -7
- data/lib/active_record/tasks/sqlite_database_tasks.rb +2 -2
- data/lib/active_record/test_fixtures.rb +12 -0
- data/lib/active_record/testing/query_assertions.rb +2 -2
- data/lib/active_record/token_for.rb +1 -1
- data/lib/active_record/transactions.rb +1 -3
- data/lib/active_record/validations/uniqueness.rb +8 -8
- data/lib/active_record.rb +16 -1
- data/lib/arel/collectors/bind.rb +1 -1
- data/lib/arel/crud.rb +0 -2
- data/lib/arel/delete_manager.rb +0 -5
- data/lib/arel/nodes/delete_statement.rb +2 -4
- data/lib/arel/nodes/update_statement.rb +2 -4
- data/lib/arel/select_manager.rb +2 -6
- data/lib/arel/update_manager.rb +0 -5
- data/lib/arel/visitors/dot.rb +0 -2
- data/lib/arel/visitors/sqlite.rb +0 -25
- data/lib/arel/visitors/to_sql.rb +1 -3
- metadata +14 -11
|
@@ -102,16 +102,16 @@ module ActiveRecord
|
|
|
102
102
|
select_all(arel, name, binds, async: async).then(&:rows)
|
|
103
103
|
end
|
|
104
104
|
|
|
105
|
-
def query_value(
|
|
106
|
-
single_value_from_rows(query(
|
|
105
|
+
def query_value(...) # :nodoc:
|
|
106
|
+
single_value_from_rows(query(...))
|
|
107
107
|
end
|
|
108
108
|
|
|
109
|
-
def query_values(
|
|
110
|
-
query(
|
|
109
|
+
def query_values(...) # :nodoc:
|
|
110
|
+
query(...).map(&:first)
|
|
111
111
|
end
|
|
112
112
|
|
|
113
|
-
def query(
|
|
114
|
-
internal_exec_query(
|
|
113
|
+
def query(...) # :nodoc:
|
|
114
|
+
internal_exec_query(...).rows
|
|
115
115
|
end
|
|
116
116
|
|
|
117
117
|
# Determines whether the SQL statement is a write query.
|
|
@@ -163,14 +163,14 @@ module ActiveRecord
|
|
|
163
163
|
# +binds+ as the bind substitutes. +name+ is logged along with
|
|
164
164
|
# the executed +sql+ statement.
|
|
165
165
|
def exec_delete(sql, name = nil, binds = [])
|
|
166
|
-
|
|
166
|
+
affected_rows(internal_execute(sql, name, binds))
|
|
167
167
|
end
|
|
168
168
|
|
|
169
169
|
# Executes update +sql+ statement in the context of this connection using
|
|
170
170
|
# +binds+ as the bind substitutes. +name+ is logged along with
|
|
171
171
|
# the executed +sql+ statement.
|
|
172
172
|
def exec_update(sql, name = nil, binds = [])
|
|
173
|
-
|
|
173
|
+
affected_rows(internal_execute(sql, name, binds))
|
|
174
174
|
end
|
|
175
175
|
|
|
176
176
|
def exec_insert_all(sql, name) # :nodoc:
|
|
@@ -224,11 +224,9 @@ module ActiveRecord
|
|
|
224
224
|
|
|
225
225
|
return if table_names.empty?
|
|
226
226
|
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
execute_batch(statements, "Truncate Tables")
|
|
231
|
-
end
|
|
227
|
+
disable_referential_integrity do
|
|
228
|
+
statements = build_truncate_statements(table_names)
|
|
229
|
+
execute_batch(statements, "Truncate Tables")
|
|
232
230
|
end
|
|
233
231
|
end
|
|
234
232
|
|
|
@@ -358,7 +356,7 @@ module ActiveRecord
|
|
|
358
356
|
end
|
|
359
357
|
yield current_transaction.user_transaction
|
|
360
358
|
else
|
|
361
|
-
|
|
359
|
+
within_new_transaction(isolation: isolation, joinable: joinable, &block)
|
|
362
360
|
end
|
|
363
361
|
rescue ActiveRecord::Rollback
|
|
364
362
|
# rollbacks are silently swallowed
|
|
@@ -411,6 +409,14 @@ module ActiveRecord
|
|
|
411
409
|
# Begins the transaction (and turns off auto-committing).
|
|
412
410
|
def begin_db_transaction() end
|
|
413
411
|
|
|
412
|
+
def begin_deferred_transaction(isolation_level = nil) # :nodoc:
|
|
413
|
+
if isolation_level
|
|
414
|
+
begin_isolated_db_transaction(isolation_level)
|
|
415
|
+
else
|
|
416
|
+
begin_db_transaction
|
|
417
|
+
end
|
|
418
|
+
end
|
|
419
|
+
|
|
414
420
|
def transaction_isolation_levels
|
|
415
421
|
{
|
|
416
422
|
read_uncommitted: "READ UNCOMMITTED",
|
|
@@ -427,6 +433,15 @@ module ActiveRecord
|
|
|
427
433
|
raise ActiveRecord::TransactionIsolationError, "adapter does not support setting transaction isolation"
|
|
428
434
|
end
|
|
429
435
|
|
|
436
|
+
# Hook point called after an isolated DB transaction is committed
|
|
437
|
+
# or rolled back.
|
|
438
|
+
# Most adapters don't need to implement anything because the isolation
|
|
439
|
+
# level is set on a per transaction basis.
|
|
440
|
+
# But some databases like SQLite set it on a per connection level
|
|
441
|
+
# and need to explicitly reset it after commit or rollback.
|
|
442
|
+
def reset_isolation_level
|
|
443
|
+
end
|
|
444
|
+
|
|
430
445
|
# Commits the transaction (and turns on auto-committing).
|
|
431
446
|
def commit_db_transaction() end
|
|
432
447
|
|
|
@@ -473,11 +488,9 @@ module ActiveRecord
|
|
|
473
488
|
table_deletes = tables_to_delete.map { |table| "DELETE FROM #{quote_table_name(table)}" }
|
|
474
489
|
statements = table_deletes + fixture_inserts
|
|
475
490
|
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
execute_batch(statements, "Fixtures Load")
|
|
480
|
-
end
|
|
491
|
+
transaction(requires_new: true) do
|
|
492
|
+
disable_referential_integrity do
|
|
493
|
+
execute_batch(statements, "Fixtures Load")
|
|
481
494
|
end
|
|
482
495
|
end
|
|
483
496
|
end
|
|
@@ -524,28 +537,64 @@ module ActiveRecord
|
|
|
524
537
|
HIGH_PRECISION_CURRENT_TIMESTAMP
|
|
525
538
|
end
|
|
526
539
|
|
|
527
|
-
|
|
528
|
-
|
|
540
|
+
# Same as raw_execute but returns an ActiveRecord::Result object.
|
|
541
|
+
def raw_exec_query(...) # :nodoc:
|
|
542
|
+
cast_result(raw_execute(...))
|
|
543
|
+
end
|
|
544
|
+
|
|
545
|
+
# Execute a query and returns an ActiveRecord::Result
|
|
546
|
+
def internal_exec_query(...) # :nodoc:
|
|
547
|
+
cast_result(internal_execute(...))
|
|
529
548
|
end
|
|
530
549
|
|
|
531
550
|
private
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
551
|
+
# Lowest level way to execute a query. Doesn't check for illegal writes, doesn't annotate queries, yields a native result object.
|
|
552
|
+
def raw_execute(sql, name = nil, binds = [], prepare: false, async: false, allow_retry: false, materialize_transactions: true, batch: false)
|
|
553
|
+
type_casted_binds = type_casted_binds(binds)
|
|
554
|
+
log(sql, name, binds, type_casted_binds, async: async) do |notification_payload|
|
|
555
|
+
with_raw_connection(allow_retry: allow_retry, materialize_transactions: materialize_transactions) do |conn|
|
|
556
|
+
perform_query(conn, sql, binds, type_casted_binds, prepare: prepare, notification_payload: notification_payload, batch: batch)
|
|
557
|
+
end
|
|
558
|
+
end
|
|
559
|
+
end
|
|
535
560
|
|
|
536
|
-
|
|
561
|
+
def perform_query(raw_connection, sql, binds, type_casted_binds, prepare:, notification_payload:, batch:)
|
|
562
|
+
raise NotImplementedError
|
|
563
|
+
end
|
|
537
564
|
|
|
538
|
-
|
|
565
|
+
# Receive a native adapter result object and returns an ActiveRecord::Result object.
|
|
566
|
+
def cast_result(raw_result)
|
|
567
|
+
raise NotImplementedError
|
|
539
568
|
end
|
|
540
569
|
|
|
541
|
-
def
|
|
542
|
-
|
|
543
|
-
|
|
570
|
+
def affected_rows(raw_result)
|
|
571
|
+
raise NotImplementedError
|
|
572
|
+
end
|
|
573
|
+
|
|
574
|
+
def preprocess_query(sql)
|
|
575
|
+
check_if_write_query(sql)
|
|
576
|
+
mark_transaction_written_if_write(sql)
|
|
577
|
+
|
|
578
|
+
# We call tranformers after the write checks so we don't add extra parsing work.
|
|
579
|
+
# This means we assume no transformer whille change a read for a write
|
|
580
|
+
# but it would be insane to do such a thing.
|
|
581
|
+
ActiveRecord.query_transformers.each do |transformer|
|
|
582
|
+
sql = transformer.call(sql, self)
|
|
544
583
|
end
|
|
584
|
+
|
|
585
|
+
sql
|
|
545
586
|
end
|
|
546
587
|
|
|
547
|
-
|
|
548
|
-
|
|
588
|
+
# Same as #internal_exec_query, but yields a native adapter result
|
|
589
|
+
def internal_execute(sql, name = "SQL", binds = [], prepare: false, async: false, allow_retry: false, materialize_transactions: true, &block)
|
|
590
|
+
sql = preprocess_query(sql)
|
|
591
|
+
raw_execute(sql, name, binds, prepare: prepare, async: async, allow_retry: allow_retry, materialize_transactions: materialize_transactions, &block)
|
|
592
|
+
end
|
|
593
|
+
|
|
594
|
+
def execute_batch(statements, name = nil, **kwargs)
|
|
595
|
+
statements.each do |statement|
|
|
596
|
+
raw_execute(statement, name, **kwargs)
|
|
597
|
+
end
|
|
549
598
|
end
|
|
550
599
|
|
|
551
600
|
DEFAULT_INSERT_VALUE = Arel.sql("DEFAULT").freeze
|
|
@@ -614,10 +663,6 @@ module ActiveRecord
|
|
|
614
663
|
end
|
|
615
664
|
end
|
|
616
665
|
|
|
617
|
-
def with_multi_statements
|
|
618
|
-
yield
|
|
619
|
-
end
|
|
620
|
-
|
|
621
666
|
def combine_multi_statements(total_sql)
|
|
622
667
|
total_sql.join(";\n")
|
|
623
668
|
end
|
|
@@ -629,6 +674,8 @@ module ActiveRecord
|
|
|
629
674
|
raise AsynchronousQueryInsideTransactionError, "Asynchronous queries are not allowed inside transactions"
|
|
630
675
|
end
|
|
631
676
|
|
|
677
|
+
# We make sure to run query transformers on the orignal thread
|
|
678
|
+
sql = preprocess_query(sql)
|
|
632
679
|
future_result = async.new(
|
|
633
680
|
pool,
|
|
634
681
|
sql,
|
|
@@ -636,19 +683,19 @@ module ActiveRecord
|
|
|
636
683
|
binds,
|
|
637
684
|
prepare: prepare,
|
|
638
685
|
)
|
|
639
|
-
if supports_concurrent_connections? && current_transaction.
|
|
686
|
+
if supports_concurrent_connections? && !current_transaction.joinable?
|
|
640
687
|
future_result.schedule!(ActiveRecord::Base.asynchronous_queries_session)
|
|
641
688
|
else
|
|
642
689
|
future_result.execute!(self)
|
|
643
690
|
end
|
|
644
|
-
|
|
645
|
-
end
|
|
646
|
-
|
|
647
|
-
result = internal_exec_query(sql, name, binds, prepare: prepare, allow_retry: allow_retry)
|
|
648
|
-
if async
|
|
649
|
-
FutureResult.wrap(result)
|
|
691
|
+
future_result
|
|
650
692
|
else
|
|
651
|
-
result
|
|
693
|
+
result = internal_exec_query(sql, name, binds, prepare: prepare, allow_retry: allow_retry)
|
|
694
|
+
if async
|
|
695
|
+
FutureResult.wrap(result)
|
|
696
|
+
else
|
|
697
|
+
result
|
|
698
|
+
end
|
|
652
699
|
end
|
|
653
700
|
end
|
|
654
701
|
|
|
@@ -191,26 +191,15 @@ module ActiveRecord
|
|
|
191
191
|
end
|
|
192
192
|
end
|
|
193
193
|
|
|
194
|
+
attr_accessor :query_cache
|
|
195
|
+
|
|
194
196
|
def initialize(*)
|
|
195
197
|
super
|
|
196
198
|
@query_cache = nil
|
|
197
199
|
end
|
|
198
200
|
|
|
199
|
-
attr_writer :query_cache
|
|
200
|
-
|
|
201
|
-
def query_cache
|
|
202
|
-
if @pinned && @owner != ActiveSupport::IsolatedExecutionState.context
|
|
203
|
-
# With transactional tests, if the connection is pinned, any thread
|
|
204
|
-
# other than the one that pinned the connection need to go through the
|
|
205
|
-
# query cache pool, so each thread get a different cache.
|
|
206
|
-
pool.query_cache
|
|
207
|
-
else
|
|
208
|
-
@query_cache
|
|
209
|
-
end
|
|
210
|
-
end
|
|
211
|
-
|
|
212
201
|
def query_cache_enabled
|
|
213
|
-
query_cache&.enabled?
|
|
202
|
+
@query_cache&.enabled?
|
|
214
203
|
end
|
|
215
204
|
|
|
216
205
|
# Enable the query cache within the block.
|
|
@@ -249,7 +238,7 @@ module ActiveRecord
|
|
|
249
238
|
|
|
250
239
|
# If arel is locked this is a SELECT ... FOR UPDATE or somesuch.
|
|
251
240
|
# Such queries should not be cached.
|
|
252
|
-
if
|
|
241
|
+
if @query_cache&.enabled? && !(arel.respond_to?(:locked) && arel.locked)
|
|
253
242
|
sql, binds, preparable, allow_retry = to_sql_and_binds(arel, binds, preparable)
|
|
254
243
|
|
|
255
244
|
if async
|
|
@@ -273,13 +262,13 @@ module ActiveRecord
|
|
|
273
262
|
|
|
274
263
|
result = nil
|
|
275
264
|
@lock.synchronize do
|
|
276
|
-
result = query_cache[key]
|
|
265
|
+
result = @query_cache[key]
|
|
277
266
|
end
|
|
278
267
|
|
|
279
268
|
if result
|
|
280
269
|
ActiveSupport::Notifications.instrument(
|
|
281
270
|
"sql.active_record",
|
|
282
|
-
|
|
271
|
+
cache_notification_info_result(sql, name, binds, result)
|
|
283
272
|
)
|
|
284
273
|
end
|
|
285
274
|
|
|
@@ -292,7 +281,7 @@ module ActiveRecord
|
|
|
292
281
|
hit = true
|
|
293
282
|
|
|
294
283
|
@lock.synchronize do
|
|
295
|
-
result = query_cache.compute_if_absent(key) do
|
|
284
|
+
result = @query_cache.compute_if_absent(key) do
|
|
296
285
|
hit = false
|
|
297
286
|
yield
|
|
298
287
|
end
|
|
@@ -301,13 +290,19 @@ module ActiveRecord
|
|
|
301
290
|
if hit
|
|
302
291
|
ActiveSupport::Notifications.instrument(
|
|
303
292
|
"sql.active_record",
|
|
304
|
-
|
|
293
|
+
cache_notification_info_result(sql, name, binds, result)
|
|
305
294
|
)
|
|
306
295
|
end
|
|
307
296
|
|
|
308
297
|
result.dup
|
|
309
298
|
end
|
|
310
299
|
|
|
300
|
+
def cache_notification_info_result(sql, name, binds, result)
|
|
301
|
+
payload = cache_notification_info(sql, name, binds)
|
|
302
|
+
payload[:row_count] = result.length
|
|
303
|
+
payload
|
|
304
|
+
end
|
|
305
|
+
|
|
311
306
|
# Database adapters can override this method to
|
|
312
307
|
# provide custom cache information.
|
|
313
308
|
def cache_notification_info(sql, name, binds)
|
|
@@ -160,8 +160,6 @@ module ActiveRecord
|
|
|
160
160
|
end
|
|
161
161
|
|
|
162
162
|
def defined_for?(to_table: nil, validate: nil, **options)
|
|
163
|
-
options = options.slice(*self.options.keys)
|
|
164
|
-
|
|
165
163
|
(to_table.nil? || to_table.to_s == self.to_table) &&
|
|
166
164
|
(validate.nil? || validate == self.options.fetch(:validate, validate)) &&
|
|
167
165
|
options.all? { |k, v| Array(self.options[k]).map(&:to_s) == Array(v).map(&:to_s) }
|
|
@@ -188,8 +186,6 @@ module ActiveRecord
|
|
|
188
186
|
end
|
|
189
187
|
|
|
190
188
|
def defined_for?(name:, expression: nil, validate: nil, **options)
|
|
191
|
-
options = options.slice(*self.options.keys)
|
|
192
|
-
|
|
193
189
|
self.name == name.to_s &&
|
|
194
190
|
(validate.nil? || validate == self.options.fetch(:validate, validate)) &&
|
|
195
191
|
options.all? { |k, v| self.options[k].to_s == v.to_s }
|
|
@@ -352,7 +348,7 @@ module ActiveRecord
|
|
|
352
348
|
# Inside migration files, the +t+ object in {create_table}[rdoc-ref:SchemaStatements#create_table]
|
|
353
349
|
# is actually of this type:
|
|
354
350
|
#
|
|
355
|
-
# class SomeMigration < ActiveRecord::Migration[
|
|
351
|
+
# class SomeMigration < ActiveRecord::Migration[8.0]
|
|
356
352
|
# def up
|
|
357
353
|
# create_table :foo do |t|
|
|
358
354
|
# puts t.class # => "ActiveRecord::ConnectionAdapters::TableDefinition"
|
|
@@ -435,7 +431,7 @@ module ActiveRecord
|
|
|
435
431
|
#
|
|
436
432
|
# == Examples
|
|
437
433
|
#
|
|
438
|
-
# # Assuming
|
|
434
|
+
# # Assuming +td+ is an instance of TableDefinition
|
|
439
435
|
# td.column(:granted, :boolean, index: true)
|
|
440
436
|
#
|
|
441
437
|
# == Short-hand examples
|
|
@@ -186,9 +186,6 @@ module ActiveRecord
|
|
|
186
186
|
# Join tables for {ActiveRecord::Base.has_and_belongs_to_many}[rdoc-ref:Associations::ClassMethods#has_and_belongs_to_many] should set it to false.
|
|
187
187
|
#
|
|
188
188
|
# A Symbol can be used to specify the type of the generated primary key column.
|
|
189
|
-
#
|
|
190
|
-
# A Hash can be used to specify the generated primary key column creation options.
|
|
191
|
-
# See {add_column}[rdoc-ref:ConnectionAdapters::SchemaStatements#add_column] for available options.
|
|
192
189
|
# [<tt>:primary_key</tt>]
|
|
193
190
|
# The name of the primary key, if one is to be added automatically.
|
|
194
191
|
# Defaults to +id+. If <tt>:id</tt> is false, then this option is ignored.
|
|
@@ -348,6 +345,15 @@ module ActiveRecord
|
|
|
348
345
|
# # Creates a table called 'assemblies_parts' with no id.
|
|
349
346
|
# create_join_table(:assemblies, :parts)
|
|
350
347
|
#
|
|
348
|
+
# # Creates a table called 'paper_boxes_papers' with no id.
|
|
349
|
+
# create_join_table('papers', 'paper_boxes')
|
|
350
|
+
#
|
|
351
|
+
# A duplicate prefix is combined into a single prefix. This is useful for
|
|
352
|
+
# namespaced models like Music::Artist and Music::Record:
|
|
353
|
+
#
|
|
354
|
+
# # Creates a table called 'music_artists_records' with no id.
|
|
355
|
+
# create_join_table('music_artists', 'music_records')
|
|
356
|
+
#
|
|
351
357
|
# You can pass an +options+ hash which can include the following keys:
|
|
352
358
|
# [<tt>:table_name</tt>]
|
|
353
359
|
# Sets the table name, overriding the default.
|
|
@@ -519,7 +525,7 @@ module ActiveRecord
|
|
|
519
525
|
raise NotImplementedError, "rename_table is not implemented"
|
|
520
526
|
end
|
|
521
527
|
|
|
522
|
-
# Drops a table from the database.
|
|
528
|
+
# Drops a table or tables from the database.
|
|
523
529
|
#
|
|
524
530
|
# [<tt>:force</tt>]
|
|
525
531
|
# Set to +:cascade+ to drop dependent objects as well.
|
|
@@ -530,10 +536,12 @@ module ActiveRecord
|
|
|
530
536
|
#
|
|
531
537
|
# Although this command ignores most +options+ and the block if one is given,
|
|
532
538
|
# it can be helpful to provide these in a migration's +change+ method so it can be reverted.
|
|
533
|
-
# In that case, +options+ and the block will be used by #create_table.
|
|
534
|
-
def drop_table(
|
|
535
|
-
|
|
536
|
-
|
|
539
|
+
# In that case, +options+ and the block will be used by #create_table except if you provide more than one table which is not supported.
|
|
540
|
+
def drop_table(*table_names, **options)
|
|
541
|
+
table_names.each do |table_name|
|
|
542
|
+
schema_cache.clear_data_source_cache!(table_name.to_s)
|
|
543
|
+
execute "DROP TABLE#{' IF EXISTS' if options[:if_exists]} #{quote_table_name(table_name)}"
|
|
544
|
+
end
|
|
537
545
|
end
|
|
538
546
|
|
|
539
547
|
# Add a new +type+ column named +column_name+ to +table_name+.
|
|
@@ -685,7 +693,7 @@ module ActiveRecord
|
|
|
685
693
|
#
|
|
686
694
|
# If the options provided include an +if_exists+ key, it will be used to check if the
|
|
687
695
|
# column does not exist. This will silently ignore the migration rather than raising
|
|
688
|
-
# if the column was already
|
|
696
|
+
# if the column was already used.
|
|
689
697
|
#
|
|
690
698
|
# remove_column(:suppliers, :qualification, if_exists: true)
|
|
691
699
|
def remove_column(table_name, column_name, type = nil, **options)
|
|
@@ -847,6 +855,16 @@ module ActiveRecord
|
|
|
847
855
|
#
|
|
848
856
|
# Note: only supported by PostgreSQL.
|
|
849
857
|
#
|
|
858
|
+
# ====== Creating an index where NULLs are treated equally
|
|
859
|
+
#
|
|
860
|
+
# add_index(:people, :last_name, nulls_not_distinct: true)
|
|
861
|
+
#
|
|
862
|
+
# generates:
|
|
863
|
+
#
|
|
864
|
+
# CREATE INDEX index_people_on_last_name ON people (last_name) NULLS NOT DISTINCT
|
|
865
|
+
#
|
|
866
|
+
# Note: only supported by PostgreSQL version 15.0.0 and greater.
|
|
867
|
+
#
|
|
850
868
|
# ====== Creating an index with a specific method
|
|
851
869
|
#
|
|
852
870
|
# add_index(:developers, :name, using: 'btree')
|
|
@@ -448,10 +448,14 @@ module ActiveRecord
|
|
|
448
448
|
# = Active Record Real \Transaction
|
|
449
449
|
class RealTransaction < Transaction
|
|
450
450
|
def materialize!
|
|
451
|
-
if
|
|
452
|
-
|
|
451
|
+
if joinable?
|
|
452
|
+
if isolation_level
|
|
453
|
+
connection.begin_isolated_db_transaction(isolation_level)
|
|
454
|
+
else
|
|
455
|
+
connection.begin_db_transaction
|
|
456
|
+
end
|
|
453
457
|
else
|
|
454
|
-
connection.
|
|
458
|
+
connection.begin_deferred_transaction(isolation_level)
|
|
455
459
|
end
|
|
456
460
|
|
|
457
461
|
super
|
|
@@ -472,13 +476,19 @@ module ActiveRecord
|
|
|
472
476
|
end
|
|
473
477
|
|
|
474
478
|
def rollback
|
|
475
|
-
|
|
479
|
+
if materialized?
|
|
480
|
+
connection.rollback_db_transaction
|
|
481
|
+
connection.reset_isolation_level if isolation_level
|
|
482
|
+
end
|
|
476
483
|
@state.full_rollback!
|
|
477
484
|
@instrumenter.finish(:rollback) if materialized?
|
|
478
485
|
end
|
|
479
486
|
|
|
480
487
|
def commit
|
|
481
|
-
|
|
488
|
+
if materialized?
|
|
489
|
+
connection.commit_db_transaction
|
|
490
|
+
connection.reset_isolation_level if isolation_level
|
|
491
|
+
end
|
|
482
492
|
@state.full_commit!
|
|
483
493
|
@instrumenter.finish(:commit) if materialized?
|
|
484
494
|
end
|