# frozen_string_literal: true require "cases/helper" require "support/schema_dumping_helper" if ActiveRecord::Base.connection.supports_check_constraints? module ActiveRecord class Migration class CheckConstraintTest < ActiveRecord::TestCase include SchemaDumpingHelper class Trade < ActiveRecord::Base end setup do @connection = ActiveRecord::Base.connection @connection.create_table "trades", force: true do |t| t.integer :price t.integer :quantity end end teardown do @connection.drop_table "trades", if_exists: true rescue nil end def test_check_constraints check_constraints = @connection.check_constraints("products") assert_equal 1, check_constraints.size constraint = check_constraints.first assert_equal "products", constraint.table_name assert_equal "products_price_check", constraint.name if current_adapter?(:Mysql2Adapter) assert_equal "`price` > `discounted_price`", constraint.expression else assert_equal "price > discounted_price", constraint.expression end end def test_add_check_constraint @connection.add_check_constraint :trades, "quantity > 0" check_constraints = @connection.check_constraints("trades") assert_equal 1, check_constraints.size constraint = check_constraints.first assert_equal "trades", constraint.table_name assert_equal "chk_rails_2189e9f96c", constraint.name if current_adapter?(:Mysql2Adapter) assert_equal "`quantity` > 0", constraint.expression else assert_equal "quantity > 0", constraint.expression 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" end assert_match(/refunds/, e.message) end def test_added_check_constraint_ensures_valid_values @connection.add_check_constraint :trades, "quantity > 0", name: "quantity_check" assert_raises(ActiveRecord::StatementInvalid) do Trade.create(quantity: -1) end end if ActiveRecord::Base.connection.supports_validate_constraints? def test_not_valid_check_constraint Trade.create(quantity: -1) @connection.add_check_constraint :trades, "quantity > 0", name: "quantity_check", validate: false assert_raises(ActiveRecord::StatementInvalid) do Trade.create(quantity: -1) end end def test_validate_check_constraint_by_name @connection.add_check_constraint :trades, "quantity > 0", name: "quantity_check", validate: false assert_not_predicate @connection.check_constraints("trades").first, :validated? @connection.validate_check_constraint :trades, name: "quantity_check" assert_predicate @connection.check_constraints("trades").first, :validated? end def test_validate_non_existing_check_constraint_raises assert_raises ArgumentError do @connection.validate_check_constraint :trades, name: "quantity_check" end end else # Check constraint should still be created, but should not be invalid def test_add_invalid_check_constraint @connection.add_check_constraint :trades, "quantity > 0", name: "quantity_check", validate: false check_constraints = @connection.check_constraints("trades") assert_equal 1, check_constraints.size cc = check_constraints.first assert_predicate cc, :validated? end end def test_remove_check_constraint @connection.add_check_constraint :trades, "price > 0", name: "price_check" @connection.add_check_constraint :trades, "quantity > 0", name: "quantity_check" assert_equal 2, @connection.check_constraints("trades").size @connection.remove_check_constraint :trades, name: "quantity_check" assert_equal 1, @connection.check_constraints("trades").size constraint = @connection.check_constraints("trades").first assert_equal "trades", constraint.table_name assert_equal "price_check", constraint.name if current_adapter?(:Mysql2Adapter) assert_equal "`price` > 0", constraint.expression else assert_equal "price > 0", constraint.expression end end def test_remove_non_existing_check_constraint assert_raises(ArgumentError) do @connection.remove_check_constraint :trades, name: "nonexistent" end end end end end else module ActiveRecord class Migration class NoForeignKeySupportTest < ActiveRecord::TestCase setup do @connection = ActiveRecord::Base.connection end def test_add_check_constraint_should_be_noop @connection.add_check_constraint :products, "discounted_price > 0", name: "discounted_price_check" end def test_remove_check_constraint_should_be_noop @connection.remove_check_constraint :products, name: "price_check" end def test_check_constraints_should_raise_not_implemented assert_raises(NotImplementedError) do @connection.check_constraints("products") end end end end end end