powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / FibPlus. Непонятки с хранением бинарных строк
16 сообщений из 16, страница 1 из 1
FibPlus. Непонятки с хранением бинарных строк
    #38441773
Фотография arni
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Связка FB с 1С (mssql). Получаю на стороне MSSQL бинарные IDшники. Родной тип данных для них - bynary(16), т.е. контейнер на 16 байт. У птички принять во что-то числовое не вариант - слишком велика разрядная сетка, поэтому делается UUID-столбец CHAR(16) CHARACTER SET OCTETS.

В делфи исходный столбец определяется в SDAC как TBytesField, результирующий столбец в FibPlus определяется как TFibStringField (предок от TStringField).

Далее присваивание примерно такого плана:
Код: pascal
1.
2.
3.
4.
5.
6.
FIBDataSet.Append;
...
FIBDataSetUUID.AsString := SDACQuery.FieldByName('UUID').AsString;
if FIBDataSetUUID.AsString <> SDACQuery.FieldByName('UUID').AsString then
  raise Exception.Create('Не впихнулось!');
FIBDataSet.Post;


Т.е. переливка данных через свойство AsString.

В итоге часть данных переливается например такое:
Код: plaintext
0xB22A2C768A5115E011E3096B89BDD8E4

Часть не переливается - рейзится исключение. Например такое:
Код: plaintext
0xB22A2C768A5115E011E32A0089B8B117

До post или после проверка - неважно. Без неё в поле попадает обрезанный вариант строки (не 16 байт). Если выводить содержимое в лог, то на том месте, где обрыв, некий непечатный символ, который переводит строку в консоли.
Есть предположение, что AsString или иное в потрогах FibPlus/TDataSet обрезает поле после этого непечатаемого символа. Но нет ощущения, что так и должно быть (баг или фича?).

Замена чарсета с OCTETS на NONE результата не дает.
Замена метода чтения/записи AsString на AsVariant также.
Замена компонента для вставки с TpFIBDataSet на TpFIBQuery и передача содержимого через параметры результата не дало - также обрезает.

Но! Замена типа поля-приемника на BLOB SUB_TYPE 0 дает рабочее решение - данные корректно переливаются через тот же AsString.
Иметь столбец блобов в таблице сто-тысячнике не улыбается, тем более там всего 16 байт на значение.

Что я делал не так, что посоветуете сделать, чтобы запихать двоичные данные в CHAR(16) CHARACTER SET OCTETS?


Delphi7, FibPlus 6.9.9
Была мысль, публиковать топик в Delphi-раздел, но думаю в bid=2 быстрее помогут.
...
Рейтинг: 0 / 0
FibPlus. Непонятки с хранением бинарных строк
    #38441783
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
arniЕсть предположение, что AsString или иное в потрогах FibPlus/TDataSet обрезает
поле после этого непечатаемого символа. Но нет ощущения, что так и должно быть (баг или
фича?).
Ясно дело - баг. Где-то они работают со строкой как zero-terminated. Devrace пиши, кроме
них никто их баг править не будет.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
FibPlus. Непонятки с хранением бинарных строк
    #38441789
Esperito
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
arniЧасть не переливается - рейзится исключение. Например такое:
Код: plaintext
0xB22A2C768A5115E011E32A 00 89B8B117
Поперхнулось на символе #0, похоже.
Нельзя ли FIBDataSetUUID создать как гуид поле и заполнять как гуид?
...
Рейтинг: 0 / 0
FibPlus. Непонятки с хранением бинарных строк
    #38441816
hvlad
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
TField.SetData пробовал ?
...
Рейтинг: 0 / 0
FibPlus. Непонятки с хранением бинарных строк
    #38441845
Фотография arni
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hvlad, пробовал. Результат не изменился.

Но!
Сделав каст выборки заполненого поля CHAR(16) CHARACTER SET OCTETS к типу BLOB SUB_TYPE TEXT, оказалось, что содержимое не потерялось. Т.е. компонент все-таки справляется с записью значения, но не справляется с извлечением его обратно. Т.е. сеттер отрабатывает, а геттер достает уже покоцанные данные, поэтому и не проходит сравнение.
Думаю, что с этим делать. Продолжать дальше бить в бубен, или плюнуть и использовать блоб, или вообще хранить нормализованные GUID в ASCII-виде.
...
Рейтинг: 0 / 0
FibPlus. Непонятки с хранением бинарных строк
    #38441847
Фотография kdv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
arni,

