Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / C++ [игнор отключен] [закрыт для гостей] / DB_VARNUMERIC, SBYTE, Oracle OLE DB / 7 сообщений из 7, страница 1 из 1
05.09.2005, 17:50
    #33252484
Lana K.
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
DB_VARNUMERIC, SBYTE, Oracle OLE DB
Умные люди, помогите пожалуйста разобраться!

Проблема в следующем.
Наша программа на С++ может связываться с БД через Oracle OLE DB. И потом пользователи могут отправлять запросы, какие им хочется. Из-за баги в провайдере приходиться сейчас связывать буфера для результатов запроса не как текст (так мы делали раньше), а как тип данных, возвращаемый провайдером после анализа запроса (интерфейс IColumnsInfo).
Для некоторых данных (например для вычисляемых значений, типа "SELECT 1/4 FROM DUAL") Oracle возвращает тип DBTYPE_VARNUMERIC.
Данные, которые потом провайдер пишет в подготовленный нами буфер, имеют следующую структуру:
Typedef struct tagDB_VARNUMERIC {
BYTE precision;
SBYTE scale;
BYTE sign;
BYTE val[ 1 ];
} DB_VARNUMERIC;
Вот у меня проблема с полем scale. Я его в программе выковыриваю следующим образом:
SBYTE scale = ( ( DB_VARNUMERIC * ) rowData )->scale;
и потом так использую:
adjust *= sign;
if (scale < 0)
{
for( int k = 0 ; k > scale ; k-- ) adjust *= 10;
dValue *= adjust;
}
else
{
for( int k = 0 ; k < scale ; k++ ) adjust *= 10;
dValue /= adjust;
}
(dValue это double переменная, в которую я перегружаю само число из поля val структуры DB_VARNUMERIC).
И всё было бы замечательно, если бы для чисел с експонентой между -128 и -114 не получалась бы полнейшая ерунда.

Вот теперь и вопрос: это Oracle мне чушь подсовывает, или я значение scale неправильно выковыриваю?

Итак, то, что я получаю: вместо 142 -> -114; 141 -> -115;... ; 128 -> -128;
а вот уже начиная с експоненты -113 уже всё в порядке: 127, 126,...
Варианты:
int scale = ( int )( ( DB_VARNUMERIC * ) rowData )->scale;
char scale = ( char )( ( DB_VARNUMERIC * ) rowData )->scale;
signed char scale = ( signed char )( ( DB_VARNUMERIC * ) rowData )->scale;

Заранее спасибо за идеи!!!
...
Рейтинг: 0 / 0
08.09.2005, 19:15
    #33259788
