unixODBC+Oracle+UTF8 и двойное перекодирование

Saemon Zixel
Дата: 24.10.2015 23:37:48
Добрый день.

Что имеем:
oracle-xe-univ-10.2.0.1-1.0.i386
oracle-instantclient-basic-10.2.0.3-1.i386
instantclient-odbc-linux32-10.2.0.3-20061115
unixODBC-2.3.1-3.1.2.i586

Оракл запущен и всё настроено как надо (ценой нескольких дней напряжённой работы и большого количества потерянных нервов).

Прописал драйвер в odbcinst.ini
[Oracle_10g]
Description=Oracle ODBC driver for Oracle 10g
Driver=/usr/lib/oracle/10.2.0.3/client/lib/libsqora.so.10.1
Setup=/usr/lib/oracle/10.2.0.3/client/lib/libsqora.so.10.1
FileUsage = 1
Driver Logging = 7

Прописал базу в odbc.ini
[XE]
Driver = Oracle_10g
ServerName = //127.0.0.1:1521/XE
DSN = XE

Локаль установил - LANG=ru_RU.UTF-8
И для оракла прописал - NLS_LANG=.AL32UTF8
Подключаюсь успешно - isql XE system ***

Проверяю настройки базы:
SQL> SELECT * FROM nls_database_parameters;
NLS_LANGUAGE = AMERICAN
NLS_TERRITORY = AMERICA
NLS_CURRENCY = $
NLS_ISO_CURRENCY = AMERICA
NLS_NUMERIC_CHARACTERS = .,
NLS_CHARACTERSET = AL32UTF8
NLS_CALENDAR = GREGORIAN
NLS_DATE_FORMAT = DD-MON-RR
NLS_DATE_LANGUAGE = AMERICAN
NLS_SORT = BINARY
NLS_TIME_FORMAT = HH.MI.SSXFF AM
NLS_TIMESTAMP_FORMAT = DD-MON-RR HH.MI.SSXFF AM
NLS_TIME_TZ_FORMAT = HH.MI.SSXFF AM TZR
NLS_TIMESTAMP_TZ_FORMAT = DD-MON-RR HH.MI.SSXFF AM TZR
NLS_DUAL_CURRENCY = $
NLS_COMP = BINARY
NLS_LENGTH_SEMANTICS = BYTE
NLS_NCHAR_CONV_EXCP = FALSE
NLS_NCHAR_CHARACTERSET = AL16UTF16
NLS_RDBMS_VERSION = 10.2.0.1.0

Далее делаю так:
SQL> CREATE TABLE test(col1 VARCHAR2(255), col2 NVARCHAR2(255));
SQLRowCount returns -1

SQL> INSERT INTO test VALUES ('123абв', '123абв');
SQLRowCount returns 1

SQL> SELECT col1, col2, dump(col1), dump(col2) FROM test;

COL1
--------------------------------------------------------------------------------
COL2
--------------------------------------------------------------------------------
DUMP(COL1)
--------------------------------------------------------------------------------
DUMP(COL2)
--------------------------------------------------------------------------------
123абв
123абв
Typ=1 Len=15: 49,50,51,195,144,194,176,195,144,194,177,195,144,194,178
Typ=1 Len=18: 0,49,0,50,0,51,0,208,0,176,0,208,0,177,0,208,0,178

По дампу содержимого колонок видно двойное кодирование UTF8.
Откуда? Как? Уже второй день мучаюсь и не могу побороть...

Что интересно, если сделать - NLS_LANG=.WE8ISO8859P1
То SELECT выдаст уже читаемый текст:
SQL> SELECT col1, col2, dump(col1), dump(col2) FROM test;

COL1
--------------------------------------------------------------------------------
COL2
--------------------------------------------------------------------------------
DUMP(COL1)
--------------------------------------------------------------------------------
DUMP(COL2)
--------------------------------------------------------------------------------
123абв
123абв
Typ=1 Len=15: 49,50,51,195,144,194,176,195,144,194,177,195,144,194,178
Typ=1 Len=18: 0,49,0,50,0,51,0,208,0,176,0,208,0,177,0,208,0,178

Но это нето. Это всё криво...

У кого-нибудь было подобное? Кто что может подсказать?
Есть мнение что драйвер ODBC неподходящий (не для Universal), и надо качать какую-нибудь другую версию драйвера. Но тогда какую?
Dimitry Sibiryakov
Дата: 25.10.2015 00:28:36

Saemon Zixel
Подключаюсь успешно - isql XE system ***

А если проделать всё то же самое в родном sqlplus?

Posted via ActualForum NNTP Server 1.5

echo абв | od -t x1
Дата: 25.10.2015 00:30:48
Saemon Zixel,

Зачем тебе odbc?
Кодировку клиента нужно смотреть в nls_SESSION_parameters.
Отображением и вводом символов занимается клиентская программа, в данном случае консоль. Какая у нее кодировка и шрифт?
V$SESSION_CONNECT_INFO
Дата: 25.10.2015 09:48:26
echo абв | od -t x1
Кодировку клиента нужно смотреть в nls_SESSION_parameters.
а увидишь?
Saemon Zixel
Дата: 25.10.2015 19:33:00
Dimitry Sibiryakov, в родном sqlplus всё нормально. Двойной перекодировки не происходит. Русский текст вставляется и считывается нормально.

К сожалению не могу сейчас перепроверить. Борюсь с "ORA-12528: TNS:listener: all appropriate instances are blocking new connections"...
Saemon Zixel
Дата: 25.10.2015 19:42:56
Перезапустил оракл...
Перепроверил, в sqlplus получилось следующее:

SQL> INSERT INTO test VALUES ('123абв', '123абв');

1 row created.

SQL> SELECT dump(col1), dump(col2), col1, col2 FROM test;

DUMP(COL1)
--------------------------------------------------------------------------------
DUMP(COL2)
--------------------------------------------------------------------------------
COL1
--------------------------------------------------------------------------------
COL2
--------------------------------------------------------------------------------
Typ=1 Len=15: 49,50,51,195,144,194,176,195,144,194,177,195,144,194,178
Typ=1 Len=18: 0,49,0,50,0,51,0,208,0,176,0,208,0,177,0,208,0,178
123абв
123абв


DUMP(COL1)
--------------------------------------------------------------------------------
DUMP(COL2)
--------------------------------------------------------------------------------
COL1
--------------------------------------------------------------------------------
COL2
--------------------------------------------------------------------------------
Typ=1 Len=9: 49,50,51,208,176,208,177,208,178
Typ=1 Len=12: 0,49,0,50,0,51,4,48,4,49,4,50
123абв
123абв
Saemon Zixel
Дата: 25.10.2015 20:14:35
При этом если NLS_LANG выставить в .AL32UTF8
isql выдаст:

SQL> SELECT * FROM test;
+---------------------+---------------------+
| COL1 | COL2 |
+---------------------+---------------------+
| 123абв | 123абв |
| 123абв | 123абв |
+---------------------+---------------------+

А если NLS_LANG выставить в .WE8ISO8859P1 будет:

SQL> SELECT * FROM test;
+---------------------+---------------------+
| COL1 | COL2 |
+---------------------+---------------------+
| 123абв | 123абв |
| **ERROR** | **ERROR** |
+---------------------+---------------------+
Dimitry Sibiryakov
Дата: 25.10.2015 20:29:04

Saemon Zixel
При этом если NLS_LANG выставить в .AL32UTF8
isql выдаст:

Вот в этом состоянии, когда он даёт вывод, совпадающий с sqlplus попробуй добавить из него
ещё одну строку в таблицу. Возможно, первая была добавлена когда в ходе экспериментов LANG
не совпадал с NLS_LANG.

Posted via ActualForum NNTP Server 1.5

Saemon Zixel
Дата: 25.10.2015 20:42:23
Dimitry Sibiryakov,

saemon@mypc:~> export NLS_LANG=.AL32UTF8
saemon@mypc:~> isql -m30 XE system ***
+---------------------------------------+
| Connected! |
| |
| sql-statement |
| help [tablename] |
| quit |
| |
+---------------------------------------+
SQL> DELETE FROM test;
SQLRowCount returns 2
SQL> INSERT INTO test VALUES('123абв', '123абв');
SQLRowCount returns 1
SQL> SELECT * FROM test;
+-------------------------------+-------------------------------+
| COL1 | COL2 |
+-------------------------------+-------------------------------+
| 123абв | 123абв |
+-------------------------------+-------------------------------+
SQLRowCount returns -1
1 rows fetched
SQL>
Dimitry Sibiryakov
Дата: 25.10.2015 21:01:03

Saemon Zixel
SQL> DELETE FROM test;

Нахрена?..

Posted via ActualForum NNTP Server 1.5