ODBC + MSSQL: проблема с кодировкой.

2,540 views
Skip to first unread message

begemot_sun

unread,
Nov 27, 2013, 5:40:50 AM11/27/13
to erlang-...@googlegroups.com


Работаю c MSSQL  ODBC (fretds).
База в cp1251 кодировке.

Заведен DSN:
[mssql]
host = *********
port = ****
tds verion = 7.0
client charset = UTF-8

Консоль в utf8 кодировке. Стандартные средства типа isql работают на ура и показывают текст как надо.
odbc в erlang возвращает вместо строк знаки вопроса (??????) по количеству символов в строке.
Пробовал опцию {binary_strings, on} - не помогает, возвращает <<"???????">>.

Как можно побороть данную проблему?



Dmitry Begunkov

unread,
Nov 29, 2013, 2:17:31 AM11/29/13
to erlang-...@googlegroups.com
ODBC freedts всегда возвращает только в utf-16, так что придется делать что то типа:  unicode:characters_to_binary(C, {utf16,little}, utf8)

среда, 27 ноября 2013 г., 14:40:50 UTC+4 пользователь begemot_sun написал:

Sergey Loguntsov

unread,
Nov 29, 2013, 11:25:32 AM11/29/13
to erlang-...@googlegroups.com
Спасибо, но вопрос был немного не в этом.

В общем, решилась проблема таким образом:
В настройках ODBC, там где прописывается DSN необходимо прописывать
Servername указывающий на секцию из freetds.conf, например в данном
случае такую:
[mssql]
client charset = UTF-8
tds verion = 7.0

Данная секция указывает на то, что в Erlang придут данные в UTF8.

Сам DSN выглядит так:
[mssql]
host = *********
port = ****
servername = mssql <- ссылка на freetds.conf

Ошибка была в том, что ODBC не передает параметры драйверам в
идентификаторах которых имеются пробелы, поэтому с помощью директивы
Servername подключается секция из freetds.conf
Таким образом проблема была чисто админского характера, Erlang тут не причем.
А вот isql входящий в поставку unixODBC непонятно как выдавал
правильную кодировку. Почему ? - неизвестно (возможно он
самостоятельно как-то преобразовывал cp1251 в UTF8 (кодировка
консоли).



29 ноября 2013 г., 11:17 пользователь Dmitry Begunkov
<dbeg...@gmail.com> написал:
> --
> Вы получили это сообщение, так как подписаны на группу "Erlang по-русски".
> Чтобы отказаться от подписки на эту тему, перейдите на страницу
> https://groups.google.com/d/topic/erlang-russian/CD8gktiBGeU/unsubscribe.
> Чтобы отказаться от подписки на эту группу и все входящие в нее темы,
> отправьте электронное письмо на адрес
> erlang-russia...@googlegroups.com.
> Чтобы добавлять сообщения в эту группу, отправьте письмо по адресу
> erlang-...@googlegroups.com.
> Настройки подписки и доставки писем:
> https://groups.google.com/groups/opt_out.

Daniil Churikov

unread,
Nov 30, 2013, 7:03:15 PM11/30/13
to erlang-...@googlegroups.com
Если мне не изменяет память, перекодировкой в этой свзяке занимается iconv, и для него где-то отдельно задаются настройки

среда, 27 ноября 2013 г., 5:40:50 UTC-5 пользователь begemot_sun написал:

Sergey Loguntsov

unread,
Dec 1, 2013, 2:29:57 AM12/1/13
to erlang-...@googlegroups.com
Да, он это делает внутри freetds. Просто настройки freetds не
подключались к ODBC очевидыным образом.

1 декабря 2013 г., 4:03 пользователь Daniil Churikov <ddo...@gmail.com> написал:

Vadim Nik

unread,
Dec 1, 2013, 8:19:55 AM12/1/13
to erlang-...@googlegroups.com

to  begemot_sun, 
реально удалось победить проблему? И получить utf-8 c MSSQL без перекодировки в Erlang?

Можно попросить аналогичный листинг из консоли приведенный мной ниже?


aeroplan@SERVER-ERL-DEV:~$ erl +pc unicode
Erlang R16B (erts-5.10.1) [source] [64-bit halfword] [smp:8:8] [async-threads:10] [kernel-poll:false]

Eshell V5.10.1  (abort with ^G)
1> odbc:start().
ok
2> {ok, C} = odbc:connect("dsn=SKLAD82W;uid=usr;pwd=pass",[{binary_strings, on} ]).
{ok,<0.45.0>}
3> odbc:sql_query(C, binary_to_list(<<"select N'АаБб'"/utf8>>)).               
{selected,[[]],[{<<16,4,48,4,17,4,49,4>>}]}
4>

ЭТО :  <<16,4,48,4,17,4,49,4>>  -> UTF-16

Достаточно давно мучаемся этим вопросом, чего уже только не испробовали. И вот здесь русским по белому написано :  SQL_WCHAR(size) Unicode binary encoded as UTF16 little endian.

Скажите, что мы не правы реализуя свой модуль ODBC и есть для нас "серебряная пуля", которая поможет избежать 4-х конвертаций строк при получении данных из БД в UTF-8.  :0) Заранее спасибо.