а чего бубен-то. исходники фибплюса же есть. думаю, там недолго копать.
...
Рейтинг: 0 / 0
FibPlus. Непонятки с хранением бинарных строк
    #38441859
Фотография arni
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Увы, поспешил с выводами: запись через TFIBStringField.AsString всеже коцает значение: последний байт не соответствует контрольному значению. Если обернуть uuid_to_char(), то получаются соответственно
Код: plaintext
B22A2C76-8A51-15E0-11E3-2A0089B8B100
Код: plaintext
B22A2C76-8A51-15E0-11E3-2A0089B8B117

Также оказалось, что у firebird и mssql разный выхлоп при переводе бинарного UUID в текстовку
Код: sql
1.
cast(UUID as UNIQUEIDENTIFIER)


Код: plaintext
762C2AB2-518A-E015-11E3-2A0089B8B117
Младшие байты совпали, старшие - нет.
Видимо надо уже на свежую понедельничную голову всё это переосмысливать.
...
Рейтинг: 0 / 0
FibPlus. Непонятки с хранением бинарных строк
    #38441864
Гаджимурадов Рустам
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
arni> Т.е. сеттер отрабатывает, а геттер достает уже покоцанные данные, поэтому и не проходит сравнение.

Поробуй принудительно тип поля задать BLOB вместо sttring.
Ну или кастуй на худой конец.

Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
FibPlus. Непонятки с хранением бинарных строк
    #38441866
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
arniоказалось, что у firebird и mssql разный выхлоп при переводе бинарного UUID в
текстовку
Да, это известный баг uuid_to_char. Поищи в трекере.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
FibPlus. Непонятки с хранением бинарных строк
    #38441867
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Гаджимурадов РустамПоробуй принудительно тип поля задать BLOB вместо sttring.
Ну или кастуй на худой конец.

И эти люди смеются надо мной когда я говорю, что от компонент одни проблемы...
...
Рейтинг: 0 / 0
FibPlus. Непонятки с хранением бинарных строк
    #38441878
чччД
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
arni,

используй свойство TFIBXSQLVAR.AsGuid - как раз 16 байт.
...
Рейтинг: 0 / 0
FibPlus. Непонятки с хранением бинарных строк
    #38442004
Гаджимурадов Рустам
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
DS> И эти люди смеются надо мной когда я говорю, что от компонент одни проблемы...

Ну, вовсе не "одни проблемы". Тем более твоё замечание не к месту,
ибо ТС отказываться от компонент и ваять свой велосипед не будет.

Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
FibPlus. Непонятки с хранением бинарных строк
    #38442123
Фотография arni
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Реята, спасибо за советы. Но лучший советчик - ясная, выспаная голова.

Давайте я подробно расскажу с чем имею дело. Просто, чтобы топик был законченным.

Тестовый запрос на стороне mssql:
Код: sql
1.
2.
3.
select UUID, cast(UUID as char(16)), NAME
  from SP_STOCK
 where NAME='__Мебель_Склад гот.продук'


Получаем:
Код: plaintext
0xB22A2C768A5115E011E325A8E322A49D
Код: plaintext
І*,vЉQаг%Ёг"¤ќ
Код: plaintext
__Мебель_Склад гот.продук


Тип первого столбца - binary(16). При выводе на экран мы видим HEX-представление.
Второй столбец - натуальное значение. Пришлось постараться поискать строку, которая бы не содержала откровенно непечатных символов.

Этот вариант отлично засосется в Firebird посредством FibPlus компонентов. Подробности в стартовом сообщении.
Если ASCII-представление UUID (второй столбец) содержит непечатный символ, то при передаче часть значения теряется. Не теряется, если приемник - столбец BLOB. Но как оказалось, текстовые блобы (TFIBMemoField кажется) в Delphi не могут работать в lookup-связках, а т.к. перекачивается справочник и обсуждаемое поле - суть ID, то лукапом ему работать на роду написано. Причем в гридах, что затрудняет подстановку костылей (своя форма подбора значения из справочника).

Далее я был несколько обескуражен тем, как работает функция uuid_to_char в firebird:
Код: sql
1.
2.
select uuid_to_char('І*,vЉQаг%Ёг"¤ќ')
  from rdb$database

получаем:
Код: plaintext
B22A2C76-8A51-15E0-11E3-25A8E322A49D

Если присмотреться, то это просто строка от HEX-представления и черточки для красоты. Возможно так всё и задумывалось, но я просто был сбит с толку, что
Код: sql
1.
cast(UUID as UNIQUEIDENTIFIER)