Lana K.
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
DB_VARNUMERIC, SBYTE, Oracle OLE DB
Ответ простой: SBYTE scale. Смешно ожидать, что в scale будет стоять 142, если в SBYTE можно только от -128 до 127 представить.
Заклинило, звиняйте.
Другой вопрос, чего это Oracle OLE DB туда пихает то, что поместиться не может, вместо того чтобы ошибку вернуть :-(((.
...
Рейтинг: 0 / 0
09.09.2005, 06:34
    #33260140
Станислав C.
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
DB_VARNUMERIC, SBYTE, Oracle OLE DB
Lana K.Ответ простой: SBYTE scale. Смешно ожидать, что в scale будет стоять 142, если в SBYTE можно только от -128 до 127 представить.
Заклинило, звиняйте.
Другой вопрос, чего это Oracle OLE DB туда пихает то, что поместиться не может, вместо того чтобы ошибку вернуть :-(((.
Извиняйте, но ведь 142 < 255... Верно? А от -128 до 127 как раз и расположено 256 значений... Вот Оракл и "пихает" туда это значение...
А проблема здесь кроется в обработке значений (знаковые / беззнаковые).
В случае, если значение знаковое, добавление лишней 1 (переход от 127 к 128) приведет к установке знакового бита в 1, что в свою очередь приведет к значению -128... Скорее всего, Вам надо просто применить преобразование в (unsigned char) (Это как раз и будет интервал от 0 до 255)...
...
Рейтинг: 0 / 0
09.09.2005, 06:50
    #33260148
Станислав C.
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
DB_VARNUMERIC, SBYTE, Oracle OLE DB
Станислав C. Lana K.Ответ простой: SBYTE scale. Смешно ожидать, что в scale будет стоять 142, если в SBYTE можно только от -128 до 127 представить.
Заклинило, звиняйте.
Другой вопрос, чего это Oracle OLE DB туда пихает то, что поместиться не может, вместо того чтобы ошибку вернуть :-(((.
Извиняйте, но ведь 142 < 255... Верно? А от -128 до 127 как раз и расположено 256 значений... Вот Оракл и "пихает" туда это значение...
А проблема здесь кроется в обработке значений (знаковые / беззнаковые).
В случае, если значение знаковое, добавление лишней 1 (переход от 127 к 128) приведет к установке знакового бита в 1, что в свою очередь приведет к значению -128... Скорее всего, Вам надо просто применить преобразование в (unsigned char) (Это как раз и будет интервал от 0 до 255)...
В догонку код, подтверждающий мои слова:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
#include <stdio.h>
#include <conio.h>

int main(int argc, char* argv[])
{
 unsigned char scale =  142 ; //Да любое значение <=255
 printf("Unsigned: %d\n",scale);
 printf("Signed: %d\n",(signed char)scale);
 getch();
 return  0 ;
}
...
Рейтинг: 0 / 0
12.09.2005, 15:18
    #33264368
Lana K.
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
DB_VARNUMERIC, SBYTE, Oracle OLE DB
Станислав C., спасибо за ответ, но вы не совсем правы. SBYTE - это signed char. Преобразование к unsigned char приведёт просто к искажению данных. Для отрицательных значений будет происходить такая же петрушка, как и с 142 в signed char.
Кстати, можете это проверить вашим же кодом.
Итак, ещё раз: в структуре могут поместиться значения со scale от -128 до 127, поэтому я считаю поведение Oracle OLE DB ошибочным. Либо исходное число должно было быть округлено так, чтобы его представление в этой структуре было возможным, либо должна возвращаться ошибка.
Кстати, майкрософтовский OLE DB провайдер для таких значений возвращает ошибку и пустую структуру.
...
Рейтинг: 0 / 0
12.09.2005, 15:30
    #33264407
Станислав C.
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
DB_VARNUMERIC, SBYTE, Oracle OLE DB
Lana K.Станислав C., спасибо за ответ, но вы не совсем правы. SBYTE - это signed char. Преобразование к unsigned char приведёт просто к искажению данных. Для отрицательных значений будет происходить такая же петрушка, как и с 142 в signed char.
Кстати, можете это проверить вашим же кодом.
Итак, ещё раз: в структуре могут поместиться значения со scale от -128 до 127, поэтому я считаю поведение Oracle OLE DB ошибочным. Либо исходное число должно было быть округлено так, чтобы его представление в этой структуре было возможным, либо должна возвращаться ошибка.
Кстати, майкрософтовский OLE DB провайдер для таких значений возвращает ошибку и пустую структуру.

Я все понял правильно. Я лишь отвечаю на Ваш вопрос:
автор
Вот теперь и вопрос: это Oracle мне чушь подсовывает, или я значение scale неправильно выковыриваю?

и объясняю как число, не помещающееся в указанный диапазон (от -128 до 127) все-таки оказывается записанным в переменную... И что это не ошибка, а лишь взгляд на интерпретацию двоичного представления числа... А как Вам поступать дальше (уж коль скоро такая особенность проявилась) - решайте сами... Я же не даю никакого совета...
...
Рейтинг: 0 / 0
16.09.2005, 14:37
    #33273745
Lana K.
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
DB_VARNUMERIC, SBYTE, Oracle OLE DB
Может кому пригодиться информация. Oracle открыл под это дело Bug 4607375:

DBTYPE_VARNUMERIC WRONG BEHAVIOUR WHEN SCALE EXCEEDS 127.
...
Рейтинг: 0 / 0
Форумы / C++ [игнор отключен] [закрыт для гостей] / DB_VARNUMERIC, SBYTE, Oracle OLE DB / 7 сообщений из 7, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]