
Наконец-то пришлось столкнуться с кириллицей при налаживании веб-интерфейса к mysql. Ничего не предвещало приключений. Панголин из коробки, апач, перл, мускуль - тоже. Ну какие могут быть проблемы?
Ан-нет!
Сначала содержимое базы в utf8 (DEFAULT CHARSET=utf8 COLLATE=utf8_bin) вопросиками. Но при этом принтанутый перлом текст на русском прекрасно отображался. Решение нашлось довольно быстро: "mysql_enable_utf8=>1" в опциях при открытии базы.
Но после этого появились "Wide character in print ..." на каждое значение на русском. Надо напомнить что у меня use strict; и use warnings; (или -w в первой строке) стоят всегда принципиально и код вылизывается до последнего варнинга. Поиски помогли понять что в перле не всё так просто с поддержкой юникода. Оказывается, есть классические текстовые строки, которые состоят из однобайтовых символов, а есть символьные строки (юникодовые), которые могут состоять из многобайтовых символов. Там, внутри, разница между ними в специальном флаге.
Нашлись рекомендации заюзать прагму use utf8; - вообще ничего не изменилось. "Ага...", - подумалось: "... видимо юникод поддерживается по-умолчанию и эти фичи влючаются автоматичеки. Ведь текст русский отображается корректно!" Выключаем.
Предлагалось решение переключить поток (т.е. в нашем случае STDOUT) в соответствующий режим: binmode STDOUT, ":utf8";. И он действительно переключал его - ругательства исчезли! Но вот незадача: выводимый текст стал кракозябровым! Причём не весь, а только тот, что сформирован в самом пёрле!
Наваждение какое-то: опция при подключении к базе поволяет увидеть содержимое полей, но ругается широкими символами (что может в любой момент аукнуться). Без опции никак, значит нужно искать как работать с включенной опцией. binmode убрало ругательства на широкие символы (значит правильным путём идём?) но сломало русский текст в принтах. Внезапно пляски с бубном дали замечательный результат: именно с binmode ...,":utf8"; прагма use utf8; дала нужный результат. Из чего можно сделать вывод: прагма заставляет интерпретировать все текстовые строки, сформированные в перле, как юникодовые, одновременно устанавливая в них нужный флаг. Из базы данных при включенной опции текстовые строки получают собственные флаги и поэтому на них эти пляски не влияют. А binmode приводит выходной поток в нужный формат. Вопрос напрашивается: "А как же до этого выводилась кириллица?". Очень просто: перл работал с ней и выводил как простую последовательность однобайтовых символов, хотя тот же mc и показывает строки как юникодные. Потому что mc по-умолчанию их так воспринимает. Как последовательность однобайтовых символов эти строки видит и апач через CGI и ему не важно что там на самом деле. Принудительно выставленный charset=utf8 тупо сообщает браузеру как надо воспринимать поток. Теперь же прагма объясниля перлу что за строки у него и теперь он осознанно работает с уникодом. И выводит по бинмоду. И из базы вынимает по опции.
Теперь можно быть готовым к неожиданностям, когда придётся, например, регекспом чего-нибудь в кириллице делать.
Ах, да! На закуску ещё одна история. В эту базу пытаемся загружать данные, экспортированные из другой базы. Другая база - это interbase с дефаултовым 1251. Со старым перлом 5.8.8, в отличие от 5.14 о которой до сих пор шла речь.
Перловый скрипт (на старой системе) к этому времени уже успешно экспортировал данные в файл для импорта в новую базу, на лету перекодируя из 1251 в utf8. И файлы успешно пересылаются на новую систему (scp) и загружаются (пока ещё вручную) mysql. Напрашивается следующий шаг - загружать данные напрямую их одной системы в другую, уж коли один находятся в пределах видимости (коммуникационной) и на старой системе работа с mysql тоже возможна. Несколько штрихов - и данные скриптом из старой базы поехали в новую. Только, к сожалению, загруженные данные оказались кракозябровыми. И даже опция не помогла. Ещё несколько безуспешных гугленей и затем perldoc DBD::mysql наводит на мысль попробовать SET NAMES utf8; и это при том, что мануал читался на новой системе. И "о, чудо!" - скрипт "тёрся головой о мою ногу и мурлыкал" (а) А.Азимов. Контрольная проверка perldoc DBD::mysql на старой системе не нашла упоминания о mysql_enable_utf8;.
Теперь квестово-исследовательская работа завершена и продолжается творческо-исследоваельская. :)