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.

Files changed (168) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +251 -3
  3. data/README.rdoc +1 -1
  4. data/lib/active_record.rb +1 -0
  5. data/lib/active_record/advisory_lock_base.rb +18 -0
  6. data/lib/active_record/aggregations.rb +0 -1
  7. data/lib/active_record/association_relation.rb +10 -8
  8. data/lib/active_record/associations.rb +2 -2
  9. data/lib/active_record/associations/alias_tracker.rb +0 -1
  10. data/lib/active_record/associations/association.rb +5 -1
  11. data/lib/active_record/associations/builder/collection_association.rb +2 -2
  12. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +1 -3
  13. data/lib/active_record/associations/collection_association.rb +6 -2
  14. data/lib/active_record/associations/collection_proxy.rb +2 -3
  15. data/lib/active_record/associations/has_many_association.rb +0 -1
  16. data/lib/active_record/associations/join_dependency.rb +23 -9
  17. data/lib/active_record/associations/join_dependency/join_association.rb +12 -3
  18. data/lib/active_record/associations/preloader.rb +2 -3
  19. data/lib/active_record/associations/preloader/association.rb +3 -1
  20. data/lib/active_record/attribute_assignment.rb +0 -1
  21. data/lib/active_record/attribute_decorators.rb +0 -2
  22. data/lib/active_record/attribute_methods.rb +0 -51
  23. data/lib/active_record/attribute_methods/before_type_cast.rb +0 -1
  24. data/lib/active_record/attribute_methods/dirty.rb +8 -3
  25. data/lib/active_record/attribute_methods/primary_key.rb +0 -2
  26. data/lib/active_record/attribute_methods/read.rb +0 -1
  27. data/lib/active_record/attribute_methods/serialization.rb +0 -1
  28. data/lib/active_record/attribute_methods/time_zone_conversion.rb +0 -2
  29. data/lib/active_record/attribute_methods/write.rb +0 -1
  30. data/lib/active_record/attributes.rb +0 -1
  31. data/lib/active_record/autosave_association.rb +11 -7
  32. data/lib/active_record/callbacks.rb +1 -2
  33. data/lib/active_record/coders/yaml_column.rb +0 -1
  34. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +107 -13
  35. data/lib/active_record/connection_adapters/abstract/database_statements.rb +21 -15
  36. data/lib/active_record/connection_adapters/abstract/query_cache.rb +5 -5
  37. data/lib/active_record/connection_adapters/abstract/quoting.rb +53 -0
  38. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +1 -2
  39. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +27 -27
  40. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +1 -1
  41. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +55 -37
  42. data/lib/active_record/connection_adapters/abstract/transaction.rb +14 -7
  43. data/lib/active_record/connection_adapters/abstract_adapter.rb +62 -25
  44. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +25 -32
  45. data/lib/active_record/connection_adapters/connection_specification.rb +3 -4
  46. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +2 -2
  47. data/lib/active_record/connection_adapters/mysql/column.rb +1 -1
  48. data/lib/active_record/connection_adapters/mysql/database_statements.rb +8 -12
  49. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +0 -1
  50. data/lib/active_record/connection_adapters/mysql/quoting.rb +44 -7
  51. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +1 -2
  52. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +3 -1
  53. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +8 -8
  54. data/lib/active_record/connection_adapters/mysql2_adapter.rb +12 -4
  55. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +9 -3
  56. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +0 -1
  57. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +0 -1
  58. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +0 -1
  59. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +0 -1
  60. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +2 -2
  61. data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +1 -1
  62. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +0 -1
  63. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +0 -1
  64. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +1 -1
  65. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +0 -1
  66. data/lib/active_record/connection_adapters/postgresql/quoting.rb +39 -2
  67. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +1 -1
  68. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +2 -2
  69. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +1 -1
  70. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +0 -1
  71. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +15 -29
  72. data/lib/active_record/connection_adapters/postgresql/utils.rb +0 -1
  73. data/lib/active_record/connection_adapters/postgresql_adapter.rb +17 -3
  74. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +8 -7
  75. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +38 -3
  76. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +3 -3
  77. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +23 -8
  78. data/lib/active_record/connection_adapters/statement_pool.rb +0 -1
  79. data/lib/active_record/connection_handling.rb +17 -22
  80. data/lib/active_record/core.rb +8 -6
  81. data/lib/active_record/counter_cache.rb +4 -1
  82. data/lib/active_record/database_configurations.rb +60 -31
  83. data/lib/active_record/database_configurations/url_config.rb +0 -1
  84. data/lib/active_record/dynamic_matchers.rb +2 -3
  85. data/lib/active_record/enum.rb +9 -0
  86. data/lib/active_record/explain.rb +0 -1
  87. data/lib/active_record/fixture_set/table_row.rb +0 -1
  88. data/lib/active_record/fixture_set/table_rows.rb +0 -1
  89. data/lib/active_record/fixtures.rb +11 -9
  90. data/lib/active_record/gem_version.rb +1 -1
  91. data/lib/active_record/inheritance.rb +0 -3
  92. data/lib/active_record/insert_all.rb +5 -6
  93. data/lib/active_record/internal_metadata.rb +1 -1
  94. data/lib/active_record/locking/optimistic.rb +0 -1
  95. data/lib/active_record/log_subscriber.rb +1 -1
  96. data/lib/active_record/middleware/database_selector.rb +3 -4
  97. data/lib/active_record/middleware/database_selector/resolver.rb +5 -8
  98. data/lib/active_record/migration.rb +43 -32
  99. data/lib/active_record/migration/command_recorder.rb +6 -18
  100. data/lib/active_record/migration/compatibility.rb +3 -3
  101. data/lib/active_record/migration/join_table.rb +0 -1
  102. data/lib/active_record/model_schema.rb +3 -2
  103. data/lib/active_record/nested_attributes.rb +0 -2
  104. data/lib/active_record/no_touching.rb +2 -2
  105. data/lib/active_record/null_relation.rb +0 -1
  106. data/lib/active_record/persistence.rb +4 -5
  107. data/lib/active_record/querying.rb +1 -1
  108. data/lib/active_record/railtie.rb +1 -2
  109. data/lib/active_record/railties/collection_cache_association_loading.rb +1 -1
  110. data/lib/active_record/railties/databases.rake +63 -23
  111. data/lib/active_record/reflection.rb +9 -9
  112. data/lib/active_record/relation.rb +13 -1
  113. data/lib/active_record/relation/batches.rb +0 -1
  114. data/lib/active_record/relation/calculations.rb +3 -5
  115. data/lib/active_record/relation/delegation.rb +7 -6
  116. data/lib/active_record/relation/finder_methods.rb +14 -4
  117. data/lib/active_record/relation/from_clause.rb +4 -0
  118. data/lib/active_record/relation/merger.rb +6 -3
  119. data/lib/active_record/relation/predicate_builder.rb +1 -5
  120. data/lib/active_record/relation/query_methods.rb +94 -55
  121. data/lib/active_record/relation/spawn_methods.rb +0 -1
  122. data/lib/active_record/relation/where_clause.rb +0 -1
  123. data/lib/active_record/result.rb +0 -1
  124. data/lib/active_record/sanitization.rb +30 -2
  125. data/lib/active_record/schema.rb +1 -1
  126. data/lib/active_record/schema_dumper.rb +5 -1
  127. data/lib/active_record/schema_migration.rb +1 -1
  128. data/lib/active_record/scoping.rb +0 -1
  129. data/lib/active_record/scoping/default.rb +0 -1
  130. data/lib/active_record/scoping/named.rb +3 -3
  131. data/lib/active_record/store.rb +1 -1
  132. data/lib/active_record/suppressor.rb +2 -2
  133. data/lib/active_record/table_metadata.rb +21 -10
  134. data/lib/active_record/tasks/database_tasks.rb +76 -8
  135. data/lib/active_record/tasks/mysql_database_tasks.rb +3 -2
  136. data/lib/active_record/tasks/postgresql_database_tasks.rb +0 -1
  137. data/lib/active_record/tasks/sqlite_database_tasks.rb +0 -1
  138. data/lib/active_record/test_databases.rb +1 -16
  139. data/lib/active_record/test_fixtures.rb +2 -1
  140. data/lib/active_record/timestamp.rb +26 -17
  141. data/lib/active_record/touch_later.rb +3 -2
  142. data/lib/active_record/transactions.rb +18 -19
  143. data/lib/active_record/type.rb +0 -1
  144. data/lib/active_record/type/adapter_specific_registry.rb +2 -5
  145. data/lib/active_record/type/hash_lookup_type_map.rb +0 -1
  146. data/lib/active_record/type/serialized.rb +0 -1
  147. data/lib/active_record/type/type_map.rb +0 -1
  148. data/lib/active_record/type/unsigned_integer.rb +0 -1
  149. data/lib/active_record/type_caster/connection.rb +16 -10
  150. data/lib/active_record/validations.rb +3 -3
  151. data/lib/active_record/validations/associated.rb +1 -2
  152. data/lib/arel.rb +17 -6
  153. data/lib/arel/predications.rb +5 -6
  154. data/lib/arel/visitors/depth_first.rb +1 -2
  155. data/lib/arel/visitors/dot.rb +0 -1
  156. data/lib/arel/visitors/mssql.rb +0 -1
  157. data/lib/arel/visitors/oracle.rb +1 -2
  158. data/lib/arel/visitors/oracle12.rb +0 -1
  159. data/lib/arel/visitors/postgresql.rb +0 -1
  160. data/lib/arel/visitors/sqlite.rb +0 -1
  161. data/lib/arel/visitors/to_sql.rb +23 -27
  162. data/lib/arel/visitors/visitor.rb +9 -6
  163. data/lib/arel/visitors/where_sql.rb +0 -1
  164. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +0 -1
  165. data/lib/rails/generators/active_record/migration.rb +0 -1
  166. data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +1 -1
  167. data/lib/rails/generators/active_record/model/model_generator.rb +0 -1
  168. metadata +13 -9
@@ -314,7 +314,7 @@ module ActiveRecord
314
314
  @_destroy_callback_already_called = false
315
315
  end
316
316
 
317
- def touch(*) #:nodoc:
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
@@ -39,7 +39,6 @@ module ActiveRecord
39
39
  end
40
40
 
41
41
  private
42
-
43
42
  def check_arity_of_constructor
44
43
  load(nil)
45
44
  rescue ArgumentError
@@ -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
- Thread.new(frequency, pool) { |t, p|
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, :connections, :size, :reaper
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(@lock_thread || Thread.current)] ||= checkout
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(Thread.current)]
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(build_truncate_statements(table_name), name)
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
- Array(build_truncate_statements(*table_names)).each do |sql|
190
- execute_batch(sql, "Truncate Tables")
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
- total_sql = Array(combine_multi_statements(table_deletes + fixture_inserts))
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
- total_sql.each do |sql|
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(sql, name = nil)
406
- execute(sql, name)
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.to_sql
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 build_truncate_statements(*table_names)
467
- truncate_tables = table_names.map do |table_name|
468
- "TRUNCATE TABLE #{quote_table_name(table_name)}"
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(Thread.current)] = true
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(Thread.current)
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(Thread.current)]
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