activerecord 6.0.0 → 6.0.3

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 (150) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +185 -1
  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/has_and_belongs_to_many.rb +0 -2
  12. data/lib/active_record/associations/collection_association.rb +6 -2
  13. data/lib/active_record/associations/collection_proxy.rb +1 -2
  14. data/lib/active_record/associations/has_many_association.rb +0 -1
  15. data/lib/active_record/associations/join_dependency.rb +13 -0
  16. data/lib/active_record/associations/join_dependency/join_association.rb +1 -1
  17. data/lib/active_record/associations/preloader.rb +2 -3
  18. data/lib/active_record/attribute_assignment.rb +0 -1
  19. data/lib/active_record/attribute_decorators.rb +0 -2
  20. data/lib/active_record/attribute_methods/before_type_cast.rb +0 -1
  21. data/lib/active_record/attribute_methods/dirty.rb +2 -2
  22. data/lib/active_record/attribute_methods/primary_key.rb +0 -2
  23. data/lib/active_record/attribute_methods/read.rb +0 -1
  24. data/lib/active_record/attribute_methods/serialization.rb +0 -1
  25. data/lib/active_record/attribute_methods/time_zone_conversion.rb +0 -2
  26. data/lib/active_record/attribute_methods/write.rb +0 -1
  27. data/lib/active_record/attributes.rb +0 -1
  28. data/lib/active_record/autosave_association.rb +8 -6
  29. data/lib/active_record/callbacks.rb +1 -2
  30. data/lib/active_record/coders/yaml_column.rb +0 -1
  31. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +14 -7
  32. data/lib/active_record/connection_adapters/abstract/database_statements.rb +21 -15
  33. data/lib/active_record/connection_adapters/abstract/query_cache.rb +2 -2
  34. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +1 -2
  35. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +27 -27
  36. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +47 -30
  37. data/lib/active_record/connection_adapters/abstract/transaction.rb +4 -5
  38. data/lib/active_record/connection_adapters/abstract_adapter.rb +23 -8
  39. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +25 -32
  40. data/lib/active_record/connection_adapters/connection_specification.rb +2 -3
  41. data/lib/active_record/connection_adapters/mysql/column.rb +1 -1
  42. data/lib/active_record/connection_adapters/mysql/database_statements.rb +8 -12
  43. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +0 -1
  44. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +1 -2
  45. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +8 -8
  46. data/lib/active_record/connection_adapters/mysql2_adapter.rb +0 -1
  47. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +9 -3
  48. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +0 -1
  49. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +0 -1
  50. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +0 -1
  51. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +0 -1
  52. data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +1 -1
  53. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +0 -1
  54. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +0 -1
  55. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +1 -1
  56. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +0 -1
  57. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +1 -1
  58. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +2 -2
  59. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +1 -1
  60. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +0 -1
  61. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +15 -29
  62. data/lib/active_record/connection_adapters/postgresql/utils.rb +0 -1
  63. data/lib/active_record/connection_adapters/postgresql_adapter.rb +9 -2
  64. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +8 -7
  65. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +0 -1
  66. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +3 -3
  67. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +12 -7
  68. data/lib/active_record/connection_adapters/statement_pool.rb +0 -1
  69. data/lib/active_record/connection_handling.rb +13 -22
  70. data/lib/active_record/core.rb +8 -6
  71. data/lib/active_record/counter_cache.rb +4 -1
  72. data/lib/active_record/database_configurations/url_config.rb +0 -1
  73. data/lib/active_record/dynamic_matchers.rb +2 -3
  74. data/lib/active_record/explain.rb +0 -1
  75. data/lib/active_record/fixture_set/table_row.rb +0 -1
  76. data/lib/active_record/fixture_set/table_rows.rb +0 -1
  77. data/lib/active_record/fixtures.rb +0 -3
  78. data/lib/active_record/gem_version.rb +1 -1
  79. data/lib/active_record/inheritance.rb +0 -3
  80. data/lib/active_record/insert_all.rb +4 -4
  81. data/lib/active_record/internal_metadata.rb +1 -1
  82. data/lib/active_record/locking/optimistic.rb +0 -1
  83. data/lib/active_record/log_subscriber.rb +1 -1
  84. data/lib/active_record/middleware/database_selector.rb +0 -1
  85. data/lib/active_record/middleware/database_selector/resolver.rb +9 -14
  86. data/lib/active_record/migration.rb +4 -4
  87. data/lib/active_record/migration/command_recorder.rb +6 -18
  88. data/lib/active_record/migration/compatibility.rb +3 -3
  89. data/lib/active_record/migration/join_table.rb +0 -1
  90. data/lib/active_record/model_schema.rb +3 -2
  91. data/lib/active_record/nested_attributes.rb +0 -2
  92. data/lib/active_record/no_touching.rb +2 -2
  93. data/lib/active_record/null_relation.rb +0 -1
  94. data/lib/active_record/persistence.rb +4 -5
  95. data/lib/active_record/querying.rb +1 -1
  96. data/lib/active_record/railtie.rb +1 -1
  97. data/lib/active_record/railties/collection_cache_association_loading.rb +1 -1
  98. data/lib/active_record/railties/databases.rake +3 -0
  99. data/lib/active_record/reflection.rb +8 -8
  100. data/lib/active_record/relation.rb +13 -1
  101. data/lib/active_record/relation/batches.rb +0 -1
  102. data/lib/active_record/relation/calculations.rb +1 -1
  103. data/lib/active_record/relation/delegation.rb +7 -6
  104. data/lib/active_record/relation/finder_methods.rb +10 -2
  105. data/lib/active_record/relation/from_clause.rb +4 -0
  106. data/lib/active_record/relation/merger.rb +0 -1
  107. data/lib/active_record/relation/predicate_builder.rb +1 -5
  108. data/lib/active_record/relation/query_methods.rb +37 -12
  109. data/lib/active_record/relation/spawn_methods.rb +0 -1
  110. data/lib/active_record/relation/where_clause.rb +0 -1
  111. data/lib/active_record/result.rb +0 -1
  112. data/lib/active_record/schema_migration.rb +1 -1
  113. data/lib/active_record/scoping.rb +0 -1
  114. data/lib/active_record/scoping/default.rb +0 -1
  115. data/lib/active_record/scoping/named.rb +3 -3
  116. data/lib/active_record/store.rb +1 -1
  117. data/lib/active_record/suppressor.rb +2 -2
  118. data/lib/active_record/table_metadata.rb +16 -1
  119. data/lib/active_record/tasks/mysql_database_tasks.rb +0 -1
  120. data/lib/active_record/tasks/postgresql_database_tasks.rb +0 -1
  121. data/lib/active_record/tasks/sqlite_database_tasks.rb +0 -1
  122. data/lib/active_record/test_fixtures.rb +2 -1
  123. data/lib/active_record/timestamp.rb +0 -1
  124. data/lib/active_record/touch_later.rb +1 -2
  125. data/lib/active_record/transactions.rb +9 -9
  126. data/lib/active_record/type.rb +0 -1
  127. data/lib/active_record/type/adapter_specific_registry.rb +2 -5
  128. data/lib/active_record/type/hash_lookup_type_map.rb +0 -1
  129. data/lib/active_record/type/serialized.rb +0 -1
  130. data/lib/active_record/type/type_map.rb +0 -1
  131. data/lib/active_record/type/unsigned_integer.rb +0 -1
  132. data/lib/active_record/validations.rb +2 -3
  133. data/lib/active_record/validations/associated.rb +1 -2
  134. data/lib/arel.rb +17 -6
  135. data/lib/arel/predications.rb +5 -6
  136. data/lib/arel/visitors/depth_first.rb +0 -1
  137. data/lib/arel/visitors/dot.rb +0 -1
  138. data/lib/arel/visitors/mssql.rb +0 -1
  139. data/lib/arel/visitors/oracle.rb +1 -2
  140. data/lib/arel/visitors/oracle12.rb +0 -1
  141. data/lib/arel/visitors/postgresql.rb +0 -1
  142. data/lib/arel/visitors/sqlite.rb +0 -1
  143. data/lib/arel/visitors/to_sql.rb +0 -1
  144. data/lib/arel/visitors/visitor.rb +0 -1
  145. data/lib/arel/visitors/where_sql.rb +0 -1
  146. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +0 -1
  147. data/lib/rails/generators/active_record/migration.rb +0 -1
  148. data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +1 -1
  149. data/lib/rails/generators/active_record/model/model_generator.rb +0 -1
  150. metadata +13 -9
