-
Notifications
You must be signed in to change notification settings - Fork 34
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Case insensitive uniqueness validation does not work for MySQL #38
Comments
I have a potential fix which works for MySQL, and I can make it a pull request if you want, but I wasn't sure how it may affect PostgreSQL and others, given that schema_validations doesn't seem to use schema_plus_columns' The fix is to def has_case_insensitive_index?(column, scope)
+ if column.respond_to?(:case_sensitive?) && ! column.case_sensitive?
+ return true
+ end
indexed_columns = (scope + [column.name]).map(&:to_sym).sort
index = column.indexes.select { |i| i.unique && i.columns.map(&:to_sym).sort == indexed_columns }.first
index && index.respond_to?(:case_sensitive?) && !index.case_sensitive?
end |
@dmeranda thanks for the detailed info. I think you're dead on. I don't think your change would break anything, but of course the way to find out is to push it and see if the test suite fails. My only additional thoughts are:
|
Yes, your points are reasonable. I'm actually investigating schema_plus_columns now to see how or why it is working for me, and if it perhaps warrants a patch too. I can start working on a pull request. |
cool, thanks for looking into it |
Regarding schema_plus_columns, it is working beacause it is using schema_monkey to patch the So when you get an instance of So it just happens to work, accidentally, at least under Rails 4. Though the documentation for schema_plus_columns could probably be updated to say that the method By the way, if I temporarily rename the |
I'm not sure if this issue belongs here or in schema_plus_columns, or both.
Using schema_validations 2.1.1, Rails 4.2.6, and with MySQL 5.7.
Unlike PostgreSQL, in MySQL it is the columns themselves that determine if they are case-sensitive or insensitive, and is not a property of any index. Fortunately the standard Rails mysql connection adapter already defines a
case_sensitive?
method on the AR Column class which works correctly. However the auto-generated validation methods by this gem seem to treat all columns as being case-sensitive.Say you have a MySQL table defined like the following: I'm showing the raw MySQL schema so you can see the
COLLATE
qualifiers; wherefield1
is case-insensitive (*_ci
) andfield2
is case-sensitive (*_bin
):Now in rails you can introspect the properties of these two columns. Notice that
case_sensitive?
returns the expected value — (I don't know what this doesn't conflict withschema_plus_column
's similarly named method, which would fail because MySQL's Index class doesn't supportcase_sensitive?
)But now if you create a couple records only differing in case the validation checks don't catch the case-insensitive match and pass the insert on to MySQL, which raises a uniqueness constraint violation.
The debug output of the auto-generated validators is:
The text was updated successfully, but these errors were encountered: