Skip to content

Commit ae0dd06

Browse files
authored
Merge pull request rails#53232 from kamipo/extract_drop_constraint
Extract `remove_constraint` for SQL standard `DROP CONSTRAINT` syntax
2 parents 1ce87cf + bc613e2 commit ae0dd06

File tree

10 files changed

+56
-38
lines changed

10 files changed

+56
-38
lines changed

activerecord/lib/active_record/connection_adapters/abstract/schema_creation.rb

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ def visit_AlterTable(o)
2828
sql << o.foreign_key_drops.map { |fk| visit_DropForeignKey fk }.join(" ")
2929
sql << o.check_constraint_adds.map { |con| visit_AddCheckConstraint con }.join(" ")
3030
sql << o.check_constraint_drops.map { |con| visit_DropCheckConstraint con }.join(" ")
31+
sql << o.constraint_drops.map { |con| visit_DropConstraint con }.join(" ")
3132
end
3233

3334
def visit_ColumnDefinition(o)
@@ -96,9 +97,11 @@ def visit_AddForeignKey(o)
9697
"ADD #{accept(o)}"
9798
end
9899

99-
def visit_DropForeignKey(name)
100+
def visit_DropConstraint(name)
100101
"DROP CONSTRAINT #{quote_column_name(name)}"
101102
end
103+
alias :visit_DropForeignKey :visit_DropConstraint
104+
alias :visit_DropCheckConstraint :visit_DropConstraint
102105

103106
def visit_CreateIndexDefinition(o)
104107
index = o.index
@@ -127,10 +130,6 @@ def visit_AddCheckConstraint(o)
127130
"ADD #{accept(o)}"
128131
end
129132

130-
def visit_DropCheckConstraint(name)
131-
"DROP CONSTRAINT #{quote_column_name(name)}"
132-
end
133-
134133
def quoted_columns(o)
135134
String === o.columns ? o.columns : quoted_columns_for_index(o.columns, o.column_options)
136135
end

activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
# frozen_string_literal: true
22

3-
43
module ActiveRecord
54
module ConnectionAdapters # :nodoc:
65
# Abstract representation of an index definition on a table. Instances of
@@ -622,6 +621,7 @@ class AlterTable # :nodoc:
622621
attr_reader :adds
623622
attr_reader :foreign_key_adds, :foreign_key_drops
624623
attr_reader :check_constraint_adds, :check_constraint_drops
624+
attr_reader :constraint_drops
625625

626626
def initialize(td)
627627
@td = td
@@ -630,6 +630,7 @@ def initialize(td)
630630
@foreign_key_drops = []
631631
@check_constraint_adds = []
632632
@check_constraint_drops = []
633+
@constraint_drops = []
633634
end
634635

635636
def name; @td.name; end
@@ -650,6 +651,10 @@ def drop_check_constraint(constraint_name)
650651
@check_constraint_drops << constraint_name
651652
end
652653

654+
def drop_constraint(constraint_name)
655+
@constraint_drops << constraint_name
656+
end
657+
653658
def add_column(name, type, **options)
654659
name = name.to_s
655660
type = type.to_sym

activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1334,7 +1334,6 @@ def remove_check_constraint(table_name, expression = nil, if_exists: false, **op
13341334
execute schema_creation.accept(at)
13351335
end
13361336

1337-
13381337
# Checks to see if a check constraint exists on a table for a given check constraint definition.
13391338
#
13401339
# check_constraint_exists?(:products, name: "price_check")
@@ -1346,6 +1345,13 @@ def check_constraint_exists?(table_name, **options)
13461345
check_constraint_for(table_name, **options).present?
13471346
end
13481347

1348+
def remove_constraint(table_name, constraint_name) # :nodoc:
1349+
at = create_alter_table(table_name)
1350+
at.drop_constraint(constraint_name)
1351+
1352+
execute schema_creation.accept(at)
1353+
end
1354+
13491355
def dump_schema_information # :nodoc:
13501356
versions = pool.schema_migration.versions
13511357
insert_versions_sql(versions) if versions.any?

activerecord/lib/active_record/connection_adapters/postgresql/schema_creation.rb

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,7 @@ def visit_AlterTable(o)
1111
sql = super
1212
sql << o.constraint_validations.map { |fk| visit_ValidateConstraint fk }.join(" ")
1313
sql << o.exclusion_constraint_adds.map { |con| visit_AddExclusionConstraint con }.join(" ")
14-
sql << o.exclusion_constraint_drops.map { |con| visit_DropExclusionConstraint con }.join(" ")
1514
sql << o.unique_constraint_adds.map { |con| visit_AddUniqueConstraint con }.join(" ")
16-
sql << o.unique_constraint_drops.map { |con| visit_DropUniqueConstraint con }.join(" ")
1715
end
1816

1917
def visit_AddForeignKey(o)
@@ -72,18 +70,10 @@ def visit_AddExclusionConstraint(o)
7270
"ADD #{accept(o)}"
7371
end
7472

75-
def visit_DropExclusionConstraint(name)
76-
"DROP CONSTRAINT #{quote_column_name(name)}"
77-
end
78-
7973
def visit_AddUniqueConstraint(o)
8074
"ADD #{accept(o)}"
8175
end
8276

83-
def visit_DropUniqueConstraint(name)
84-
"DROP CONSTRAINT #{quote_column_name(name)}"
85-
end
86-
8777
def visit_ChangeColumnDefinition(o)
8878
column = o.column
8979
column.sql_type = type_to_sql(column.type, **column.options)

activerecord/lib/active_record/connection_adapters/postgresql/schema_definitions.rb

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -356,15 +356,13 @@ def validate_check_constraint(*args)
356356

357357
# = Active Record PostgreSQL Adapter Alter \Table
358358
class AlterTable < ActiveRecord::ConnectionAdapters::AlterTable
359-
attr_reader :constraint_validations, :exclusion_constraint_adds, :exclusion_constraint_drops, :unique_constraint_adds, :unique_constraint_drops
359+
attr_reader :constraint_validations, :exclusion_constraint_adds, :unique_constraint_adds
360360

361361
def initialize(td)
362362
super
363363
@constraint_validations = []
364364
@exclusion_constraint_adds = []
365-
@exclusion_constraint_drops = []
366365
@unique_constraint_adds = []
367-
@unique_constraint_drops = []
368366
end
369367

370368
def validate_constraint(name)
@@ -375,17 +373,9 @@ def add_exclusion_constraint(expression, options)
375373
@exclusion_constraint_adds << @td.new_exclusion_constraint_definition(expression, options)
376374
end
377375

378-
def drop_exclusion_constraint(constraint_name)
379-
@exclusion_constraint_drops << constraint_name
380-
end
381-
382376
def add_unique_constraint(column_name, options)
383377
@unique_constraint_adds << @td.new_unique_constraint_definition(column_name, options)
384378
end
385-
386-
def drop_unique_constraint(unique_constraint_name)
387-
@unique_constraint_drops << unique_constraint_name
388-
end
389379
end
390380
end
391381
end

activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -764,10 +764,7 @@ def exclusion_constraint_options(table_name, expression, options) # :nodoc:
764764
def remove_exclusion_constraint(table_name, expression = nil, **options)
765765
excl_name_to_delete = exclusion_constraint_for!(table_name, expression: expression, **options).name
766766

767-
at = create_alter_table(table_name)
768-
at.drop_exclusion_constraint(excl_name_to_delete)
769-
770-
execute schema_creation.accept(at)
767+
remove_constraint(table_name, excl_name_to_delete)
771768
end
772769

773770
# Adds a new unique constraint to the table.
@@ -819,10 +816,7 @@ def unique_constraint_options(table_name, column_name, options) # :nodoc:
819816
def remove_unique_constraint(table_name, column_name = nil, **options)
820817
unique_name_to_delete = unique_constraint_for!(table_name, column: column_name, **options).name
821818

822-
at = create_alter_table(table_name)
823-
at.drop_unique_constraint(unique_name_to_delete)
824-
825-
execute schema_creation.accept(at)
819+
remove_constraint(table_name, unique_name_to_delete)
826820
end
827821

828822
# Maps logical Rails types to PostgreSQL-specific data types.

activerecord/test/cases/migration/check_constraint_test.rb

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,16 @@ def test_check_constraint_exists_ensures_required_options
242242
assert_equal "At least one of :name or :expression must be supplied", error.message
243243
end
244244

245+
if supports_sql_standard_drop_constraint?
246+
def test_remove_constraint
247+
@connection.add_check_constraint :trades, "quantity > 0", name: "quantity_check"
248+
249+
assert_equal 1, @connection.check_constraints("trades").size
250+
@connection.remove_constraint :trades, "quantity_check"
251+
assert_equal 0, @connection.check_constraints("trades").size
252+
end
253+
end
254+
245255
def test_remove_check_constraint
246256
@connection.add_check_constraint :trades, "price > 0", name: "price_check"
247257
@connection.add_check_constraint :trades, "quantity > 0", name: "quantity_check"
@@ -313,7 +323,7 @@ def test_remove_constraint_from_change_table_with_options
313323
else
314324
module ActiveRecord
315325
class Migration
316-
class NoForeignKeySupportTest < ActiveRecord::TestCase
326+
class NoCheckConstraintSupportTest < ActiveRecord::TestCase
317327
setup do
318328
@connection = ActiveRecord::Base.lease_connection
319329
end

activerecord/test/cases/migration/foreign_key_test.rb

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -380,6 +380,16 @@ def test_foreign_key_exists_in_change_table
380380
end
381381
end
382382

383+
if supports_sql_standard_drop_constraint?
384+
def test_remove_constraint
385+
@connection.add_foreign_key :astronauts, :rockets, column: "rocket_id", name: "fancy_named_fk"
386+
387+
assert_equal 1, @connection.foreign_keys("astronauts").size
388+
@connection.remove_constraint :astronauts, "fancy_named_fk"
389+
assert_equal [], @connection.foreign_keys("astronauts")
390+
end
391+
end
392+
383393
def test_remove_foreign_key_inferes_column
384394
@connection.add_foreign_key :astronauts, :rockets
385395

activerecord/test/cases/test_case.rb

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -324,7 +324,6 @@ def self.run(*args)
324324
end
325325
end
326326

327-
328327
class SQLite3TestCase < TestCase
329328
def self.run(*args)
330329
super if current_adapter?(:SQLite3Adapter)

activerecord/test/support/adapter_helper.rb

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,21 @@ def supports_text_column_with_default?
4848
end
4949
end
5050

51+
def supports_sql_standard_drop_constraint?
52+
if current_adapter?(:SQLite3Adapter)
53+
false
54+
elsif current_adapter?(:Mysql2Adapter, :TrilogyAdapter)
55+
conn = ActiveRecord::Base.lease_connection
56+
if conn.mariadb?
57+
conn.database_version >= "10.3.13"
58+
else
59+
conn.database_version >= "8.0.19"
60+
end
61+
else
62+
true
63+
end
64+
end
65+
5166
%w[
5267
supports_savepoints?
5368
supports_partial_index?

0 commit comments

Comments
 (0)