Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2003.08.21;
Скачать: CL | DM;

Вниз

Надо сохранить значение ЛЮБОГО поля TpFIBQuery в поток(Stream)   Найти похожие ветки 

 
VID ©   (2003-07-26 23:07) [0]

подробней:
Q:TpFIBQuery;
выполняем запрос SELECT-SQL с помощью этого Q.
Допустим возвращается выборка состоящая их N записей и трёх полей.
Первое поле, допустим, Varchar, второе INTEGER а третье - ваще BLOB
так вот необходимо решение, что бы значение любого из этих полей (да и вообще значения любых полей, а не только этих трёх, возвращаемых запросом Q) сохранить в Stream:TMemoryStream;
Как это сделать ?
Скажу сразу что метод Q.FieldByName["FIELD1"].SaveToStream(); работает только если FIELD1 - блоб-поле...


 
Pat ©   (2003-07-26 23:27) [1]

Как я понял основная проблема - это работа с потоками. Копай в эту сторону.


 
VID ©   (2003-07-26 23:36) [2]

хм... в общем то, копать конечно можно...
я просто думал может у кого есть уже откопанное решение...
а так вообще то я знаю, что взависимости от того что хранится в конкретном поле Q (null, string, non-string, blob) метод записи в поток будет отличаться...
Просто надеюсь у кого-нибудь есть универсальное решение...


 
Serg Vostrikov   (2003-07-27 10:41) [3]

Совсем универсального нет. А суть метода в общем-то проста. Основной поток, в который ты сохраняешь, разделяется на несколько частей вида
[type_id], [size], [data]

То есть, скажем что-то вроде:

var vWord : WORD;
vStr: string;

for Index := 0 to pred(pFIBQuery1.FieldCount) do begin
case pFIBQuery1.Fields[Index].SQLType and (not 1) of
SQL_TEXT: begin
vWord := 1; // varchar type_id
Stream.WriteBuffer(vWord, 2);
vStr := pFIBQuery1.Fields[Index].AsString;
Stream.WriteBuffer(length(vStr), 2);
( vStr[1], Length(S) Совсем универсального нет. А суть метода в общем-то проста. Основной поток, в который ты сохраняешь, разделяется на несколько частей вида
[type_id], [size], [data]

То есть, скажем что-то вроде:

var vWord : WORD;
vStr: string;

for Index := 0 to pred(pFIBQuery1.FieldCount) do begin
case pFIBQuery1.Fields[Index].SQLType and (not 1) of
SQL_TEXT: begin
vWord := 1; // varchar type_id
Stream.WriteBuffer(vWord, 2);
vStr := pFIBQuery1.Fields[Index].AsString;
Stream.WriteBuffer(length(vStr), 2);
Stream.WriteBuffer(vStr[1], Length(S));
end;
SQL_...
end;
end;

Пишу навскидку, но общая идея, думаю, ясна. Читать, ес-но, в обратном порядке - взял два байта - получил тип поля, взял еще два - получил размер нужного буфера. Прочитал буфер. В засимости от типа поля проинтерпретировал как нужно и записал куда нужно.


 
VID ©   (2003-07-27 22:54) [4]

итак я написал такую функцию по сохранению данных любого поля в поток.
просмотрите, исправьте, пожалуйста, и обратите внимание на комментарии - там мои вопросы.

Function TDM.SaveFieldValueToStream(Query:TpFIBQuery; FieldIndex:Integer; Stream:TStream):Boolean;
Var DataType, DataSize:Integer;
P:Pointer;
S:String;
begin
Result := False;
IF Query = nil then exit;
IF Stream = nil then exit;
IF (FieldIndex<0) or (FieldIndex > Query.FieldCount-1) then Exit;
IF Query.Fields[FieldIndex].IsNull then Exit;

DataSize := Query.Fields[FieldIndex].Size;
DataType := Query.Fields[FieldIndex].SQLType;
Stream.Position := 0;
try
IF DataType=SQL_BLOB then
Query.Fields[FieldIndex].SaveToStream(Stream)
else
begin
//Если поле - VARCHAR то DataType почему то не SQL_TEXT а именно SQL_VARYING
IF DataType = SQL_VARYING then
begin
S:=Query.Fields[FieldIndex].AsString;
DataSize := Length(S);
Stream.Write(S[1], DataSize);
end
else
begin
GetMem(P, DataSize);
try
{Здесь я скопировал данные из поля в P
Понятно что P- указатель, но вот вопрос:
Если GetMem создал новую область памяти как я просил
то возникла ли вторая копиия данных хранимых в поле
(из-за CopmyMemory) или нет ? или может просто P теперь указывает
на тот же адресс что и Query.Fields[FieldIndex].AsPointer а второй копии
данных не появилось ?}
CopyMemory(P, Query.Fields[FieldIndex].AsPointer, DataSize);
Stream.Write(P^, DataSize);
finally
( P) итак я написал такую функцию по сохранению данных любого поля в поток.
просмотрите, исправьте, пожалуйста, и обратите внимание на комментарии - там мои вопросы.

Function TDM.SaveFieldValueToStream(Query:TpFIBQuery; FieldIndex:Integer; Stream:TStream):Boolean;
Var DataType, DataSize:Integer;
P:Pointer;
S:String;
begin
Result := False;
IF Query = nil then exit;
IF Stream = nil then exit;
IF (FieldIndex<0) or (FieldIndex > Query.FieldCount-1) then Exit;
IF Query.Fields[FieldIndex].IsNull then Exit;

DataSize := Query.Fields[FieldIndex].Size;
DataType := Query.Fields[FieldIndex].SQLType;
Stream.Position := 0;
try
IF DataType=SQL_BLOB then
Query.Fields[FieldIndex].SaveToStream(Stream)
else
begin
//Если поле - VARCHAR то DataType почему то не SQL_TEXT а именно SQL_VARYING
IF DataType = SQL_VARYING then
begin
S:=Query.Fields[FieldIndex].AsString;
DataSize := Length(S);
Stream.Write(S[1], DataSize);
end
else
begin
GetMem(P, DataSize);
try
{Здесь я скопировал данные из поля в P
Понятно что P- указатель, но вот вопрос:
Если GetMem создал новую область памяти как я просил
то возникла ли вторая копиия данных хранимых в поле
(из-за CopmyMemory) или нет ? или может просто P теперь указывает
на тот же адресс что и Query.Fields[FieldIndex].AsPointer а второй копии
данных не появилось ?}
CopyMemory(P, Query.Fields[FieldIndex].AsPointer, DataSize);
Stream.Write(P^, DataSize);
finally
FreeMem(P);
end;
end;
end;
Result := True;
except end;
end;



Страницы: 1 вся ветка

Текущий архив: 2003.08.21;
Скачать: CL | DM;

Наверх




Память: 0.49 MB
Время: 0.012 c
6-68428
Manfred
2003-06-14 01:51
2003.08.21
Ожидание ответа сервера.


1-68391
Igor Popov
2003-08-07 03:32
2003.08.21
Как создать контекстную справку для компонентов на форме?


14-68530
Сергеич
2003-08-05 11:56
2003.08.21
Столкнулся с любопытной пробл.


14-68476
Карлсон
2003-08-06 00:39
2003.08.21
Перекодировка DVD


14-68542
rosl
2003-08-02 09:12
2003.08.21
install shield