Vadim Nik

unread,
Dec 1, 2013, 8:32:01 AM12/1/13
to erlang-...@googlegroups.com


begemot_sun, извините, не увидел , что у Вас БД в cp1251 , везет :0)

Sergey Loguntsov

unread,
Dec 1, 2013, 10:42:13 AM12/1/13
to erlang-...@googlegroups.com
Мой тестовый вывод вот для такого кода:

root@ubuntu:~# cat test.erl
odbc:start().
{ok, S} = odbc:connect("DSN=mssql;UID=****;PWD=*********", [
{trace_driver, on},
{binary_strings, on}
]).
{_, _, [ {B} | _ ] } = odbc:sql_query(S, "select name from services").
io:format("~s~n~n", [ B ]).

Eshell V5.10.3 (abort with ^G)
1> ok
2> {ok,<0.39.0>}
3> {selected,["name"],
[{<<208,146,209,129,208,181>>},
{<<208,161,208,187,209,131,208,182,208,177,208,176,32,50,
55,48,48,50,55,48>>},
{<<208,161,208,187,209,131,208,182,208,177,208,176,32,50,
55,48,48,50,50,50>>},
{<<208,161,208,187,209,131,208,182,208,177,208,176,32,50,
55,48,48,49,49,48>>},
{<<208,161,208,187,209,131,208,182,208,177,208,176,32,50,
55,48,48,56,48,56>>},
{<<208,161,208,187,209,131,208,182,208,177,208,176,32,50,
57,48,48,50,57,...>>},
{<<208,161,208,187,209,131,208,182,208,177,208,176,32,50,
55,48,49,49,...>>},
{<<208,161,208,187,209,131,208,182,208,177,208,176,32,50,
55,48,49,...>>},
{<<208,161,208,187,209,131,208,182,208,177,208,176,32,50,
55,48,...>>},
{<<"WestMotors">>},
{<<208,146,208,149,208,161,208,162>>},
{<<208,159,208,181,208,185,208,189,209,130,208,177,208,
...>>},
{<<208,161,208,187,209,131,208,182,208,177,208,176,...>>},
{<<208,157,208,176,208,177,208,190,209,128,32,...>>},
{<<208,161,208,187,209,131,208,182,208,177,...>>},
{<<208,174,209,128,208,184,209,129,209,...>>},
{<<208,161,208,187,209,131,208,182,...>>},
{<<208,161,208,187,209,131,208,...>>},
{<<208,161,208,187,209,131,...>>},
{<<"Beznal 2222222">>},
{<<208,147,208,176,...>>},
{<<208,147,208,...>>},
{<<208,144,...>>},
{<<"�"...>>},
{<<...>>},
{...}|...]}
4> Все