на стороне mssql выдает другую строку:
Код: plaintext
762C2AB2-518A-E015-11E3-25A8E322A49D

Интересно, что последние две части квинтета совпали, вторая и третья части тоже совпали, но в них переставлены местами байты, а первая часть тоже совпала, но буковки перемешаны там просто адски, хотя и теже самые. :)

Под конец добил 1Сник, который показал как он может преобразовывать код в 1C-объект:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
УИД = "B22A2C76-8A51-15E0-11E3-25A8E322A49D";
УИД = НРЕГ(СтрЗаменить(УИД,"-",""));
УИД1 = Прав(УИД,8 );
УИД2 = Сред(УИД,21,4);
УИД3 = Сред(УИД,17,4);
УИД4 = Лев(УИД,4);
УИД5 = Сред(УИД,5,12);
УИД = УИД1 + "-" +УИД2 + "-" + УИД3 + "-" + УИД4 + "-" + УИД5;
Склад = Справочники.Склады.ПолучитьСсылку(Новый УникальныйИдентификатор(УИД));
Сообщить(УИД);
Сообщить(Склад);

Результат:
Код: plaintext
1.
e322a49d-25a8-11e3-b22a-2c768a5115e0
__Мебель_Склад гот.продук

Я совершенно не въехал, что за третий GUID-подобный объект у него родился (e322a49d-25a8-11e3-b22a-2c768a5115e0) и почему он оказался непохож ни на mssql-guid (762C2AB2-518A-E015-11E3-25A8E322A49D), ни на HEX-представление, оно же результат птичкиного uuid_to_char (B22A2C76-8A51-15E0-11E3-25A8E322A49D).
Но с практической точки зрения дальше вроде всё стало ясно:
- 1Сника устроит на входе HEX;
- значит на стороне firebird будем хранить HEX в виде CHAR(32);
- значит на стороне mssql нужно получать это HEX в виде строки (сейчас это binary, которая только выглядит как HEX).
Последнее решилось с помощью гугла:
Код: sql
1.
convert(char(32), UUID, 2)

Код: plaintext
B22A2C768A5115E011E325A8E322A49D
И к черту эти char(16) character set octets: перепахивать библиотеку ради корректной записи/чтения через AsString смысла не вижу. А вот mssql похоже теперь потеть больше, т.к. выборки из приложения теперь ему делать не через
Код: sql
1.
where UUID = :UUID

, а через
Код: sql
1.
where convert(char(32), UUID, 2) = :UUID


Но как пелось в детской песенке:авторПозабыты хлопоты, остановлен бег -
Вкалывают роботы, а не человек.:)

p.s. Не сомневаюсь, что суровая жизнь и тут меня хлопнет по шапке, как это было вчера с блобами. Но пока вроде выглядит всё по рабочему... хоть и не особо энтерпрайзненько
...
Рейтинг: 0 / 0
FibPlus. Непонятки с хранением бинарных строк
    #38442138
hvlad
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
arniА вот mssql похоже теперь потеть больше, т.к. выборки из приложения теперь ему делать не через
Код: sql
1.
where UUID = :UUID


, а через
Код: sql
1.
where convert(char(32), UUID, 2) = :UUID

Сдаётся мне, что так ты не дашь ему искать по индексу, так что ищи способ кастить параметр, а не поле
...
Рейтинг: 0 / 0
FibPlus. Непонятки с хранением бинарных строк
    #38442158
Фотография arni
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hvlad,

да, так, либо индекс по выражению. Но есть ощущение, что любая оптимизация, пока решение не проверено временем, суть - зло.

offСуровые 1Сники не дают права вертеть DDL в их суровой базе с их суровыми таблицами _Reference001 ... _Reference999 и не менее суровыми столбцами _Fld0001 ... _Fld9999. Удалось выпросить только view'шки создавать, чтобы маппить идентификаторы на человекочитаемые. А до этого запросы писать было как дамп памяти разбирать, ну или как Нэо читал падающие зеленые буковки.
...
Рейтинг: 0 / 0
FibPlus. Непонятки с хранением бинарных строк
    #38442431
Фотография ScareCrow
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
у 1С ников есть файлик маппинга в нормальные названия. его можно распарсить и больше не мучатся.
...
Рейтинг: 0 / 0
16 сообщений из 16, страница 1 из 1
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / FibPlus. Непонятки с хранением бинарных строк
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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