UDF под Firebird 1.0.3

Access Violation, некорректное выполнение запросов или вызовов API, ошибки утилит командной строки, в общем все, что вам мешает работать

Модераторы: kdv, dimitr

Ответить
WildSery
Заслуженный разработчик
Сообщения: 1738
Зарегистрирован: 05 июн 2006, 16:19

UDF под Firebird 1.0.3

Сообщение WildSery » 24 янв 2007, 21:20

Сразу извиняюсь за версию сервера, просить поправить ничего не буду :wink: На 2.0 смотрел - там всё как надо работает.
Вечером уже глаз замылился, найти по теме ничего не могу (не там ищу?).
Вот значит какая загогулина:

Код: Выделить всё

insert into Table1 (id /* integer */, Blb /* BLOb */) values (1, 'какой-то текст');
insert into Table1 (id, Blb) values (2, null);
Процедура BLObToCString в UDFDEMO.
Если она работает просто как

Код: Выделить всё

select BLObToCString(Blb) from Table1 where id=1
union all
select BLObToCString(Blb) from Table1 where id=2
то всё пучком, первая строка 'какой-то текст', во второй строке - пустая строка.
А если в процедуре... Тут начинаются странности.

Код: Выделить всё

CREATE PROCEDURE TEST(
    ID INTEGER)
RETURNS (
    STR VARCHAR(255))
AS
begin
  select substring(BLObToCString(Blb) from 1 for 250) from Table1 where id=:id into Str;
  suspend;
end

select Str from TEST(1)
union all
select Str from TEST(2)
В результате в первой строке 'какой-то текст', и во второй тоже 'какой-то текст'.
Т.е. если в BLObToCString передаётся NULL, а результат пихается в переменную, то в ней оказывается последнее "не-NULL" значение.
Результат не меняется, если убрать substring, а размер выходной сделать максимальным объявленным в UDF (16383).

Теперь вопрос - можно ли как-то обойти это средствами самой UDF?
Такая же функция с дескрипторами, которая понимает NULL, у меня имеется, но на эту старую завязано порядка 140 процедур, очень не хочется их лопатить, да ещё нужно будет по скриптам и исходникам модулей смотреть, не зашито ли чего... :cry:

kdv
Forum Admin
Сообщения: 6595
Зарегистрирован: 25 окт 2004, 18:07

Сообщение kdv » 24 янв 2007, 21:57

udf можно отлаживать. в отладчике посмотри, что там приходит в виде блоба, если оно null.
могу быть неправ про функции с by descriptor, но там когда-то передавалась не серверная структура блоба, а клиентская, в результате это фактически не работало.

стоп. возможно это какая-то байда с blob_id. если да, то в FB 1.03 получается что ее побороть нельзя. все же, советую залезть в отладчик.

Dimitry Sibiryakov
Заслуженный разработчик
Сообщения: 1436
Зарегистрирован: 15 сен 2005, 09:05

Сообщение Dimitry Sibiryakov » 25 янв 2007, 07:40

А я еще посоветую попробовать этот запрос в isql.

WildSery
Заслуженный разработчик
Сообщения: 1738
Зарегистрирован: 05 июн 2006, 16:19

Сообщение WildSery » 25 янв 2007, 11:16

В isql отрабатывает идентично описанному.

Дмитрий, я под отладчиком гонял, пытаясь понять, почему так. Но суть не в этом. Такое поведение я тестировал так:

Код: Выделить всё

    with BLOb do
      if (not Assigned(Handle)) or (TotalLength=0) then begin
        CString[0]:='N';
        CString[1]:='u';
        CString[2]:='l';
        CString[3]:='l';
        CString[4]:='!';
        CString[5]:=#0;
        Exit;
      end;
Т.е. я BLOb трогал, только если там чего-то есть.
Отладчик показывает, что в эту ветку заходит в двух случаях, если блоб равен NULL и если равен пустой строке.
И присваивает вроде всё ок. Но вот только строка 'Null!' возвращается только если блоб на входе был пустая строка, а вот если на входе был NULL, то не возращается ничего (пустая строка!) если функцию вызывал просто селектом, и предыдущее значение, если через функцию.

Дописано 25.01.07 18:33
Кстати, я тут злобный хак попробовал, через rdb$functions и rdb$function_arguments заменил определение функций (чтобы не перекомпиливать 140 процедур), вроде работает, подводных камней тут нету, что скажете?

Ответить