Текущий архив: 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