I am in an existing Postgres 14 database that has the following Operators and Functions in place that augment an '=' or 'LIKE' query to leverage 'lower()' (thus allowing the query to take advantage of Indexes). This is allowing us to do case-insensitive queries without having to directly include 'lower()' in the query.
-- ------------ CREATE FUNCTIONS -----------
CREATE OR REPLACE FUNCTION ci_caseinsmatch(varchar, varchar) RETURNS boolean
AS $$
SELECT LOWER($1)::text = LOWER($2)::text;
$$
LANGUAGE sql
IMMUTABLE STRICT;
CREATE FUNCTION ci_like(varchar, varchar) RETURNS boolean
AS $$
SELECT LOWER($1)::text LIKE LOWER($2)::text;
$$
LANGUAGE sql;
-- ------------ CREATE OPERATORS -----------
CREATE OPERATOR = (
PROCEDURE = ci_caseinsmatch,
LEFTARG = varchar,
RIGHTARG = varchar,
COMMUTATOR = =,
NEGATOR = <>
);
CREATE OPERATOR ~~(
PROCEDURE = ci_like,
LEFTARG = varchar,
RIGHTARG = varchar,
RESTRICT = likesel,
JOIN = likejoinsel);
(That code courtesy of postgresonline)
With the proper indexes in place, this gets us the ability to do fast case-insensitive searches like
select * from packages where a_varchar_column='Bd1261d5-6e47-481f-a7e2-6f54c88dd8eb';
or
select * from packages where a_varchar_column LIKE 'Bd1261d5-6e47-481f-a7e2-6f54c88dd8eb';
any time we're comparing VARCHAR's, without worrying about the casing of characters, or having to interject lower() in to the queries manually.
Now I want to extend that capability to IN queries, like this
select * from packages where a_varchar_column IN ('b8fec092-fdea-4c1f-bf30-7f4124da660e', 'ae7a78f3-d419-4361-95c9-9254f1c76da2')
But IN (which translates to =AND) is not an Operator. So I can't CREATE OPERATOR IN nor CREATE OPERATOR =AND.
So the underlying question is, can I interject a function any time an '=AND' construct is called, and how do I set up that trigger ?
In this case it happens to be desired when we have a varchar on the left that we want forced to lower(), but that's already handled by the Function.
I know for certain that if my app were using lower() like this
select * from packages where lower(a_varchar_column) IN ('b8fec092-fdea-4c1f-bf30-7f4124da660e', 'ae7a78f3-d419-4361-95c9-9254f1c76da2')
that the query is fast and takes advantage of our Indexes. But I'm trying to have the database do that on the applications behalf.