@@ -292,7 +292,7 @@ module ActiveRecord
292
292
  #
293
293
  # See also TableDefinition#column for details on how to create columns.
294
294
  def create_table(table_name, **options)
295
- td = create_table_definition(table_name, options)
295
+ td = create_table_definition(table_name, **options)
296
296
 
297
297
  if options[:id] != false && !options[:as]
298
298
  pk = options.fetch(:primary_key) do
@@ -302,14 +302,14 @@ module ActiveRecord
302
302
  if pk.is_a?(Array)
303
303
  td.primary_keys pk
304
304
  else
305
- td.primary_key pk, options.fetch(:id, :primary_key), options.except(:comment)
305
+ td.primary_key pk, options.fetch(:id, :primary_key), **options.except(:comment)
306
306
  end
307
307
  end
308
308
 
309
309
  yield td if block_given?
310
310
 
311
311
  if options[:force]
312
- drop_table(table_name, options.merge(if_exists: true))
312
+ drop_table(table_name, **options, if_exists: true)
313
313
  end
314
314
 
315
315
  result = execute schema_creation.accept td
@@ -378,9 +378,9 @@ module ActiveRecord
378
378
 
379
379
  t1_ref, t2_ref = [table_1, table_2].map { |t| t.to_s.singularize }
380
380
 
