The impetus for my question is that I had hoped that PostgreSQL would behave consistently when selecting from citext columns, regardless of whether or not the string to be matched is wrapped in one or more instances of lower() (any such wrapping is beyond my control). That appears not to be the case. (Of course, it is entirely possible that my tests are invalid or I am misunderstanding fundamental concepts.)
Steps to Reproduce Testing Scenario
CREATE EXTENSION IF NOT EXISTS citext;
CREATE TABLE users (id int, email citext);
INSERT INTO users(id, email) VALUES
(1, 'USER@example.com');
Tests
As expected when using the citext type, the lowercase variant yields a result:
# select * from users where email = 'user@example.com';
id | email
----+------------------
1 | USER@example.com
(1 row)
Changing the = operator to like yields a result:
select * from users where email like lower('user@example.com');
id | email
----+------------------
1 | USER@example.com
(1 row)
As does the "inverse":
# select * from users where lower(email) = 'user@example.com';
id | email
----+------------------
1 | USER@example.com
(1 row)
As does wrapping both values in lower():
# select * from users where lower(email) = lower('user@example.com');
id | email
----+------------------
1 | USER@example.com
(1 row)
My Question
Why then does the following query not return a result in this instance?
# select * from users where email = lower('user@example.com');
id | email
----+-------
(0 rows)
The manual says of the citext type:
Essentially, it internally calls lower when comparing values.
The operative word seems to be "essentially"; this statement implies the following, which does yield a result:
select * from users where lower(email) = lower(lower('user@example.com'));
id | email
----+------------------
1 | USER@example.com
(1 row)
Might this be related to the following caveat in the Limitations section of the above-cited document?
citext's case-folding behavior depends on the LC_CTYPE setting of your database.
# SHOW LC_CTYPE;
lc_ctype
-------------
en_US.UTF-8
(1 row)
Any explanation in this regard is much appreciated.