InterBase: тормозология и глюконавтика
Страница 25. Как это будет по-русски


 

Как это будет по-русски

Известно, что вся компьютерная отрасль развивается под жёстким давлением американского шовинизма. То есть эти буржуи проектируют все свои продукты в предположении, что ихняя Америка - единственная страна на Земле. Потом иногда спохватываются (в лучшем случае) и добавляют функции поддержки национальных кодировок, но поскольку добавление происходит задним числом, практически всегда получается криво. Причём поддержка тех стран, в которых продукт продаётся, сделана ещё хоть как-то культурно. Над остальными же просто издеваются.

InterBase в этом смысле - не исключение. То есть зачатки национальной поддержки в стиле SQL92 наблюдаются. В частности, имеются понятия набора символов (character set) и сравнения (collation), в системных метаданных предусмотрено хранение их параметров. Вот только операторов create/drop character set, create/drop collation нет. Честно говоря, я их кроме как в стандарте SQL нигде больше и не видел. А жаль.

То, что реализовано, так же удобством не отличается. Приходится каждый раз при создании БД или подключении через Interactive SQL тыкать InterBase носом в правильные настройки.

В целом национальная поддержка оперирует двумя понятиями:

  • Набор символов определяет, какие буквы и прочие символы можно хранить в строках данной кодировки.
  • Последовательность сравнения определяет, какие символы в данном наборе являются большими, а какие меньшими. Для одного набора символов может сущесвтовать несколько сравнений, например заглавные и строчные буквы в одном сравнении считаются равными, а в другом - нет.
Более конкретно в InterBase имеется:
  • Кодовые страницы CYRL (кириллица в кодировке ДОС) и WIN1251 (в кодировке Windows). Не смотря на поддержку Unix, нет ни КОИ8, ни хотя бы ISO8859-5, что довольно странно.
  • Сравнения DB_RUS, PDOX_CYRL, CYRL для кодировки CYRL (не вникал в различия, так как никогда не приходилось пользоваться) и  PXW_CYRL, WIN1251 для кодировки WIN1251.

Если указать кодировку без сравнения, то по умолчанию установится сравнение, одноимённое с кодировкой. А одноимённые сравнения практически всегда сравнивают строки с учётом регистра, обеспечивая лишь примитивную алфавитную сортировку. Более полезные сравнения, игнорирующие регистр и правильно сортирующие строки со смешанным верхним/нижним регистром называются по-другому. Причём если установить кодировку по умолчанию для базы ещё можно, то последовательность сравнения - нет. Хотя, как обычно, существует обходной и очень ненадёжный манёвр с метаданными.

Если же не указать кодировку по умолчанию вообще, то установится NONE, то есть отсутствие какого-либо слежения за байтами, помещаемыми в строки. При всей своей примитивности - достаточно опасная вещь. В строки с такой кодировкой можно записать хоть русский, хоть какой-либо другой текст.

Но вот корректно его сравнить (буква "Ё" практически во всех кодовых таблицах стоит отдельно от остального алфавита) или преобразовать в верхний регистр уже не удастся. И преобразовать в другую кодировку внутри InterBase - тоже! Ведь InterBase ничего не знает о том, какие символы хранятся в кодировке NONE. Один путь - вытащить строки на клиента, а потом загнать обратно в сервер. Так что такую опасность надо учитывать и принимать меры заранее. Другой - применить UDF.

Всё дальнейшее изложение будет идти с ориентацией на кодировку Windows. На самом деле для ДОСа никаких существенных отличий нет (кроме идентификаторов).

И так, первым делом надо создать БД с правильной кодировкой по умолчанию. Делается это путём дописывания в конец оператора create database следующей опции: default character set win1251. Далее надо все поля с русским текстом объявлять как collate PXW_CYRL. Везде, где воспринимается collate.

Альтернативный способ состоит в обновлении метаданных, которое нужно проделывать после каждого перебэкапа. Это плохо, потому что ко всему ещё и опасно, но зато может сработать на уже существующей базе.

И так, надо назначить данной кодировке правильную последовательность сравнения по умолчанию. InterBase в этом отношении злопамятен, так что если сначала создать таблицу со строковыми полями, а затем поменять сравнение, то на ранее созданные поля это не подействует. В общем, данная установка умолчания делается парой операторов:

update RDB$CHARACTER_SETS

  set RDB$DEFAULT_COLLATE_NAME = 'PXW_CYRL'

  where RDB$CHARACTER_SET_NAME like 'WIN1251%'

;

commit work

;
После этого можно приступать к созданию таблиц и прочих вещей - строки будут корректно сравниваться и сортироваться без учёта регистра. Существующие поля можно исправить через RDB$FIELDS и RDB$RELATION_FIELDS.

Остаётся поговорить о настройке клиента. Обычно это сводится главным образом к настройке BDE, о котором немного ниже, но мелких пакостей добавляет и Interactive SQL. Последний никогда не запоминает кодовую страницу, в которой работает клиент и никогда не пытается её опознать автоматически (что так же возможно практически всегда). Вместо этого в качестве кодировки устанавливается NONE со всеми её "приятностями".

Что же касается BDE, то здесь правильный русский драйвер называется AnCyrr на диске и PDOX ANSI Cyrillic в интерактивных настройках. При инициализации соединения с базой BDE использует драйвера в следующем порядке:

  • Предполагается, что клиент работает в кодировке, соответствующей языковому драйверу по умолчанию в системе.
  • Для определения кодировки строк в БД первым делом используется языковый драйвер, настроенный в алиасе
  • Если алиаса нет, или в нём языковый драйвер не указан, используется языковый драйвер для драйвера БД (в нашем случае - для InterBase)
  • Если и для драйвера БД языковый драйвер не указан, используется драйвер по умолчанию для системы.

В общем, наилучший способ - сразу же после установки BDE пройтись по всем настройкам и везде, где упоминается языковый драйвер настроить PDOX ANSI Cyrillic. Рай от этого не наступит, но проблемы сведутся к минимуму.

 
« Предыдущая статья