Skip to content

Commit a51e967

Browse files
authored
Merge pull request rails#46592 from pirj/dont-use-lower-for-case-insensitive-queries-on-citext
Don't use lower() for citext columns
2 parents c6b227b + 61464b0 commit a51e967

File tree

3 files changed

+19
-1
lines changed

3 files changed

+19
-1
lines changed

activerecord/CHANGELOG.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
1+
* Stop using `LOWER()` for case-insensitive queries on `citext` columns
2+
3+
Previously, `LOWER()` was added for e.g. uniqueness validations with
4+
`case_sensitive: false`.
5+
It wasn't mentioned in the documentation that the index without `LOWER()`
6+
wouldn't be used in this case.
7+
8+
*Phil Pirozhkov*
9+
110
* Extract `#sync_timezone_changes` method in AbstractMysqlAdapter to enable subclasses
211
to sync database timezone changes without overriding `#raw_execute`.
312

activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1031,7 +1031,10 @@ def build_statement_pool
10311031
end
10321032

10331033
def can_perform_case_insensitive_comparison_for?(column)
1034-
@case_insensitive_cache ||= {}
1034+
# NOTE: citext is an exception. It is possible to perform a
1035+
# case-insensitive comparison using `LOWER()`, but it is
1036+
# unnecessary, as `citext` is case-insensitive by definition.
1037+
@case_insensitive_cache ||= { "citext" => false }
10351038
@case_insensitive_cache.fetch(column.sql_type) do
10361039
@case_insensitive_cache[column.sql_type] = begin
10371040
sql = <<~SQL

activerecord/test/cases/adapters/postgresql/citext_test.rb

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,12 @@ def test_select_case_insensitive
7171
assert_equal "Cased Text", x.cival
7272
end
7373

74+
def test_case_insensitiveness
75+
attr = Citext.arel_table[:cival]
76+
comparison = @connection.case_insensitive_comparison(attr, nil)
77+
assert_no_match(/lower/i, comparison.to_sql)
78+
end
79+
7480
def test_schema_dump_with_shorthand
7581
output = dump_table_schema("citexts")
7682
assert_match %r[t\.citext "cival"], output

0 commit comments

Comments
 (0)