381
- create_table(join_table_name, options.merge!(id: false)) do |td|
382
- td.references t1_ref, column_options
383
- td.references t2_ref, column_options
381
+ create_table(join_table_name, **options.merge!(id: false)) do |td|
382
+ td.references t1_ref, **column_options
383
+ td.references t2_ref, **column_options
384
384
  yield td if block_given?
385
385
  end
386
386
  end
@@ -391,7 +391,7 @@ module ActiveRecord
391
391
  # Although this command ignores the block if one is given, it can be helpful
392
392
  # to provide one in a migration's +change+ method so it can be reverted.
393
393
  # In that case, the block will be used by #create_join_table.
394
- def drop_join_table(table_1, table_2, options = {})
394
+ def drop_join_table(table_1, table_2, **options)
395
395
  join_table_name = find_join_table_name(table_1, table_2, options)
396
396
  drop_table(join_table_name)
397
397
  end
@@ -468,7 +468,7 @@ module ActiveRecord
468
468
  # end
469
469
  #
470
470
  # See also Table for details on all of the various column transformations.
471
- def change_table(table_name, options = {})
471
+ def change_table(table_name, **options)
472
472
  if supports_bulk_alter? && options[:bulk]
473
473
  recorder = ActiveRecord::Migration::CommandRecorder.new(self)
474
474
  yield update_table_definition(table_name, recorder)
@@ -498,7 +498,7 @@ module ActiveRecord
498
498
  # Although this command ignores most +options+ and the block if one is given,
499
499
  # it can be helpful to provide these in a migration's +change+ method so it can be reverted.
500
500
  # In that case, +options+ and the block will be used by #create_table.
501
- def drop_table(table_name, options = {})
501
+ def drop_table(table_name, **options)
502
502
  execute "DROP TABLE#{' IF EXISTS' if options[:if_exists]} #{quote_table_name(table_name)}"
503
503
  end
504
504
 
@@ -587,7 +587,7 @@ module ActiveRecord
587
587
  # # ALTER TABLE "shapes" ADD "triangle" polygon
588
588
  def add_column(table_name, column_name, type, **options)
589
589
  at = create_alter_table table_name
590
- at.add_column(column_name, type, options)
590
+ at.add_column(column_name, type, **options)
591
591
  execute schema_creation.accept at
592
592
  end
593
593
 
@@ -610,8 +610,8 @@ module ActiveRecord
610
610
  # to provide these in a migration's +change+ method so it can be reverted.
611
611
  # In that case, +type+ and +options+ will be used by #add_column.
612
612
  # Indexes on the column are automatically removed.
613
- def remove_column(table_name, column_name, type = nil, options = {})
614
- execute "ALTER TABLE #{quote_table_name(table_name)} #{remove_column_for_alter(table_name, column_name, type, options)}"
613
+ def remove_column(table_name, column_name, type = nil, **options)
614
+ execute "ALTER TABLE #{quote_table_name(table_name)} #{remove_column_for_alter(table_name, column_name, type, **options)}"
615
615
  end
616
616
 
617
617
  # Changes the column's definition according to the new options.
@@ -783,7 +783,7 @@ module ActiveRecord
783
783
  #
784
784
  # For more information see the {"Transactional Migrations" section}[rdoc-ref:Migration].
785
785
  def add_index(table_name, column_name, options = {})
786
- index_name, index_type, index_columns, index_options = add_index_options(table_name, column_name, options)
786
+ index_name, index_type, index_columns, index_options = add_index_options(table_name, column_name, **options)
787
787
  execute "CREATE #{index_type} INDEX #{quote_column_name(index_name)} ON #{quote_table_name(table_name)} (#{index_columns})#{index_options}"
788
788
  end
789
789
 
@@ -902,7 +902,7 @@ module ActiveRecord
902
902
  # add_reference(:products, :supplier, foreign_key: {to_table: :firms})
903
903
  #
904
904
  def add_reference(table_name, ref_name, **options)
905
- ReferenceDefinition.new(ref_name, options).add_to(update_table_definition(table_name, self))
905
+ ReferenceDefinition.new(ref_name, **options).add_to(update_table_definition(table_name, self))
906
906
  end
907
907
  alias :add_belongs_to :add_reference
908
908
 
@@ -930,7 +930,7 @@ module ActiveRecord
930
930
  foreign_key_options = { to_table: reference_name }
931
931
  end
932
932
  foreign_key_options[:column] ||= "#{ref_name}_id"
933
- remove_foreign_key(table_name, foreign_key_options)
933
+ remove_foreign_key(table_name, **foreign_key_options)
934
934
  end
935
935
 
936
936
  remove_column(table_name, "#{ref_name}_id")
@@ -988,7 +988,7 @@ module ActiveRecord
988
988
  # Action that happens <tt>ON UPDATE</tt>. Valid values are +:nullify+, +:cascade+ and +:restrict+
989
989
  # [<tt>:validate</tt>]
990
990
  # (PostgreSQL only) Specify whether or not the constraint should be validated. Defaults to +true+.
991
- def add_foreign_key(from_table, to_table, options = {})
991
+ def add_foreign_key(from_table, to_table, **options)
992
992
  return unless supports_foreign_keys?
993
993
 
994
994
  options = foreign_key_options(from_table, to_table, options)
@@ -1145,22 +1145,22 @@ module ActiveRecord
1145
1145
  #
1146
1146
  # add_timestamps(:suppliers, null: true)
1147
1147
  #
1148
- def add_timestamps(table_name, options = {})
1148
+ def add_timestamps(table_name, **options)
1149
1149
  options[:null] = false if options[:null].nil?
1150
1150
 
1151
1151
  if !options.key?(:precision) && supports_datetime_with_precision?
1152
1152
  options[:precision] = 6
1153
1153
  end
1154
1154
 
1155
- add_column table_name, :created_at, :datetime, options
1156
- add_column table_name, :updated_at, :datetime, options
1155
+ add_column table_name, :created_at, :datetime, **options
1156
+ add_column table_name, :updated_at, :datetime, **options
1157
1157
  end
1158
1158
 
1159
1159
  # Removes the timestamp columns (+created_at+ and +updated_at+) from the table definition.
1160
1160
  #
1161
1161
  # remove_timestamps(:suppliers)
1162
1162
  #
1163
- def remove_timestamps(table_name, options = {})
1163
+ def remove_timestamps(table_name, **options)
1164
1164
  remove_column table_name, :updated_at
1165
1165
  remove_column table_name, :created_at
1166
1166
  end
@@ -1196,7 +1196,7 @@ module ActiveRecord
1196
1196
  if data_source_exists?(table_name) && index_name_exists?(table_name, index_name)
1197
1197
  raise ArgumentError, "Index name '#{index_name}' on table '#{table_name}' already exists"
1198
1198
  end
1199
- index_columns = quoted_columns_for_index(column_names, options).join(", ")
1199
+ index_columns = quoted_columns_for_index(column_names, **options).join(", ")
1200
1200
 
1201
1201
  [index_name, index_type, index_columns, index_options, algorithm, using, comment]
1202
1202
  end
@@ -1253,7 +1253,7 @@ module ActiveRecord
1253
1253
  # the PostgreSQL adapter for supporting operator classes.
1254
1254
  def add_options_for_index_columns(quoted_columns, **options)
1255
1255
  if supports_index_sort_order?
1256
- quoted_columns = add_index_sort_order(quoted_columns, options)
1256
+ quoted_columns = add_index_sort_order(quoted_columns, **options)
1257
1257
  end
1258
1258
 
1259
1259
  quoted_columns
@@ -1263,7 +1263,7 @@ module ActiveRecord
1263
1263
  return [column_names] if column_names.is_a?(String)
