Skip to content

Commit

Permalink
Merge pull request #42429 from Flixt/fix-mysql-check-constraints-quoting
Browse files Browse the repository at this point in the history
Fix duplicate escaping of quotes for check constraint expressions in MySQL schema
  • Loading branch information
rafaelfranca committed Sep 26, 2023
2 parents dcc6ad5 + 468d3d0 commit dc56140
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 0 deletions.
9 changes: 9 additions & 0 deletions activerecord/CHANGELOG.md
@@ -1,3 +1,12 @@
* Fix duplicate quoting for check constraint expressions in schema dump when using MySQL

A check constraint with an expression, that already contains quotes, lead to an invalid schema
dump with the mysql2 adapter.

Fixes #42424.

*Felix Tscheulin*

* Performance tune the SQLite3 adapter connection configuration

For Rails applications, the Write-Ahead-Log in normal syncing mode with a capped journal size, a healthy shared memory buffer and a shared cache will perform, on average, 2× better.
Expand Down
Expand Up @@ -531,6 +531,13 @@ def check_constraints(table_name)
expression = row["expression"]
expression = expression[1..-2] if expression.start_with?("(") && expression.end_with?(")")
expression = strip_whitespace_characters(expression)

unless mariadb?
# MySQL returns check constraints expression in an already escaped form.
# This leads to duplicate escaping later (e.g. when the expression is used in the SchemaDumper).
expression = expression.gsub("\\'", "'")
end

CheckConstraintDefinition.new(table_name, expression, options)
end
else
Expand Down
@@ -0,0 +1,35 @@
# frozen_string_literal: true

require "cases/helper"
require "support/schema_dumping_helper"

if ActiveRecord::Base.connection.supports_check_constraints?
class Mysql2CheckConstraintQuotingTest < ActiveRecord::Mysql2TestCase
include SchemaDumpingHelper

setup do
@connection = ActiveRecord::Base.connection
@connection.create_table "trades", force: true do |t|
t.string :name
end
end

teardown do
@connection.drop_table "trades", if_exists: true rescue nil
end

def test_check_constraint_no_duplicate_expression_quoting
@connection.add_check_constraint :trades, "name != 'forbidden_string'"

check_constraints = @connection.check_constraints("trades")
assert_equal 1, check_constraints.size

expression = check_constraints.first.expression
if ActiveRecord::Base.connection.mariadb?
assert_equal "`name` <> 'forbidden_string'", expression
else
assert_equal "`name` <> _utf8mb4'forbidden_string'", expression
end
end
end
end

0 comments on commit dc56140

Please sign in to comment.