Насколько я понял, MSSQL отдает данные в той кодировке, в которой
база, хотя могу и ошибаться.

кстати трейс freetds можно посмотреть в /tmp/sql.log при включенной
{trace_driver, on}, там он пишет какую кодировку он принимает и какую
отдает:
UNICODE Using encoding ASCII 'ISO8859-1' and UNICODE 'UCS-2LE'

я правда не понял почему там именно такие значения, в freetds.conf у
меня указана кодировка UTF-8 и результат меня вполне устраивает.

1 декабря 2013 г., 17:32 пользователь Vadim Nik <vadi...@gmail.com> написал:
>
>
> begemot_sun, извините, не увидел , что у Вас БД в cp1251 , везет :0)
>

Артём Семёнов

unread,
Dec 1, 2013, 11:55:59 AM12/1/13
to erlang-...@googlegroups.com
Ребят, я вот почитываю топик и думаю — микрософт до сих пор не научился юникоду, всё транскодить нужно? В, почти, 2014 году?


1 декабря 2013 г., 23:42 пользователь Sergey Loguntsov <logu...@gmail.com> написал:
Вы получили это сообщение, поскольку подписаны на группу Erlang по-русски.

Чтобы отказаться от подписки на эту группу и перестать получать из нее сообщения, отправьте электронное письмо на адрес erlang-russia...@googlegroups.com.

Sergey Loguntsov

unread,
Dec 1, 2013, 1:54:06 PM12/1/13
to erlang-...@googlegroups.com
Честно сказать не знаю, я пришел из мира Linux, там нет MSSQL :)
Зато я видел как люди запускали Erlang-сервер на Windows только потому
что не разобрались с кодировками (он у них там в продакшне работает),
да и с мобильным клиентом работает по cp1251 якобы для минимизации
трафика (проект расчитан на российскую аудиторию).

1 декабря 2013 г., 20:55 пользователь Артём Семёнов <sev...@gmail.com> написал:

Vadim Nik

unread,
Dec 1, 2013, 11:42:14 PM12/1/13
to erlang-...@googlegroups.com


воскресенье, 1 декабря 2013 г., 20:55:59 UTC+4 пользователь sevenov написал:
Ребят, я вот почитываю топик и думаю — микрософт до сих пор не научился юникоду, всё транскодить нужно? В, почти, 2014 году?


Да научился, только для MSSQL, Unicode это значит  USC-2 (он же UTF16 little endian), он и хранит и отдает юникодные строки в этом формате и без вариантов. Хотя есть вариант, это тип XML , там можно получить UTF-8

И Erlang далеко не ушел, юникодные строки из БД , модуль ODBC выдает в том же UTF-16 и тоже без вариантов. В данном случае под юникодными строками я понимаю типы  SQL_WCHAR и SQL_WVARCHAR

Так что, проблема с юникодом - она более глобальная, и мало сред, где с юникодом все шоколадно и не приходится вставлять костыли.

Vadim Nik

unread,
Dec 1, 2013, 11:49:20 PM12/1/13
to erlang-...@googlegroups.com


воскресенье, 1 декабря 2013 г., 19:42:13 UTC+4 пользователь begemot_sun написал:
кстати трейс freetds можно посмотреть в /tmp/sql.log при включенной
{trace_driver, on}, там он пишет какую кодировку он принимает и какую
отдает:
UNICODE Using encoding ASCII 'ISO8859-1' and UNICODE 'UCS-2LE'

я правда не понял почему там именно такие значения, в freetds.conf у
меня указана кодировка UTF-8 и результат меня вполне устраивает.



Для вывода этих двух кодировок FreeTDS использует свой внутренний перекодировщик (аля для юникодных и не юникодных данных), все остальное работает через iconv  и UTF-8 в том числе.


heiheshang

unread,
Jun 16, 2017, 1:36:25 AM6/16/17
to Erlang по-русски
Не пойму как проблему решать, выдает запрос одни ???? там где русские символы.

среда, 27 ноября 2013 г., 19:40:50 UTC+9 пользователь begemot_sun написал:

Aleksey Kluchnikov

unread,
Jun 16, 2017, 1:44:48 AM6/16/17
to erlang-russian
freetds! ух какая древность! оно еще пашет?
Была на одной из предыдущих работ такая задача. И она была решена, не помню как конкретно но общий подход такой же как и любое решение проблем с MS. Долгий и упорный метод тыка.
Но с какой же радостью я оттуда уволился! Ни капли сожаления не было.


16 июня 2017 г., 9:36 пользователь heiheshang <strangerf...@gmail.com> написал:

--
Вы получили это сообщение, поскольку подписаны на группу "Erlang по-русски".
Чтобы отменить подписку на эту группу и больше не получать от нее сообщения, отправьте письмо на электронный адрес erlang-russian+unsubscribe@googlegroups.com.
Чтобы отправлять сообщения в эту группу, отправьте письмо на электронный адрес erlang-russian@googlegroups.com.
Чтобы настроить другие параметры, перейдите по ссылке https://groups.google.com/d/optout.

Imants Cekusins

unread,
Jun 16, 2017, 1:46:44 AM6/16/17
to erlang-...@googlegroups.com

Dmitry Begunkov

unread,
Jun 19, 2017, 7:05:00 AM6/19/17
to Erlang по-русски
помогает что то типа unicode:characters_to_binary(<<"абв"/utf8>>,{utf16, big}, utf8). так как от MSSQL прходят данные в utf16 (насчет big могу ошибаться, возможно little)


среда, 27 ноября 2013 г., 14:40:50 UTC+4 пользователь begemot_sun написал:

Aleksey Kluchnikov

unread,
Jun 19, 2017, 9:02:34 AM6/19/17
to erlang-russian
мне смутно вспоминается что там сразу приходят знаки вопросиков, которые уже никуда не перекодуруешь, то есть настраивать надо сам freetds, вроде 10лет назад было так

19 июня 2017 г., 15:05 пользователь Dmitry Begunkov <dbeg...@gmail.com> написал:

heiheshang

unread,
Jun 20, 2017, 1:11:04 AM6/20/17
to Erlang по-русски
Да приходят знаки вопросиков. Все ришилось установкой unixodbc и freetds из сырцов и установкой charset user =utf-8 + в каталог пользователя из под которго erl стартует надо сложить файлики с настройками freetds и unixodbc

понедельник, 19 июня 2017 г., 22:02:34 UTC+9 пользователь Aleksey Kluchnikov написал:
мне смутно вспоминается что там сразу приходят знаки вопросиков, которые уже никуда не перекодуруешь, то есть настраивать надо сам freetds, вроде 10лет назад было так
19 июня 2017 г., 15:05 пользователь Dmitry Begunkov <dbeg...@gmail.com> написал:
помогает что то типа unicode:characters_to_binary(<<"абв"/utf8>>,{utf16, big}, utf8). так как от MSSQL прходят данные в utf16 (насчет big могу ошибаться, возможно little)

среда, 27 ноября 2013 г., 14:40:50 UTC+4 пользователь begemot_sun написал:


Работаю c MSSQL  ODBC (fretds).
База в cp1251 кодировке.

Заведен DSN:
[mssql]
host = *********
port = ****
tds verion = 7.0
client charset = UTF-8

Консоль в utf8 кодировке. Стандартные средства типа isql работают на ура и показывают текст как надо.
odbc в erlang возвращает вместо строк знаки вопроса (??????) по количеству символов в строке.
Пробовал опцию {binary_strings, on} - не помогает, возвращает <<"???????">>.

Как можно побороть данную проблему?



--
Вы получили это сообщение, поскольку подписаны на группу "Erlang по-русски".
Чтобы отменить подписку на эту группу и больше не получать от нее сообщения, отправьте письмо на электронный адрес erlang-russia...@googlegroups.com.
Чтобы отправлять сообщения в эту группу, отправьте письмо на электронный адрес erlang-...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages