ClickHouse / clickhouse-odbc

ODBC driver for ClickHouse
https://clickhouse.tech
Apache License 2.0
245 stars 86 forks source link

Ошибка "Cannot get the column information" в простом запросе к ClickHouse как Linked server в MS SQL через ODBC #371

Open sheigor opened 3 years ago

sheigor commented 3 years ago

есть ClickHouse version 20.7.2.30 (official build) таблица с полем типа Decimal(18, 2) в MS SQL создан Linked Server через драйвер ODBC Release 1.1.9.20201226 win64 Unicode по инструкции в тесте при попытке выбрать это поле из таблицы

exec ('select column_with_typeDecimal from table_name') at [ch_linkedserver]

возникает ошибка:

Сообщение 7399, уровень 16, состояние 1, строка 24
The OLE DB provider "MSDASQL" for linked server "ch_linkedserver" reported an error. The provider did not give any information about the error.
Сообщение 7350, уровень 16, состояние 2, строка 24
Cannot get the column information from OLE DB provider "MSDASQL" for linked server "ch_linkedserver".

в родном интерфейсе проблем нет. переполнения в поле не наблюдается, все попытки преобразовать данные к результату не приводят.

traceon commented 3 years ago
sheigor commented 3 years ago

Из других полей взять данные через linked server проблем нет. ODBCtest данные из этого поля возвращает. Однако судя по ответам он связывает это поле как тип SQL_C_CHAR размером 43. Дальнейший разбор показывает что ODBC драйвер при вызове SQLDescribeColumn возвращает тип колонки SQL_DECIMAL с точностью 41 (это же значение при вызове метода SQLGetTypeInfo о поддерживаемых типах в драйвере), а максимальная точность у DECIMAL в SQL Server только 38. Причем реальная точность самой колонки (18, 2) не указывается драйвером.

Describe Column All: icol, szColName, pcbColName, pfSqlType, pcbColDef, pibScale, *pfNullable 1, col_ID, 6, SQL_BIGINT=-5, 10, 0, SQL_NO_NULLS=0 2, col_CC, 6, SQL_DECIMAL=3, 41, 0, SQL_NO_NULLS=0

traceon commented 3 years ago

SQL_DECIMAL по умолчанию представляется как строка. 41 плюс точка плюс знак: 43. Какая версив драйвера?

sheigor commented 3 years ago

Поведение одинаковое и с 1.1.9.20201226 и с 1.1.8.20200710.

traceon commented 3 years ago

Было бы быстрее, если бы вы смогли написать список шагов, как это все поднять, запустить, воспроизвести на машине, где установлен только чистый SQL server и ClickHouse ODBC драйвер (с доступом к публичному ClickHouse playground) и человек, который не знает ничего кроме очевидных вещей про SQL server.

sheigor commented 3 years ago

Так все же очень просто. В ClickHouse надо просто иметь таблицу с колонкой с типом Decimal(18, 2) созданную и заполненную штатными средствами ClickHouse. Затем, используя пример из Вашего теста mssql.linked.server.sql, просто попытаться выбрать записи как указано в этом тесте.

sheigor commented 2 years ago

Repro с драйвером 1.1.10,20210822

exec master.dbo.sp_dropserver N'clickhouse_numeric_test', @droplogins='droplogins';
exec master.dbo.sp_addlinkedserver
        @server = N'clickhouse_numeric_test'
       ,@srvproduct=N'Clickhouse'
       ,@provider=N'MSDASQL'
       ,@provstr=N'Driver={ClickHouse ODBC Driver (Unicode)};SERVER=localhost;DATABASE=system;stringmaxlength=8000;'
exec master.dbo.sp_addlinkedsrvlogin @rmtsrvname=N'clickhouse_numeric_test',@useself=N'False',@locallogin=NULL,@rmtuser=N'default',@rmtpassword=''
exec master.dbo.sp_serveroption @server=N'clickhouse_numeric_test', @optname=N'rpc', @optvalue=N'true'
exec master.dbo.sp_serveroption @server=N'clickhouse_numeric_test', @optname=N'rpc out', @optvalue=N'true'
exec master.dbo.sp_serveroption @server=N'clickhouse_numeric_test', @optname=N'remote proc transaction promotion', @optvalue=N'false'

exec('create table if not exists default.numeric_test ( xx decimal(18,2)) engine = Memory;') at [clickhouse_numeric_test];
exec('insert into default.numeric_test VALUES (100500.5), (1), (-0.05);') at [clickhouse_numeric_test];
exec('select xx as x from default.numeric_test;') at [clickhouse_numeric_test];
exec('drop table default.numeric_test;') at [clickhouse_numeric_test];

причем сообщение об ошибке openquery и exec отличаются: у openquery: "Сообщение 7399, уровень 16, состояние 1, строка 24 The OLE DB provider "MSDASQL" for linked server "clickhouse_numeric_test" reported an error. The provider did not give any information about the error. Сообщение 7350, уровень 16, состояние 2, строка 24 Cannot get the column information from OLE DB provider "MSDASQL" for linked server "clickhouse_numeric_test" у exec: "Сообщение 7354, уровень 16, состояние 1, строка 44 The OLE DB provider "STREAM" for linked server "(null)" supplied invalid metadata for column "x". The precision exceeded the allowable maximum."

И что это за OLE DB provider "STREAM" появился?