Страница 1 из 1
Проблема с UDF возвращающие Blob
Добавлено: 04 май 2005, 11:31
_so_
Есть много udf состоящие напрмер:
DECLARE EXTERNAL FUNCTION BCOMMAUNION
BLOB,
BLOB,
BLOB
RETURNS PARAMETER 3
ENTRY_POINT 'BCommaUnion' MODULE_NAME 'oeudf.dll';
Так вот обнаружилось на Ib7.1 sp2 и Ib 7.5, что если второй парметр передается null, то UDF всегда возвращает null. Вне зависимости от того что пишем в udf.
Проверил на FB1.5 emb работает правильно. Кто встречал это и как с этим бороться?
Добавлено: 04 май 2005, 11:43
kdv
твоя udf, тебе и отлаживать.
Добавлено: 04 май 2005, 16:35
_so_
Да не из-за udf похоже дело. В FB работает и 6.0 раньше точно работало.
Если внутри UDF вызвать с параметром
BCOMMAUNION (<Парметрй>, StrToBlob('')) , то тоже работает.
Добавлено: 04 май 2005, 16:55
_so_
Поставили debug. Из debug видно, что в blob пишется не пустая строка, а blob возвращает null.
Вот например реализация:
Код: Выделить всё
type
PBlob = ^TBlob;
TBlob = record
GetSegment: function(Handle: pointer; Buffer: PChar; MaxLength: integer; var ReadLength: integer): WordBool; cdecl;
Handle: pointer; // handle
SegCount, // number of segments
MaxSegLength, // max length of segment
TotalLength: integer; // total blob length
PutSegment: procedure(Handle: pointer; Buffer: PChar; Length: integer); cdecl;
end;
const
MaxBlobPutLength = 80;
MaxVarCharLength = 32767;
MaxResultStringLength = 8190;
{ udfs }
function FillBuffer(var Blob: TBlob; Buf: PChar; FreeBufLen: integer; var ReadLen: Integer): boolean;
var
EndOfBlob: boolean;
FreeBufLenX, GotLength: integer;
begin
try
ReadLen := 0;
repeat
GotLength := 0; { !?! }
if FreeBufLen > MaxBlobPutLength
then FreeBufLenX := MaxBlobPutLength
else FreeBufLenX := FreeBufLen;
with Blob do
EndOfBlob := not GetSegment(Handle, Buf+ReadLen, FreeBufLenX, GotLength);
Inc(ReadLen, GotLength);
Dec(FreeBufLen, GotLength);
until EndOfBlob or (FreeBufLen = 0);
except
EndOfBlob := True;
end;
Buf[ReadLen] := #0;
Result := EndOfBlob;
end;
function ReadBlob(var Blob: TBlob): string;
var
ReadLen: Integer;
begin
with Blob do
if Assigned(Handle) and (TotalLength > 0) then
begin
SetLength(Result, TotalLength);
FillBuffer(Blob, PChar(Result), TotalLength, ReadLen);
SetLength(Result, ReadLen);
end else
Result := '';
end;
procedure WriteBlob(var Blob: TBlob; const S: string);
var
SLen, PutLen: integer;
PS: PChar;
begin
SLen := length(S);
PS := PChar(S);
if not Assigned(Blob.Handle) then
Exit;
if SLen = 0 then
begin
PutLen := 0;
with Blob do
PutSegment(Handle, PS, PutLen);
end else
begin
while SLen > 0 do
begin
if SLen > MaxBlobPutLength then
PutLen := MaxBlobPutLength
else
PutLen := SLen;
with Blob do
PutSegment(Handle, PS, PutLen);
dec(SLen, PutLen);
inc(PS, PutLen);
end;
end;
end;
procedure BCommaUnion(Comma1, Comma2, Res: PBlob);
begin
WriteBlob(Res^, ReadBlob(Comma1^) + ReadBlob(Comma2^));
end;
Теперь если вызвать:
select BlobToStr(BCOmmaUnion(StrToBlob('800'), Props)) as Props from classes where Props is null
То возвращает в клонке refs пустые строки.
select BlobToStr(BCOmmaUnion(StrToBlob('800'), StrToBlob(BlobToStr(Props)))) as Props from classes where Props is null
То возвращает правильно '800'
Отлаживать здесь нечего все udf работают чере одни и те же фунции
ReadBlob и WriteBlob.
Добавлено: 04 май 2005, 18:14
kdv
Поставили debug. Из debug видно,
что поставили? я имел в виду отладить функцию в отладчике Delphi.
Отлаживать здесь нечего
ну не знаю. я бы посмотрел...
Добавлено: 05 май 2005, 15:28
_so_
Уговорил и что я увидел в параметр Res приходит блоб с handle равным 0.
Если перестроить запрос на:
Код: Выделить всё
select BlobToStr(BCOmmaUnion(Props, StrToBlob('800'))) as Props from classes where Props is null
То тоже все работает. Явный глюк IB. Может Dimitr что-нибудь скажет исправляли что-то похожее в FB.
Добавлено: 06 май 2005, 08:45
dimitr
увы, ничего такого не припоминаю. Если на FB1.0 тоже работает, то мы тут не причем, иначе и вправду фиксилось.
Добавлено: 06 май 2005, 11:09
_so_
Что делать-то не использовать udf в которых последний параметр и резулбтирующий параметр равен blob?
Я препоминаю раньше мы и со строками работали также через параметр в UDF, и там были похожие глюки (я помнится писал kdv на support). Переписали все через функции, но с блобами так нельзя.
Может кто-нибудь напишет в Borland (плохо у меня с английским, а то сам бы давно написал).
Добавлено: 06 май 2005, 11:11
kdv
я увидел в параметр Res приходит блоб с handle равным 0.
давай почетче сформулируем. То есть, при передаче null вместо второго параметра, при входе в udf получаем третий параметр пустой?
Добавлено: 06 май 2005, 11:42
_so_
Да утретьего параметра (результирующего) блоба handle равен нулю. Поэтому писать как бы не куда. И следвательно udf возвращает null.