powered by simpleCommunicator - 2.0.53     © 2025 Programmizd 02
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / FB2.5 - VARCHAR, содержащие ASCII_CHAR( 0 )
12 сообщений из 12, страница 1 из 1
FB2.5 - VARCHAR, содержащие ASCII_CHAR( 0 )
    #38966491
Polesov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Привет всем.

Суть вопроса в том, что при наличии в поле типа VARCHAR символа с нулевым кодом функция CHAR_LENGTH() возвращает полную длину с у четом символов после #0, а собственно значение поля возвращается обрезанным до первого нулевого символа.

Ниже приведен несложный сценарий для ISQL:

CREATE TABLE ITEMS (
ID INTEGER NOT NULL,
NAME VARCHAR(100) NOT NULL
);

ALTER TABLE ITEMS ADD CONSTRAINT PK_ITEMS PRIMARY KEY (ID);
ALTER TABLE ITEMS ADD CONSTRAINT UNQ_ITEMS UNIQUE (NAME);

INSERT INTO ITEMS( ID, NAME ) VALUES ( 1, 'Name #1' );
COMMIT;


SELECT '<' || NAME || '>', CHAR_LENGTH( NAME )
FROM ITEMS;
/* Здесь все правильно, символа #0 нет */
NAME CHAR_LENGTH
=============================================
<Name #1> 7


/* добавляем нулевой символ */
UPDATE ITEMS
SET NAME = NAME || ASCII_CHAR( 0 ) || '+++';

SELECT '<' || NAME || '>', CHAR_LENGTH( NAME )
FROM ITEMS;
/* Ошибка: CHAR_LENGTH() возвращает большее значение, нежели чем собственно возвращенное значение поля NAME
возвращенное значение поля NAME обрезано до первого нулевого символа */
NAME CHAR_LENGTH
=============================================
<Name #1 11


/* повторно добавляем нулевой символ */
UPDATE ITEMS
SET NAME = NAME || ASCII_CHAR( 0 ) || '+++';
SELECT '<' || NAME || '>', CHAR_LENGTH( NAME )
FROM ITEMS;
/* значение, возвращенное функцией CHAR_LENGTH(), увеличилось на 4
возвращенное значение поля NAME не изменилось (так же обрезано до первого нулевого символа ) */
NAME CHAR_LENGTH
=============================================
<Name #1 15


С уважением, Polesov.
...
Рейтинг: 0 / 0
FB2.5 - VARCHAR, содержащие ASCII_CHAR( 0 )
    #38966511
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Polesov
Код: sql
1.
NAME VARCHAR(100) ==>CHARACTER SET OCTETS<== NOT NULL


Во всех остальных чарсетах нулевой символ не является валидным и последствия его вставки
неопределены.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
FB2.5 - VARCHAR, содержащие ASCII_CHAR( 0 )
    #38966533
Polesov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Тестировалось на CHARACTER SET WIN1251

Но ведь функция CHAR_LENGTH() возвращает значение с учетом того, что находится за нулевым символом.

И при передаче параметра в UDF BY DESCRIPTOR значение поля dsc_length структуры, описывающей параметр, тоже содержит значение с учетом того, что находится за нулевым символом.

Все же, если значение поля выводится до первого попавшегося нулевого символа, то и результат функции CHAR_LENGTH() тоже должен учитывать наличие нуля, а не брать значение фактической длины хранящихся в БД данных.

С уважением, Polesov.
...
Рейтинг: 0 / 0
FB2.5 - VARCHAR, содержащие ASCII_CHAR( 0 )
    #38966542
Polesov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вдогонку:

SELECT CHAR_LENGTH( '123' || ASCII_CHAR( 0 ) || '321' )
FROM RDB$DATABASE;

возвращает 7
...
Рейтинг: 0 / 0
FB2.5 - VARCHAR, содержащие ASCII_CHAR( 0 )
    #38966600
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Polesovесли значение поля выводится до первого попавшегося нулевого символа, то...

....это происходит исключительно в силу того, что в С строки традиционно null-terminated.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
FB2.5 - VARCHAR, содержащие ASCII_CHAR( 0 )
    #38966652
Polesov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ну, тогда надо, чтобы в FB функция CHAR_LENGTH() тоже возвращала результат согласно лучшим традициям С
...
Рейтинг: 0 / 0
FB2.5 - VARCHAR, содержащие ASCII_CHAR( 0 )
    #38966655
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Polesovтогда надо
Кому и зачем?
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
FB2.5 - VARCHAR, содержащие ASCII_CHAR( 0 )
    #38966662