1264
1264
 
1265
1265
  quoted_columns = Hash[column_names.map { |name| [name.to_sym, quote_column_name(name).dup] }]
1266
- add_options_for_index_columns(quoted_columns, options).values
1266
+ add_options_for_index_columns(quoted_columns, **options).values
1267
1267
  end
1268
1268
 
1269
1269
  def index_name_for_remove(table_name, options = {})
@@ -1322,8 +1322,8 @@ module ActiveRecord
1322
1322
  SchemaCreation.new(self)
1323
1323
  end
1324
1324
 
1325
- def create_table_definition(*args)
1326
- TableDefinition.new(self, *args)
1325
+ def create_table_definition(*args, **options)
1326
+ TableDefinition.new(self, *args, **options)
1327
1327
  end
1328
1328
 
1329
1329
  def create_alter_table(name)
@@ -1374,7 +1374,7 @@ module ActiveRecord
1374
1374
 
1375
1375
  def foreign_key_for(from_table, **options)
1376
1376
  return unless supports_foreign_keys?
1377
- foreign_keys(from_table).detect { |fk| fk.defined_for?(options) }
1377
+ foreign_keys(from_table).detect { |fk| fk.defined_for?(**options) }
1378
1378
  end
1379
1379
 
1380
1380
  def foreign_key_for!(from_table, to_table: nil, **options)
@@ -1436,20 +1436,37 @@ module ActiveRecord
1436
1436
  non_combinable_operations.each(&:call)
1437
1437
  end
1438
1438
 
1439
- def add_column_for_alter(table_name, column_name, type, options = {})
1439
+ def add_column_for_alter(table_name, column_name, type, **options)
1440
1440
  td = create_table_definition(table_name)
1441
- cd = td.new_column_definition(column_name, type, options)
1441
+ cd = td.new_column_definition(column_name, type, **options)
1442
1442
  schema_creation.accept(AddColumnDefinition.new(cd))
1443
1443
  end
1444
1444
 
1445
- def remove_column_for_alter(table_name, column_name, type = nil, options = {})
1445
+ def remove_column_for_alter(table_name, column_name, type = nil, **options)
1446
1446
  "DROP COLUMN #{quote_column_name(column_name)}"
1447
1447
  end
1448
1448
 
1449
- def remove_columns_for_alter(table_name, *column_names)
1449
+ def remove_columns_for_alter(table_name, *column_names, **options)
1450
1450
  column_names.map { |column_name| remove_column_for_alter(table_name, column_name) }
1451
1451
  end
1452
1452
 
1453
+ def add_timestamps_for_alter(table_name, **options)
1454
+ options[:null] = false if options[:null].nil?
1455
+
1456
+ if !options.key?(:precision) && supports_datetime_with_precision?
1457
+ options[:precision] = 6
1458
+ end
1459
+
1460
+ [
1461
+ add_column_for_alter(table_name, :created_at, :datetime, **options),
1462
+ add_column_for_alter(table_name, :updated_at, :datetime, **options)
1463
+ ]
1464
+ end
1465
+
1466
+ def remove_timestamps_for_alter(table_name, **options)
1467
+ remove_columns_for_alter(table_name, :updated_at, :created_at)
1468
+ end
1469
+
1453
1470
  def insert_versions_sql(versions)
1454
1471
  sm_table = quote_table_name(schema_migration.table_name)
1455
1472
 
@@ -98,7 +98,7 @@ module ActiveRecord
98
98
  end
99
99
 
100
100
  def rollback_records
101
- ite = records.uniq(&:object_id)
101
+ ite = records.uniq(&:__id__)
102
102
  already_run_callbacks = {}
103
103
  while record = ite.shift
104
104
  trigger_callbacks = record.trigger_transactional_callbacks?
@@ -117,7 +117,7 @@ module ActiveRecord
117
117
  end
118
118
 
119
119
  def commit_records
120
- ite = records.uniq(&:object_id)
120
+ ite = records.uniq(&:__id__)
121
121
  already_run_callbacks = {}
122
122
  while record = ite.shift
123
123
  if @run_commit_callbacks
@@ -141,8 +141,8 @@ module ActiveRecord
141
141
  end
142
142
 
143
143
  class SavepointTransaction < Transaction
144
- def initialize(connection, savepoint_name, parent_transaction, *args)
145
- super(connection, *args)
144
+ def initialize(connection, savepoint_name, parent_transaction, *args, **options)
145
+ super(connection, *args, **options)
146
146
 
147
147
  parent_transaction.state.add_child(@state)
148
148
 
@@ -309,7 +309,6 @@ module ActiveRecord
309
309
  end
310
310
 
311
311
  private
312
-
313
312
  NULL_TRANSACTION = NullTransaction.new
314
313
 
315
314
  # Deallocate invalidated prepared statements outside of the transaction
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "set"
3
4
  require "active_record/connection_adapters/determine_if_preparable_visitor"
4
5
  require "active_record/connection_adapters/schema_cache"
5
6
  require "active_record/connection_adapters/sql_type_metadata"
@@ -11,7 +12,6 @@ require "arel/collectors/bind"
11
12
  require "arel/collectors/composite"
12
13
  require "arel/collectors/sql_string"
13
14
  require "arel/collectors/substitute_binds"
14
- require "concurrent/atomic/thread_local_var"
15
15
 
16
16
  module ActiveRecord
17
17
  module ConnectionAdapters # :nodoc:
@@ -77,6 +77,7 @@ module ActiveRecord
77
77
  include Savepoints
78
78
 
79
79
  SIMPLE_INT = /\A\d+\z/
80
+ COMMENT_REGEX = %r{/\*(?:[^\*]|\*[^/])*\*/}m
80
81
 
81
82
  attr_accessor :pool
82
83
  attr_reader :visitor, :owner, :logger, :lock
@@ -103,8 +104,8 @@ module ActiveRecord
103
104
  end
104
105
 
105
106
  def self.build_read_query_regexp(*parts) # :nodoc:
