Lighthouse has a new layout. Prefer the old one? Return to the old layout, and switch back any time from the link at the top of each page.

This project is archived and is in readonly mode.

validates_uniqueness_of unicode aware field length

#2653

If I have a validates_uniqueness_of column with limit 50 and set it to:

ᏈᏉᏊᏈᏉᏊᏈᏉᏊᏈᏉᏊᏈᏉᏊᏈᏉᏊᏈᏉᏊᏈᏉᏊᏈᏉᏊᏈᏉᏊᏈᏉᏊᏈᏉᏊᏈᏉᏊᏈᏉᏊᏈᏉᏊᏈᏉᏊᏈᏉ

rails incorrectly runs a check for anything existing where that column equals

ᏈᏉᏊᏈᏉᏊᏈᏉᏊᏈᏉᏊᏈᏉᏊᏈ?

The problem is in validates_uniqueness_of string concatenation (implemented in #1042)

http://github.com/rails/rails/blob/b6bac73b282c7e500c43810f2a937fc0...

value = column.limit ? value.to_s[0, column.limit] : value.to_s

should be changed to

value = column.limit ? value.to_s.mb_chars[0, column.limit].to_s : value.to_s

NOTE: also to reproduce you must have set encoding: utf8 in database.yml, and your database table must be "convert to character set utf8"

Reported by Jacob Burkhart · May 15th, 2009 @ 06:27 PM

State: committed
Milestone: 2.3.4
Assigned to: Jeremy Kemper Jeremy Kemper
Importance: none

Activity

  1. CancelProfileIsBroken
  2. Elise Huard
    Elise Huard

    there seems to be a problem indeed - the validates_uniqueness select statement doesn't seem to work with utf8
    so verified with mysql
    I get outright errors with postgresql, while the encoding is UTF8 and so should work.
    linked to 2883 i think

    added tests, and i'll now look for a fix

    August 8th, 2009 @ 03:02 PM

  3. Elise Huard
    Elise Huard

    sorry about the lack of punctuation, there were line breaks in there.

    August 8th, 2009 @ 03:03 PM

  4. Elise Huard
    Elise Huard

    well, i updated the patch: this fix works for postgresql and sqlite3, still not for mysql though.

    August 8th, 2009 @ 04:17 PM

  5. Elise Huard
    Elise Huard

    and now a clean patch.

    August 8th, 2009 @ 10:41 PM

  6. Elise Huard
  7. Pratik
    Pratik
    • Assigned user set to Jeremy Kemper

    August 8th, 2009 @ 10:48 PM

  8. Jeremy Kemper
    Jeremy Kemper
    • Milestone changed from 2.x to 2.3.4

    Nice fix, +1. Needs rebase against master.

    August 9th, 2009 @ 03:27 AM

  9. Elise Huard
  10. Rizwan Reza
    Rizwan Reza

    not reproducible

    -1 The patch fails on master.

    Created an event whose title, with limit taken into account, is not unique.
    <false> is not true.
    

    August 9th, 2009 @ 03:51 PM

  11. Elad Meidar
    Elad Meidar

    -1 Patch applies on master but fails test, i was unable to trace the generated SQL in the tests log to see what is really going on. Since mb_chars[x,x] is obviously working, i suspect the DB is the one to blame. (MySQL)

      1) Failure:
    test_validate_uniqueness_with_limit_and_utf8(UniquenessValidationTest)
        [./test/cases/validations/uniqueness_validation_test.rb:246:in `test_validate_uniqueness_with_limit_and_utf8'
         ./test/cases/../../lib/active_record/test_case.rb:57:in `with_kcode'
         ./test/cases/validations/uniqueness_validation_test.rb:241:in `test_validate_uniqueness_with_limit_and_utf8'
         ./test/cases/../../lib/../../activemodel/lib/../../activesupport/lib/active_support/testing/setup_and_teardown.rb:62:in `__send__'
         ./test/cases/../../lib/../../activemodel/lib/../../activesupport/lib/active_support/testing/setup_and_teardown.rb:62:in `run']:
    Created an event whose title, with limit taken into account, is not unique.
    <false> is not true.
    

    August 9th, 2009 @ 05:18 PM

  12. Elise Huard
    Elise Huard

    exactly - it works for postgres and sqlite3, but not for mysql.

    August 9th, 2009 @ 08:10 PM

  13. Jeremy Kemper
    Jeremy Kemper

    Works for mysql if you regenerate your test dbs. Drop both dbs and recreate with rake mysql:build_databases. This corrects the default charset and collation.

    August 9th, 2009 @ 08:55 PM

  14. Repository
    Repository
    • State changed from new to committed

    (from [c5896bfd8432f6b7a1c6cb06486c5c85eafe9450]) validate uniqueness with limit in utf8

    [#2653 state:committed]

    Signed-off-by: Jeremy Kemper jeremy@bitsweat.net
    http://github.com/rails/rails/commit/c5896bfd8432f6b7a1c6cb06486c5c...

    August 9th, 2009 @ 08:55 PM

  15. Repository
  16. Jeremy Kemper
  17. Elise Huard
    Elise Huard

    I found what makes the test pass (and is also the condition for it to work for mysql: explicit utf8 encoding. I copied the little hack from another test.

    August 9th, 2009 @ 09:08 PM

  18. Jeremy Kemper
    Jeremy Kemper

    Elise, tests already pass for me on mysql. Why is this patch needed?

    August 9th, 2009 @ 10:32 PM

  19. Jeremy Kemper
    Jeremy Kemper

    (first do rake mysql:rebuild_databases to fix the old test database's charset and collation)

    August 9th, 2009 @ 10:34 PM

  20. Elise Huard
    Elise Huard

    Jeremy, i think your DB is properly configured (for utf8 encoding) - as you can see from Elad's comments (and mine), the mysql still failed, as opposed to the other db's.

    this patch checks for that, by doing a query and seeing if the select works properly. I use the same extra bit of code that is used in the test_validate_case_insensitive_uniqueness.

    It's a bit of a hack, but i tried different things, like removing the 'BINARY' = connection.case_sensitive_equality_operator for is_utf8? , but that resulted in collation errors in the mysql database, which seems to have LATIN_C1 encoding.

    August 9th, 2009 @ 10:39 PM

  21. Elise Huard
    Elise Huard

    aha, sorry, missed your comment. Ignore the patch then, sorry.

    August 9th, 2009 @ 10:45 PM

  22. Jeremy Kemper
    Jeremy Kemper

    Elise, this would be a useful bit of code for test/connections/native_mysql/connection.rb so we can fail fast and advise a database rebuild instead of leaving Rails testers with odd, unexplained test failures.

    August 10th, 2009 @ 05:48 AM