-
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
-
Гость
Dimitry Sibiryakov....это происходит исключительно в силу того, что в С строки традиционно null-terminated.
У меня с нулём возвращает, на Delphi. Пропатчил UIB чтобы нормально с октетами работал.
А ваш репликатор разве обрезает такие строки?
...
Рейтинг: 0 / 0
FB2.5 - VARCHAR, содержащие ASCII_CHAR( 0 )
    #38966694
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
-А ваш репликатор разве обрезает такие строки?
Мой репликатор не использует ни CHAR_LENGTH(), ни вывод данных на экран.

И таки нет, с такими странными строками при репликации ничего не происходит, поскольку
любые данные рассматриваются как двоичные и (в общем случае) не подвергаются никакому
преобразованию, передаваясь "как есть".
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
FB2.5 - VARCHAR, содержащие ASCII_CHAR( 0 )
    #38966717
Polesov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry Sibiryakov,

По крайней мере, при передаче в UDF параметра типа CSTRING BY DESCRIPTOR, значение dsc_length в структуре описания этого параметра содержит такое же значение, как и результат функции CHAR_LENGTH(), т.е. без учета нулевого символа.
...
Рейтинг: 0 / 0
FB2.5 - VARCHAR, содержащие ASCII_CHAR( 0 )
    #38966780
dimitr
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
насколько я понимаю, ошибка именно в выводе ISQL на экран. Сам по себе нулевой байт в середине строки хоть и заноза в заднице, но абсолютно валиден.
...
Рейтинг: 0 / 0
FB2.5 - VARCHAR, содержащие ASCII_CHAR( 0 )
    #38967064
Polesov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Привет всем.

Ниже пояснения по старттопику.

Вводная:

Имеются внешние текстовые данные, которые по связке с неким критерием заносятся в базу через хранимую процедуру.
Соответственно, в связке с этим неким критерием возможны следующие ситуации:
- внешние данные отсутствуют: при этом в БД пишется NULL;
- внешние данные содержат пустую стоку: при этом в БД пишется пустая строка;
- внешние данные введены: при этом в БД пишется строка, обработанная некой UDF.

Объявление UDF:

Код: plsql
1.
2.
3.
4.
DECLARE EXTERNAL FUNCTION SOME_UDF
    CSTRING(8192)
RETURNS CSTRING(8192) FREE_IT
ENTRY_POINT 'EntryPoint' MODULE_NAME 'ModuleName.dll';



Естественно, при наличии во входной строке нулевого символа происходила потеря данных.

Решение проблемы – реализация передачи входного параметра типом VARCHAR BY DESCRIPTOR:

Код: plsql
1.
2.
3.
4.
5.
DECLARE EXTERNAL FUNCTION SOME_UDF
    VARCHAR(8192) BY DESCRIPTOR,
    VARCHAR(8192) BY DESCRIPTOR
RETURNS PARAMETER 2
ENTRY_POINT 'EntryPoint' MODULE_NAME 'ModuleName.dll';


Структура описания параметра:

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
  TDSC = packed record
    dsc_dtype : byte;
    dsc_scale : shortint;
    dsc_length : word;
    dsc_sub_type : smallint;
    dsc_flags : word;
    dsc_address : pointer;
  end;



Для типа VARCHAR dsc_address в первых 2-х байтах содержит такое же значение, как и результат функции CHAR_LENGTH(), т.е. реальную длину без учета нулевых символов. При этом надо, что бы входная строка передавалась именно типом VARCHAR (dsc_dtype = 3), что обеспечивается преобразованием
Код: plsql
1.
CAST( STR_VALUE AS VARCHAR(8192) )



Кстати, при таком решении логику на равенство параметра пустому значению или на IS NULL можно перенести в саму UDF.

Данные для просмотра строк с нулевым символом можно вытаскивать через
Код: plsql
1.
REPLACE( STR_VALUE, ASCII_CHAR(0), ASCII_CHAR(16) )



С уважением, Polesov.
...
Рейтинг: 0 / 0
12 сообщений из 12, страница 1 из 1
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / FB2.5 - VARCHAR, содержащие ASCII_CHAR( 0 )
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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