106
- parts = parts.map { |part| /\A[\(\s]*#{part}/i }
107
- Regexp.union(*parts)
107
+ parts = parts.map { |part| /#{part}/i }
108
+ /\A(?:[\(\s]|#{COMMENT_REGEX})*#{Regexp.union(*parts)}/
108
109
  end
109
110
 
110
111
  def self.quoted_column_names # :nodoc:
@@ -130,10 +131,10 @@ module ActiveRecord
130
131
  @lock = ActiveSupport::Concurrency::LoadInterlockAwareMonitor.new
131
132
 
132
133
  if self.class.type_cast_config_to_boolean(config.fetch(:prepared_statements) { true })
133
- @prepared_statement_status = Concurrent::ThreadLocalVar.new(true)
134
+ @prepared_statements = true
134
135
  @visitor.extend(DetermineIfPreparableVisitor)
135
136
  else
136
- @prepared_statement_status = Concurrent::ThreadLocalVar.new(false)
137
+ @prepared_statements = false
137
138
  end
138
139
 
139
140
  @advisory_locks_enabled = self.class.type_cast_config_to_boolean(
@@ -177,7 +178,11 @@ module ActiveRecord
177
178
  end
178
179
 
179
180
  def prepared_statements
180
- @prepared_statement_status.value
181
+ @prepared_statements && !prepared_statements_disabled_cache.include?(object_id)
182
+ end
183
+
184
+ def prepared_statements_disabled_cache # :nodoc:
185
+ Thread.current[:ar_prepared_statements_disabled_cache] ||= Set.new
181
186
  end
182
187
 
183
188
  class Version
@@ -264,7 +269,10 @@ module ActiveRecord
264
269
  end
265
270
 
266
271
  def unprepared_statement
267
- @prepared_statement_status.bind(false) { yield }
272
+ cache = prepared_statements_disabled_cache.add(object_id) if @prepared_statements
273
+ yield
274
+ ensure
275
+ cache&.delete(object_id)
268
276
  end
269
277
 
270
278
  # Returns the human-readable name of the adapter. Use mixed case - one
@@ -305,6 +313,10 @@ module ActiveRecord
305
313
  false
306
314
  end
307
315
 
316
+ def supports_partitioned_indexes?
317
+ false
318
+ end
319
+
308
320
  # Does this adapter support index sort order?
309
321
  def supports_index_sort_order?
310
322
  false
@@ -409,6 +421,10 @@ module ActiveRecord
409
421
  false
410
422
  end
411
423
 
424
+ def supports_common_table_expressions?
425
+ false
426
+ end
427
+
412
428
  def supports_lazy_transactions?
413
429
  false
414
430
  end
@@ -609,7 +625,6 @@ module ActiveRecord
609
625
  end
610
626
 
611
627
  private
612
-
613
628
  def type_map
614
629
  @type_map ||= Type::TypeMap.new.tap do |mapping|
615
630
  initialize_type_map(mapping)
@@ -45,7 +45,6 @@ module ActiveRecord
45
45
 
46
46
  class StatementPool < ConnectionAdapters::StatementPool # :nodoc:
47
47
  private
48
-
49
48
  def dealloc(stmt)
50
49
  stmt.close
51
50
  end
@@ -110,6 +109,14 @@ module ActiveRecord
110
109
  !mariadb? && database_version >= "5.7.7"
111
110
  end
112
111
 
112
+ def supports_common_table_expressions?
113
+ if mariadb?
114
+ database_version >= "10.2.1"
115
+ else
116
+ database_version >= "8.0.1"
117
+ end
118
+ end
119
+
113
120
  def supports_advisory_locks?
114
121
  true
115
122
  end
@@ -359,7 +366,7 @@ module ActiveRecord
359
366
  end
360
367
 
361
368
  def add_index(table_name, column_name, options = {}) #:nodoc:
362
- index_name, index_type, index_columns, _, index_algorithm, index_using, comment = add_index_options(table_name, column_name, options)
369
+ index_name, index_type, index_columns, _, index_algorithm, index_using, comment = add_index_options(table_name, column_name, **options)
363
370
  sql = +"CREATE #{index_type} INDEX #{quote_column_name(index_name)} #{index_using} ON #{quote_table_name(table_name)} (#{index_columns}) #{index_algorithm}"
364
371
  execute add_sql_comment!(sql, comment)
365
372
  end
@@ -411,12 +418,13 @@ module ActiveRecord
411
418
  create_table_info = create_table_info(table_name)
412
419
 
413
420
  # strip create_definitions and partition_options
414
- raw_table_options = create_table_info.sub(/\A.*\n\) /m, "").sub(/\n\/\*!.*\*\/\n\z/m, "").strip
421
+ # Be aware that `create_table_info` might not include any table options due to `NO_TABLE_OPTIONS` sql mode.
422
+ raw_table_options = create_table_info.sub(/\A.*\n\) ?/m, "").sub(/\n\/\*!.*\*\/\n\z/m, "").strip
415
423
 
416
424
  # strip AUTO_INCREMENT
417
425
  raw_table_options.sub!(/(ENGINE=\w+)(?: AUTO_INCREMENT=\d+)/, '\1')
418
426
 
419
- table_options[:options] = raw_table_options
427
+ table_options[:options] = raw_table_options unless raw_table_options.blank?
420
428
 
421
429
  # strip COMMENT
422
430
  if raw_table_options.sub!(/ COMMENT='.+'/, "")
@@ -440,11 +448,11 @@ module ActiveRecord
440
448
 
441
449
  query_values(<<~SQL, "SCHEMA")
442
450
  SELECT column_name
443
- FROM information_schema.key_column_usage
444
- WHERE constraint_name = 'PRIMARY'
451
+ FROM information_schema.statistics
452
+ WHERE index_name = 'PRIMARY'
445
453
  AND table_schema = #{scope[:schema]}
446
454
  AND table_name = #{scope[:name]}
447
- ORDER BY ordinal_position
455
+ ORDER BY seq_in_index
448
456
  SQL
449
457
  end
450
458
 
@@ -485,7 +493,7 @@ module ActiveRecord
485
493
  def columns_for_distinct(columns, orders) # :nodoc:
486
494
  order_columns = orders.reject(&:blank?).map { |s|
487
495
  # Convert Arel node to string
488
- s = s.to_sql unless s.is_a?(String)
496
+ s = visitor.compile(s) unless s.is_a?(String)
489
497
  # Remove any ASC/DESC modifiers
490
498
  s.gsub(/\s+(?:ASC|DESC)\b/i, "")
491
499
  }.reject(&:blank?).map.with_index { |column, i| "#{column} AS alias_#{i}" }
@@ -522,7 +530,6 @@ module ActiveRecord
522
530
  end
523
531
 
524
532
  private
525
-
526
533
  def initialize_type_map(m = type_map)
527
534
  super
528
535
 
@@ -562,12 +569,12 @@ module ActiveRecord
562
569
  end
563
570
  end
564
571
 
565
- def register_integer_type(mapping, key, options)
572
+ def register_integer_type(mapping, key, **options)
566
573
  mapping.register_type(key) do |sql_type|
567
574
  if /\bunsigned\b/.match?(sql_type)
568
- Type::UnsignedInteger.new(options)
575
+ Type::UnsignedInteger.new(**options)
569
576
  else
570
- Type::Integer.new(options)
577
+ Type::Integer.new(**options)
571
578
  end
572
579
  end
573
580
  end
@@ -581,6 +588,7 @@ module ActiveRecord
581
588
  end
582
589
 
583
590
  # See https://dev.mysql.com/doc/refman/5.7/en/error-messages-server.html
591
+ ER_FILSORT_ABORT = 1028
584
592
  ER_DUP_ENTRY = 1062
585
593
  ER_NOT_NULL_VIOLATION = 1048
586
594
  ER_NO_REFERENCED_ROW = 1216
@@ -622,7 +630,7 @@ module ActiveRecord
622
630
  Deadlocked.new(message, sql: sql, binds: binds)
623
631
  when ER_LOCK_WAIT_TIMEOUT
624
632
  LockWaitTimeout.new(message, sql: sql, binds: binds)
625
- when ER_QUERY_TIMEOUT
633
+ when ER_QUERY_TIMEOUT, ER_FILSORT_ABORT
626
634
  StatementTimeout.new(message, sql: sql, binds: binds)
627
635
  when ER_QUERY_INTERRUPTED
628
636
  QueryCanceled.new(message, sql: sql, binds: binds)
@@ -648,7 +656,7 @@ module ActiveRecord
648
656
  end
649
657
 
650
658
  td = create_table_definition(table_name)
651
- cd = td.new_column_definition(column.name, type, options)
659
+ cd = td.new_column_definition(column.name, type, **options)
652
660
  schema_creation.accept(ChangeColumnDefinition.new(cd, column.name))
653
661
  end
654
662
 
@@ -662,12 +670,12 @@ module ActiveRecord
662
670
 
663
671
  current_type = exec_query("SHOW COLUMNS FROM #{quote_table_name(table_name)} LIKE #{quote(column_name)}", "SCHEMA").first["Type"]
664
672
  td = create_table_definition(table_name)
665
- cd = td.new_column_definition(new_column_name, current_type, options)
673
+ cd = td.new_column_definition(new_column_name, current_type, **options)
666
674
  schema_creation.accept(ChangeColumnDefinition.new(cd, column.name))
667
675
  end
668
676
 
669
677
  def add_index_for_alter(table_name, column_name, options = {})
670
- index_name, index_type, index_columns, _, index_algorithm, index_using = add_index_options(table_name, column_name, options)
678
+ index_name, index_type, index_columns, _, index_algorithm, index_using = add_index_options(table_name, column_name, **options)
671
679
  index_algorithm[0, 0] = ", " if index_algorithm.present?
672
680
  "ADD #{index_type} INDEX #{quote_column_name(index_name)} #{index_using} (#{index_columns})#{index_algorithm}"
673
681
  end
@@ -677,20 +685,6 @@ module ActiveRecord
677
685
  "DROP INDEX #{quote_column_name(index_name)}"
678
686
  end
679
687
 
680
- def add_timestamps_for_alter(table_name, options = {})
681
- options[:null] = false if options[:null].nil?
682
-
683
- if !options.key?(:precision) && supports_datetime_with_precision?
684
- options[:precision] = 6
685
- end
686
-
687
- [add_column_for_alter(table_name, :created_at, :datetime, options), add_column_for_alter(table_name, :updated_at, :datetime, options)]
688
- end
689
-
690
- def remove_timestamps_for_alter(table_name, options = {})
691
- [remove_column_for_alter(table_name, :updated_at), remove_column_for_alter(table_name, :created_at)]
692
- end
693
-
694
688
  def supports_rename_index?
695
689
  mariadb? ? false : database_version >= "5.7.6"
696
690
  end
@@ -787,7 +781,7 @@ module ActiveRecord
787
781
  options[:primary_key_column] = column_for(match[:target_table], match[:primary_key])
788
782
  end
789
783
 
790
- MismatchedForeignKey.new(options)
784
+ MismatchedForeignKey.new(**options)
791
785
  end
792
786
 
793
787
  def version_string(full_version_string)
@@ -804,7 +798,6 @@ module ActiveRecord
804
798
  end
805
799
 
806
800
  private
807
-
808
801
  def cast_value(value)
809
802
  case value
810
803
  when true then "1"