From 010a4a6e5f8bf79fe549c3227e9e3e9e567eff1a Mon Sep 17 00:00:00 2001 From: Daniel Alfaro Date: Mon, 29 Mar 2021 10:43:53 -0700 Subject: [PATCH] Add support for check_constraints with the same name on different tables - MariaDB allows the use of the same check_constraint name as long as it is on a different table. This is done by adding a new column to the information_schema.check_constraints table with name table_name. --- .../abstract_mysql_adapter.rb | 5 +++- activerecord/test/cases/helper.rb | 9 +++++++ .../cases/migration/check_constraint_test.rb | 25 +++++++++++++++++++ 3 files changed, 38 insertions(+), 1 deletion(-) diff --git a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb index 0a53b298fd..637358807c 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb @@ -427,7 +427,7 @@ module ActiveRecord if supports_check_constraints? scope = quoted_scope(table_name) - chk_info = exec_query(<<~SQL, "SCHEMA") + sql = <<~SQL SELECT cc.constraint_name AS 'name', cc.check_clause AS 'expression' FROM information_schema.check_constraints cc @@ -437,6 +437,9 @@ module ActiveRecord AND tc.table_name = #{scope[:name]} AND cc.constraint_schema = #{scope[:schema]} SQL + sql += " AND cc.table_name = #{scope[:name]}" if mariadb? + + chk_info = exec_query(sql, "SCHEMA") chk_info.map do |row| options = { diff --git a/activerecord/test/cases/helper.rb b/activerecord/test/cases/helper.rb index 48c7409bcc..31e3bfc07a 100644 --- a/activerecord/test/cases/helper.rb +++ b/activerecord/test/cases/helper.rb @@ -54,6 +54,15 @@ def supports_default_expression? end end +def supports_non_unique_constraint_name? + if current_adapter?(:Mysql2Adapter) + conn = ActiveRecord::Base.connection + conn.mariadb? + else + false + end +end + %w[ supports_savepoints? supports_partial_index? diff --git a/activerecord/test/cases/migration/check_constraint_test.rb b/activerecord/test/cases/migration/check_constraint_test.rb index 7ce8c7f781..153c994a8f 100644 --- a/activerecord/test/cases/migration/check_constraint_test.rb +++ b/activerecord/test/cases/migration/check_constraint_test.rb @@ -18,10 +18,16 @@ if ActiveRecord::Base.connection.supports_check_constraints? t.integer :price t.integer :quantity end + + @connection.create_table "purchases", force: true do |t| + t.integer :price + t.integer :quantity + end end teardown do @connection.drop_table "trades", if_exists: true rescue nil + @connection.drop_table "purchases", if_exists: true rescue nil end def test_check_constraints @@ -56,6 +62,25 @@ if ActiveRecord::Base.connection.supports_check_constraints? end end + if supports_non_unique_constraint_name? + def test_add_constraint_with_same_name_to_different_table + @connection.add_check_constraint :trades, "quantity > 0", name: "greater_than_zero" + @connection.add_check_constraint :purchases, "quantity > 0", name: "greater_than_zero" + + trades_check_constraints = @connection.check_constraints("trades") + assert_equal 1, trades_check_constraints.size + trade_constraint = trades_check_constraints.first + assert_equal "trades", trade_constraint.table_name + assert_equal "greater_than_zero", trade_constraint.name + + purchases_check_constraints = @connection.check_constraints("purchases") + assert_equal 1, purchases_check_constraints.size + purchase_constraint = purchases_check_constraints.first + assert_equal "purchases", purchase_constraint.table_name + assert_equal "greater_than_zero", purchase_constraint.name + end + end + def test_add_check_constraint_with_non_existent_table_raises e = assert_raises(ActiveRecord::StatementInvalid) do @connection.add_check_constraint :refunds, "quantity > 0", name: "quantity_check"