Errors
Trino

Trino: How to configure Presto searches to be case-insensitive?

Ты пишешь запрос в Trino к MySQL, где `name = 'Adam'` должен вернуть строку с `'adam'`. Но возвращается пустота. Или `LIKE '%a%'` ловит только строчную `a`, про

Ты пишешь запрос в Trino к MySQL, где name = 'Adam' должен вернуть строку с 'adam'. Но возвращается пустота. Или LIKE '%a%' ловит только строчную a, пропуская Alan. Знакомо?

Ты проверяешь — да, MySQL точно case-insensitive. Но Trino упорно сравнивает по-честному. В чём подвох?

Почему Trino не наследует нечувствительность к регистру

Trino — не прокси. Это распределённый SQL-движок. Он строит план запроса, и часто сам выполняет его части, а не просто пересылает сырой запрос в источник.

Соединитель (connector) читает метаданные из БД (названия таблиц, колонок, типы), но семантика операций — это уже зона ответственности Trino. Сравнение строк — одна из таких операций.

Если бы поведение зависело от каждой СУБД, то результаты одного запроса к разным источникам в федеративном запросе стали бы непредсказуемыми. Поэтому Trino по умолчанию следует стандарту SQL: сравнение строк — регистрозависимая операция.

Это касается и оператора =, и LIKE. Поэтому твой запрос where name = 'Adam' ищет точное совпадение, включая регистр.

Что делать? Явное приведение

Ответ — нормализация. Приводи сравниваемые значения к одному регистру явно, используя lower() или upper().

select * from table where lower(name) like '%a%';

Теперь 'a' в шаблоне и lower(name) оба в нижнем регистре. Запрос вернёт и adam, и Alan.

Для точного сравнения — тот же принцип:

select * from table where lower(name) = lower('Adam');

Теперь 'adam' и 'Adam' после lower() станут 'adam' и найдут друг друга.

А если не хочется оборачивать каждый столбец в lower()?

Придётся. Волшебной настройки в config.properties соединителя для глобального case-insensitive поиска нет. Можно было бы мечтать о параметре типа case-insensitive-name-matching=true, но его нет.

Можно создать view в MySQL, где заранее приведены все текстовые поля, и подключаться к нему. Или использовать вычисляемые колонки, если источник поддерживает. Но это костыли.

Правильный путь — признать, что Trino работает со своими строгими правилами, и явно указывать нужную логику в запросе. Это делает код переносимым и предсказуемым.

Итог

MySQL case-insensitive, а Trino — нет. Это не баг, а архитектурная особенность. Запрос планируется и частично выполняется в Trino, который следует стандарту SQL.

Решение всегда одно: lower(column) = lower(value). Пиши так сразу, и не будет сюрпризов. И да, это немного раздражает, но зато точно.