activerecord 6.0.0.rc1 → 6.0.3.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 +251 -3
- data/README.rdoc +1 -1
- data/lib/active_record.rb +1 -0
- data/lib/active_record/advisory_lock_base.rb +18 -0
- data/lib/active_record/aggregations.rb +0 -1
- data/lib/active_record/association_relation.rb +10 -8
- data/lib/active_record/associations.rb +2 -2
- data/lib/active_record/associations/alias_tracker.rb +0 -1
- data/lib/active_record/associations/association.rb +5 -1
- data/lib/active_record/associations/builder/collection_association.rb +2 -2
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +1 -3
- data/lib/active_record/associations/collection_association.rb +6 -2
- data/lib/active_record/associations/collection_proxy.rb +2 -3
- data/lib/active_record/associations/has_many_association.rb +0 -1
- data/lib/active_record/associations/join_dependency.rb +23 -9
- data/lib/active_record/associations/join_dependency/join_association.rb +12 -3
- data/lib/active_record/associations/preloader.rb +2 -3
- data/lib/active_record/associations/preloader/association.rb +3 -1
- data/lib/active_record/attribute_assignment.rb +0 -1
- data/lib/active_record/attribute_decorators.rb +0 -2
- data/lib/active_record/attribute_methods.rb +0 -51
- data/lib/active_record/attribute_methods/before_type_cast.rb +0 -1
- data/lib/active_record/attribute_methods/dirty.rb +8 -3
- data/lib/active_record/attribute_methods/primary_key.rb +0 -2
- data/lib/active_record/attribute_methods/read.rb +0 -1
- data/lib/active_record/attribute_methods/serialization.rb +0 -1
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +0 -2
- data/lib/active_record/attribute_methods/write.rb +0 -1
- data/lib/active_record/attributes.rb +0 -1
- data/lib/active_record/autosave_association.rb +11 -7
- data/lib/active_record/callbacks.rb +1 -2
- data/lib/active_record/coders/yaml_column.rb +0 -1
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +107 -13
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +21 -15
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +5 -5
- data/lib/active_record/connection_adapters/abstract/quoting.rb +53 -0
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +1 -2
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +27 -27
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +1 -1
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +55 -37
- data/lib/active_record/connection_adapters/abstract/transaction.rb +14 -7
- data/lib/active_record/connection_adapters/abstract_adapter.rb +62 -25
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +25 -32
- data/lib/active_record/connection_adapters/connection_specification.rb +3 -4
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +2 -2
- data/lib/active_record/connection_adapters/mysql/column.rb +1 -1
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +8 -12
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +0 -1
- data/lib/active_record/connection_adapters/mysql/quoting.rb +44 -7
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +1 -2
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +3 -1
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +8 -8
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +12 -4
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +9 -3
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +39 -2
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +15 -29
- data/lib/active_record/connection_adapters/postgresql/utils.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +17 -3
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +8 -7
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +38 -3
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +3 -3
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +23 -8
- data/lib/active_record/connection_adapters/statement_pool.rb +0 -1
- data/lib/active_record/connection_handling.rb +17 -22
- data/lib/active_record/core.rb +8 -6
- data/lib/active_record/counter_cache.rb +4 -1
- data/lib/active_record/database_configurations.rb +60 -31
- data/lib/active_record/database_configurations/url_config.rb +0 -1
- data/lib/active_record/dynamic_matchers.rb +2 -3
- data/lib/active_record/enum.rb +9 -0
- data/lib/active_record/explain.rb +0 -1
- data/lib/active_record/fixture_set/table_row.rb +0 -1
- data/lib/active_record/fixture_set/table_rows.rb +0 -1
- data/lib/active_record/fixtures.rb +11 -9
- data/lib/active_record/gem_version.rb +1 -1
- data/lib/active_record/inheritance.rb +0 -3
- data/lib/active_record/insert_all.rb +5 -6
- data/lib/active_record/internal_metadata.rb +1 -1
- data/lib/active_record/locking/optimistic.rb +0 -1
- data/lib/active_record/log_subscriber.rb +1 -1
- data/lib/active_record/middleware/database_selector.rb +3 -4
- data/lib/active_record/middleware/database_selector/resolver.rb +5 -8
- data/lib/active_record/migration.rb +43 -32
- data/lib/active_record/migration/command_recorder.rb +6 -18
- data/lib/active_record/migration/compatibility.rb +3 -3
- data/lib/active_record/migration/join_table.rb +0 -1
- data/lib/active_record/model_schema.rb +3 -2
- data/lib/active_record/nested_attributes.rb +0 -2
- data/lib/active_record/no_touching.rb +2 -2
- data/lib/active_record/null_relation.rb +0 -1
- data/lib/active_record/persistence.rb +4 -5
- data/lib/active_record/querying.rb +1 -1
- data/lib/active_record/railtie.rb +1 -2
- data/lib/active_record/railties/collection_cache_association_loading.rb +1 -1
- data/lib/active_record/railties/databases.rake +63 -23
- data/lib/active_record/reflection.rb +9 -9
- data/lib/active_record/relation.rb +13 -1
- data/lib/active_record/relation/batches.rb +0 -1
- data/lib/active_record/relation/calculations.rb +3 -5
- data/lib/active_record/relation/delegation.rb +7 -6
- data/lib/active_record/relation/finder_methods.rb +14 -4
- data/lib/active_record/relation/from_clause.rb +4 -0
- data/lib/active_record/relation/merger.rb +6 -3
- data/lib/active_record/relation/predicate_builder.rb +1 -5
- data/lib/active_record/relation/query_methods.rb +94 -55
- data/lib/active_record/relation/spawn_methods.rb +0 -1
- data/lib/active_record/relation/where_clause.rb +0 -1
- data/lib/active_record/result.rb +0 -1
- data/lib/active_record/sanitization.rb +30 -2
- data/lib/active_record/schema.rb +1 -1
- data/lib/active_record/schema_dumper.rb +5 -1
- data/lib/active_record/schema_migration.rb +1 -1
- data/lib/active_record/scoping.rb +0 -1
- data/lib/active_record/scoping/default.rb +0 -1
- data/lib/active_record/scoping/named.rb +3 -3
- data/lib/active_record/store.rb +1 -1
- data/lib/active_record/suppressor.rb +2 -2
- data/lib/active_record/table_metadata.rb +21 -10
- data/lib/active_record/tasks/database_tasks.rb +76 -8
- data/lib/active_record/tasks/mysql_database_tasks.rb +3 -2
- data/lib/active_record/tasks/postgresql_database_tasks.rb +0 -1
- data/lib/active_record/tasks/sqlite_database_tasks.rb +0 -1
- data/lib/active_record/test_databases.rb +1 -16
- data/lib/active_record/test_fixtures.rb +2 -1
- data/lib/active_record/timestamp.rb +26 -17
- data/lib/active_record/touch_later.rb +3 -2
- data/lib/active_record/transactions.rb +18 -19
- data/lib/active_record/type.rb +0 -1
- data/lib/active_record/type/adapter_specific_registry.rb +2 -5
- data/lib/active_record/type/hash_lookup_type_map.rb +0 -1
- data/lib/active_record/type/serialized.rb +0 -1
- data/lib/active_record/type/type_map.rb +0 -1
- data/lib/active_record/type/unsigned_integer.rb +0 -1
- data/lib/active_record/type_caster/connection.rb +16 -10
- data/lib/active_record/validations.rb +3 -3
- data/lib/active_record/validations/associated.rb +1 -2
- data/lib/arel.rb +17 -6
- data/lib/arel/predications.rb +5 -6
- data/lib/arel/visitors/depth_first.rb +1 -2
- data/lib/arel/visitors/dot.rb +0 -1
- data/lib/arel/visitors/mssql.rb +0 -1
- data/lib/arel/visitors/oracle.rb +1 -2
- data/lib/arel/visitors/oracle12.rb +0 -1
- data/lib/arel/visitors/postgresql.rb +0 -1
- data/lib/arel/visitors/sqlite.rb +0 -1
- data/lib/arel/visitors/to_sql.rb +23 -27
- data/lib/arel/visitors/visitor.rb +9 -6
- data/lib/arel/visitors/where_sql.rb +0 -1
- data/lib/rails/generators/active_record/application_record/application_record_generator.rb +0 -1
- data/lib/rails/generators/active_record/migration.rb +0 -1
- data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +1 -1
- data/lib/rails/generators/active_record/model/model_generator.rb +0 -1
- metadata +13 -9
@@ -314,7 +314,7 @@ module ActiveRecord
|
|
314
314
|
@_destroy_callback_already_called = false
|
315
315
|
end
|
316
316
|
|
317
|
-
def touch(
|
317
|
+
def touch(*, **) #:nodoc:
|
318
318
|
_run_touch_callbacks { super }
|
319
319
|
end
|
320
320
|
|
@@ -323,7 +323,6 @@ module ActiveRecord
|
|
323
323
|
end
|
324
324
|
|
325
325
|
private
|
326
|
-
|
327
326
|
def create_or_update(**)
|
328
327
|
_run_save_callbacks { super }
|
329
328
|
end
|
@@ -3,6 +3,7 @@
|
|
3
3
|
require "thread"
|
4
4
|
require "concurrent/map"
|
5
5
|
require "monitor"
|
6
|
+
require "weakref"
|
6
7
|
|
7
8
|
module ActiveRecord
|
8
9
|
# Raised when a connection could not be obtained within the connection
|
@@ -19,6 +20,26 @@ module ActiveRecord
|
|
19
20
|
end
|
20
21
|
|
21
22
|
module ConnectionAdapters
|
23
|
+
module AbstractPool # :nodoc:
|
24
|
+
def get_schema_cache(connection)
|
25
|
+
@schema_cache ||= SchemaCache.new(connection)
|
26
|
+
@schema_cache.connection = connection
|
27
|
+
@schema_cache
|
28
|
+
end
|
29
|
+
|
30
|
+
def set_schema_cache(cache)
|
31
|
+
@schema_cache = cache
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
class NullPool # :nodoc:
|
36
|
+
include ConnectionAdapters::AbstractPool
|
37
|
+
|
38
|
+
def initialize
|
39
|
+
@schema_cache = nil
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
22
43
|
# Connection pool base class for managing Active Record database
|
23
44
|
# connections.
|
24
45
|
#
|
@@ -146,7 +167,6 @@ module ActiveRecord
|
|
146
167
|
end
|
147
168
|
|
148
169
|
private
|
149
|
-
|
150
170
|
def internal_poll(timeout)
|
151
171
|
no_wait_poll || (timeout && wait_poll(timeout))
|
152
172
|
end
|
@@ -294,23 +314,58 @@ module ActiveRecord
|
|
294
314
|
@frequency = frequency
|
295
315
|
end
|
296
316
|
|
317
|
+
@mutex = Mutex.new
|
318
|
+
@pools = {}
|
319
|
+
@threads = {}
|
320
|
+
|
321
|
+
class << self
|
322
|
+
def register_pool(pool, frequency) # :nodoc:
|
323
|
+
@mutex.synchronize do
|
324
|
+
unless @threads[frequency]&.alive?
|
325
|
+
@threads[frequency] = spawn_thread(frequency)
|
326
|
+
end
|
327
|
+
@pools[frequency] ||= []
|
328
|
+
@pools[frequency] << WeakRef.new(pool)
|
329
|
+
end
|
330
|
+
end
|
331
|
+
|
332
|
+
private
|
333
|
+
def spawn_thread(frequency)
|
334
|
+
Thread.new(frequency) do |t|
|
335
|
+
running = true
|
336
|
+
while running
|
337
|
+
sleep t
|
338
|
+
@mutex.synchronize do
|
339
|
+
@pools[frequency].select!(&:weakref_alive?)
|
340
|
+
@pools[frequency].each do |p|
|
341
|
+
p.reap
|
342
|
+
p.flush
|
343
|
+
rescue WeakRef::RefError
|
344
|
+
end
|
345
|
+
|
346
|
+
if @pools[frequency].empty?
|
347
|
+
@pools.delete(frequency)
|
348
|
+
@threads.delete(frequency)
|
349
|
+
running = false
|
350
|
+
end
|
351
|
+
end
|
352
|
+
end
|
353
|
+
end
|
354
|
+
end
|
355
|
+
end
|
356
|
+
|
297
357
|
def run
|
298
358
|
return unless frequency && frequency > 0
|
299
|
-
|
300
|
-
loop do
|
301
|
-
sleep t
|
302
|
-
p.reap
|
303
|
-
p.flush
|
304
|
-
end
|
305
|
-
}
|
359
|
+
self.class.register_pool(pool, frequency)
|
306
360
|
end
|
307
361
|
end
|
308
362
|
|
309
363
|
include MonitorMixin
|
310
364
|
include QueryCache::ConnectionPoolConfiguration
|
365
|
+
include ConnectionAdapters::AbstractPool
|
311
366
|
|
312
367
|
attr_accessor :automatic_reconnect, :checkout_timeout, :schema_cache
|
313
|
-
attr_reader :spec, :
|
368
|
+
attr_reader :spec, :size, :reaper
|
314
369
|
|
315
370
|
# Creates a new ConnectionPool object. +spec+ is a ConnectionSpecification
|
316
371
|
# object which describes database connection information (e.g. adapter,
|
@@ -379,7 +434,7 @@ module ActiveRecord
|
|
379
434
|
# #connection can be called any number of times; the connection is
|
380
435
|
# held in a cache keyed by a thread.
|
381
436
|
def connection
|
382
|
-
@thread_cached_conns[connection_cache_key(
|
437
|
+
@thread_cached_conns[connection_cache_key(current_thread)] ||= checkout
|
383
438
|
end
|
384
439
|
|
385
440
|
# Returns true if there is an open connection being used for the current thread.
|
@@ -388,7 +443,7 @@ module ActiveRecord
|
|
388
443
|
# #connection or #with_connection methods. Connections obtained through
|
389
444
|
# #checkout will not be detected by #active_connection?
|
390
445
|
def active_connection?
|
391
|
-
@thread_cached_conns[connection_cache_key(
|
446
|
+
@thread_cached_conns[connection_cache_key(current_thread)]
|
392
447
|
end
|
393
448
|
|
394
449
|
# Signal that the thread is finished with the current connection.
|
@@ -423,6 +478,21 @@ module ActiveRecord
|
|
423
478
|
synchronize { @connections.any? }
|
424
479
|
end
|
425
480
|
|
481
|
+
# Returns an array containing the connections currently in the pool.
|
482
|
+
# Access to the array does not require synchronization on the pool because
|
483
|
+
# the array is newly created and not retained by the pool.
|
484
|
+
#
|
485
|
+
# However; this method bypasses the ConnectionPool's thread-safe connection
|
486
|
+
# access pattern. A returned connection may be owned by another thread,
|
487
|
+
# unowned, or by happen-stance owned by the calling thread.
|
488
|
+
#
|
489
|
+
# Calling methods on a connection without ownership is subject to the
|
490
|
+
# thread-safety guarantees of the underlying method. Many of the methods
|
491
|
+
# on connection adapter classes are inherently multi-thread unsafe.
|
492
|
+
def connections
|
493
|
+
synchronize { @connections.dup }
|
494
|
+
end
|
495
|
+
|
426
496
|
# Disconnects all connections in the pool, and clears the pool.
|
427
497
|
#
|
428
498
|
# Raises:
|
@@ -578,6 +648,7 @@ module ActiveRecord
|
|
578
648
|
# or a thread dies unexpectedly.
|
579
649
|
def reap
|
580
650
|
stale_connections = synchronize do
|
651
|
+
return unless @connections
|
581
652
|
@connections.select do |conn|
|
582
653
|
conn.in_use? && !conn.owner.alive?
|
583
654
|
end.each do |conn|
|
@@ -602,6 +673,7 @@ module ActiveRecord
|
|
602
673
|
return if minimum_idle.nil?
|
603
674
|
|
604
675
|
idle_connections = synchronize do
|
676
|
+
return unless @connections
|
605
677
|
@connections.select do |conn|
|
606
678
|
!conn.in_use? && conn.seconds_idle >= minimum_idle
|
607
679
|
end.each do |conn|
|
@@ -668,6 +740,10 @@ module ActiveRecord
|
|
668
740
|
thread
|
669
741
|
end
|
670
742
|
|
743
|
+
def current_thread
|
744
|
+
@lock_thread || Thread.current
|
745
|
+
end
|
746
|
+
|
671
747
|
# Take control of all existing connections so a "group" action such as
|
672
748
|
# reload/disconnect can be performed safely. It is no longer enough to
|
673
749
|
# wrap it in +synchronize+ because some pool's actions are allowed
|
@@ -809,7 +885,6 @@ module ActiveRecord
|
|
809
885
|
|
810
886
|
def new_connection
|
811
887
|
Base.send(spec.adapter_method, spec.config).tap do |conn|
|
812
|
-
conn.schema_cache = schema_cache.dup if schema_cache
|
813
888
|
conn.check_version
|
814
889
|
end
|
815
890
|
end
|
@@ -947,6 +1022,26 @@ module ActiveRecord
|
|
947
1022
|
ObjectSpace.define_finalizer self, ConnectionHandler.unowned_pool_finalizer(@owner_to_pool)
|
948
1023
|
end
|
949
1024
|
|
1025
|
+
def prevent_writes # :nodoc:
|
1026
|
+
Thread.current[:prevent_writes]
|
1027
|
+
end
|
1028
|
+
|
1029
|
+
def prevent_writes=(prevent_writes) # :nodoc:
|
1030
|
+
Thread.current[:prevent_writes] = prevent_writes
|
1031
|
+
end
|
1032
|
+
|
1033
|
+
# Prevent writing to the database regardless of role.
|
1034
|
+
#
|
1035
|
+
# In some cases you may want to prevent writes to the database
|
1036
|
+
# even if you are on a database that can write. `while_preventing_writes`
|
1037
|
+
# will prevent writes to the database for the duration of the block.
|
1038
|
+
def while_preventing_writes(enabled = true)
|
1039
|
+
original, self.prevent_writes = self.prevent_writes, enabled
|
1040
|
+
yield
|
1041
|
+
ensure
|
1042
|
+
self.prevent_writes = original
|
1043
|
+
end
|
1044
|
+
|
950
1045
|
def connection_pool_list
|
951
1046
|
owner_to_pool.values.compact
|
952
1047
|
end
|
@@ -1064,7 +1159,6 @@ module ActiveRecord
|
|
1064
1159
|
end
|
1065
1160
|
|
1066
1161
|
private
|
1067
|
-
|
1068
1162
|
def owner_to_pool
|
1069
1163
|
@owner_to_pool[Process.pid]
|
1070
1164
|
end
|
@@ -149,6 +149,10 @@ module ActiveRecord
|
|
149
149
|
exec_query(sql, name, binds)
|
150
150
|
end
|
151
151
|
|
152
|
+
def exec_insert_all(sql, name) # :nodoc:
|
153
|
+
exec_query(sql, name)
|
154
|
+
end
|
155
|
+
|
152
156
|
# Executes an INSERT query and returns the new record's ID
|
153
157
|
#
|
154
158
|
# +id_value+ will be returned unless the value is +nil+, in
|
@@ -178,7 +182,7 @@ module ActiveRecord
|
|
178
182
|
|
179
183
|
# Executes the truncate statement.
|
180
184
|
def truncate(table_name, name = nil)
|
181
|
-
execute(
|
185
|
+
execute(build_truncate_statement(table_name), name)
|
182
186
|
end
|
183
187
|
|
184
188
|
def truncate_tables(*table_names) # :nodoc:
|
@@ -186,9 +190,8 @@ module ActiveRecord
|
|
186
190
|
|
187
191
|
with_multi_statements do
|
188
192
|
disable_referential_integrity do
|
189
|
-
|
190
|
-
|
191
|
-
end
|
193
|
+
statements = build_truncate_statements(table_names)
|
194
|
+
execute_batch(statements, "Truncate Tables")
|
192
195
|
end
|
193
196
|
end
|
194
197
|
end
|
@@ -359,14 +362,12 @@ module ActiveRecord
|
|
359
362
|
def insert_fixtures_set(fixture_set, tables_to_delete = [])
|
360
363
|
fixture_inserts = build_fixture_statements(fixture_set)
|
361
364
|
table_deletes = tables_to_delete.map { |table| "DELETE FROM #{quote_table_name(table)}" }
|
362
|
-
|
365
|
+
statements = table_deletes + fixture_inserts
|
363
366
|
|
364
367
|
with_multi_statements do
|
365
368
|
disable_referential_integrity do
|
366
369
|
transaction(requires_new: true) do
|
367
|
-
|
368
|
-
execute_batch(sql, "Fixtures Load")
|
369
|
-
end
|
370
|
+
execute_batch(statements, "Fixtures Load")
|
370
371
|
end
|
371
372
|
end
|
372
373
|
end
|
@@ -402,8 +403,10 @@ module ActiveRecord
|
|
402
403
|
end
|
403
404
|
|
404
405
|
private
|
405
|
-
def execute_batch(
|
406
|
-
|
406
|
+
def execute_batch(statements, name = nil)
|
407
|
+
statements.each do |statement|
|
408
|
+
execute(statement, name)
|
409
|
+
end
|
407
410
|
end
|
408
411
|
|
409
412
|
DEFAULT_INSERT_VALUE = Arel.sql("DEFAULT").freeze
|
@@ -453,7 +456,7 @@ module ActiveRecord
|
|
453
456
|
end
|
454
457
|
|
455
458
|
manager.values = manager.create_values_list(values_list)
|
456
|
-
manager.
|
459
|
+
visitor.compile(manager.ast)
|
457
460
|
end
|
458
461
|
|
459
462
|
def build_fixture_statements(fixture_set)
|
@@ -463,11 +466,14 @@ module ActiveRecord
|
|
463
466
|
end.compact
|
464
467
|
end
|
465
468
|
|
466
|
-
def
|
467
|
-
|
468
|
-
|
469
|
+
def build_truncate_statement(table_name)
|
470
|
+
"TRUNCATE TABLE #{quote_table_name(table_name)}"
|
471
|
+
end
|
472
|
+
|
473
|
+
def build_truncate_statements(table_names)
|
474
|
+
table_names.map do |table_name|
|
475
|
+
build_truncate_statement(table_name)
|
469
476
|
end
|
470
|
-
combine_multi_statements(truncate_tables)
|
471
477
|
end
|
472
478
|
|
473
479
|
def with_multi_statements
|
@@ -8,7 +8,7 @@ module ActiveRecord
|
|
8
8
|
class << self
|
9
9
|
def included(base) #:nodoc:
|
10
10
|
dirties_query_cache base, :insert, :update, :delete, :truncate, :truncate_tables,
|
11
|
-
:rollback_to_savepoint, :rollback_db_transaction
|
11
|
+
:rollback_to_savepoint, :rollback_db_transaction, :exec_insert_all
|
12
12
|
|
13
13
|
base.set_callback :checkout, :after, :configure_query_cache!
|
14
14
|
base.set_callback :checkin, :after, :disable_query_cache!
|
@@ -33,17 +33,17 @@ module ActiveRecord
|
|
33
33
|
end
|
34
34
|
|
35
35
|
def enable_query_cache!
|
36
|
-
@query_cache_enabled[connection_cache_key(
|
36
|
+
@query_cache_enabled[connection_cache_key(current_thread)] = true
|
37
37
|
connection.enable_query_cache! if active_connection?
|
38
38
|
end
|
39
39
|
|
40
40
|
def disable_query_cache!
|
41
|
-
@query_cache_enabled.delete connection_cache_key(
|
41
|
+
@query_cache_enabled.delete connection_cache_key(current_thread)
|
42
42
|
connection.disable_query_cache! if active_connection?
|
43
43
|
end
|
44
44
|
|
45
45
|
def query_cache_enabled
|
46
|
-
@query_cache_enabled[connection_cache_key(
|
46
|
+
@query_cache_enabled[connection_cache_key(current_thread)]
|
47
47
|
end
|
48
48
|
end
|
49
49
|
|
@@ -109,7 +109,6 @@ module ActiveRecord
|
|
109
109
|
end
|
110
110
|
|
111
111
|
private
|
112
|
-
|
113
112
|
def cache_sql(sql, name, binds)
|
114
113
|
@lock.synchronize do
|
115
114
|
result =
|
@@ -135,6 +134,7 @@ module ActiveRecord
|
|
135
134
|
type_casted_binds: -> { type_casted_binds(binds) },
|
136
135
|
name: name,
|
137
136
|
connection_id: object_id,
|
137
|
+
connection: self,
|
138
138
|
cached: true
|
139
139
|
}
|
140
140
|
end
|
@@ -142,6 +142,59 @@ module ActiveRecord
|
|
142
142
|
value.to_s.gsub(%r{ (/ (?: | \g<1>) \*) \+? \s* | \s* (\* (?: | \g<2>) /) }x, "")
|
143
143
|
end
|
144
144
|
|
145
|
+
def column_name_matcher # :nodoc:
|
146
|
+
COLUMN_NAME
|
147
|
+
end
|
148
|
+
|
149
|
+
def column_name_with_order_matcher # :nodoc:
|
150
|
+
COLUMN_NAME_WITH_ORDER
|
151
|
+
end
|
152
|
+
|
153
|
+
# Regexp for column names (with or without a table name prefix).
|
154
|
+
# Matches the following:
|
155
|
+
#
|
156
|
+
# "#{table_name}.#{column_name}"
|
157
|
+
# "#{column_name}"
|
158
|
+
COLUMN_NAME = /
|
159
|
+
\A
|
160
|
+
(
|
161
|
+
(?:
|
162
|
+
# table_name.column_name | function(one or no argument)
|
163
|
+
((?:\w+\.)?\w+) | \w+\((?:|\g<2>)\)
|
164
|
+
)
|
165
|
+
(?:\s+AS\s+\w+)?
|
166
|
+
)
|
167
|
+
(?:\s*,\s*\g<1>)*
|
168
|
+
\z
|
169
|
+
/ix
|
170
|
+
|
171
|
+
# Regexp for column names with order (with or without a table name prefix,
|
172
|
+
# with or without various order modifiers). Matches the following:
|
173
|
+
#
|
174
|
+
# "#{table_name}.#{column_name}"
|
175
|
+
# "#{table_name}.#{column_name} #{direction}"
|
176
|
+
# "#{table_name}.#{column_name} #{direction} NULLS FIRST"
|
177
|
+
# "#{table_name}.#{column_name} NULLS LAST"
|
178
|
+
# "#{column_name}"
|
179
|
+
# "#{column_name} #{direction}"
|
180
|
+
# "#{column_name} #{direction} NULLS FIRST"
|
181
|
+
# "#{column_name} NULLS LAST"
|
182
|
+
COLUMN_NAME_WITH_ORDER = /
|
183
|
+
\A
|
184
|
+
(
|
185
|
+
(?:
|
186
|
+
# table_name.column_name | function(one or no argument)
|
187
|
+
((?:\w+\.)?\w+) | \w+\((?:|\g<2>)\)
|
188
|
+
)
|
189
|
+
(?:\s+ASC|\s+DESC)?
|
190
|
+
(?:\s+NULLS\s+(?:FIRST|LAST))?
|
191
|
+
)
|
192
|
+
(?:\s*,\s*\g<1>)*
|
193
|
+
\z
|
194
|
+
/ix
|
195
|
+
|
196
|
+
private_constant :COLUMN_NAME, :COLUMN_NAME_WITH_ORDER
|
197
|
+
|
145
198
|
private
|
146
199
|
def type_casted_binds(binds)
|
147
200
|
if binds.first.is_a?(Array)
|
@@ -19,7 +19,6 @@ module ActiveRecord
|
|
19
19
|
to: :@conn, private: true
|
20
20
|
|
21
21
|
private
|
22
|
-
|
23
22
|
def visit_AlterTable(o)
|
24
23
|
sql = +"ALTER TABLE #{quote_table_name(o.name)} "
|
25
24
|
sql << o.adds.map { |col| accept col }.join(" ")
|
@@ -28,7 +27,7 @@ module ActiveRecord
|
|
28
27
|
end
|
29
28
|
|
30
29
|
def visit_ColumnDefinition(o)
|
31
|
-
o.sql_type = type_to_sql(o.type, o.options)
|
30
|
+
o.sql_type = type_to_sql(o.type, **o.options)
|
32
31
|
column_sql = +"#{quote_column_name(o.name)} #{o.sql_type}"
|
33
32
|
add_column_options!(column_sql, column_options(o)) unless o.type == :primary_key
|
34
33
|
column_sql
|