Board index » delphi » Delphi patch makes working code go bad!

Delphi patch makes working code go bad!

Hi everyone.

Here is a piece of code that is working fine (and that has been working for
a long time) but that suddenly stopped working after I installed the Borland
6.01 "fixed" patch (the second one that was released). I'm using Delphi 6
Professional on Win98.

What the code does is that it retrieves a "MDHeader" from an Access97
database. A MDHeader is a 711 bytes long packed record saved into the Memo
field "Header" of the table "Headers".

Saving the whole MDHeader as one field of a table saves me from having to
create the 66 fields that describe that MDHeader.

To retreive the header:
 - I read the Memo field "Header" into the string sHeader
 - Then i convert that string to a MDHeader using a memory stream (see below
StrToTMDHeader)

Now with the Borland patch installed, the FieldByName('Header').AsString
only retrieves the first field of the header (i.e. MachineName) into
sHeader.

There may or may not be a null character in the MachineName.

Does anybody have an idea of what's going on?
Is it my code or the patch?
Do you know any other way to save and retrieve a packed record in a single
Access field?

Thanks a lot.
Eric

Here's the code.
procedure TfrmViewChannelsDialog.btnViewClick(Sender: TObject);
var
  sHeader: string;
  aHeader: TMDHeader;
begin
...
  // Read Header from DB
  with TADODataset.Create(nil) do begin
    Close;
    Connection := ViewDataConnection;
    CursorLocation := clUseServer;
    CommandText := 'SELECT * FROM Headers ORDER BY RecNum ASC';
    Open;
    Last;
    SetLength(sHeader, cHeaderSize);
    sHeader := FieldByName('Header').AsString;
    aHeader := StrToTMDHeader(sHeader);
    Close;
    Free;
  end;
...
end;

// Conversion function String to MDHeader
function StrToTMDHeader(Str: string): TMDHeader;
var
  msTemp: TMemoryStream;
begin
  msTemp := TMemoryStream.Create;
  msTemp.Write(Str[1], cHeaderSize);
  msTemp.Seek(0, soFromBeginning);
  msTemp.read(Result, cHeaderSize);
  msTemp.Free;
end;

//Data types
TName = array [1..32] of Char;
TCode = array [1..24] of Char;

TMDHeader = packed record
  MachineName:               TName;
  SerialNo:                  Word;
  LaunchDate:                Longword;
  LoopWhenFullDE:            Byte;
  UserCodeDE:                Byte;
  MotionSensorDE:            Byte;
  VibrationStop:             Word;
  StopCodesDNEx:             Byte;
  ActivityCodesDNEx:         Byte;
  StopCodeNames:             array [0..9] of TCode;
  ActivityCodeNames:         array [0..9] of TCode;
  GpsMode:                   Byte;
  GpsTimeBtwRec:             Word;
  GpsDistBtwRec:             Word;
  SpeedDE:                   Byte;
  SpeedTimeBtwRec:           Word;
  SpeedChangeToRec:          Byte;
  GpsMaxSpeed:               Word;
  ChannelMode:               array [1..4] of Byte;
  ChannelNames:              array [1..4] of TName;
  Channels12DU:              Byte;
  Channels34DU:              Byte;
  ChannelOC:                 array [1..4] of Byte;
  ChannelValues:             array [1..4, 1..2] of Word;
  MulFactors:                array [1..4] of Single;
  PromptChannel:             Byte;
  PromptTimeOut:             Word;
  PrePromptTime:             Word;
end;

cHeaderSize = SizeOf(TMDHeader);

 

Re:Delphi patch makes working code go bad!


Quote
> To retreive the header:
>  - I read the Memo field "Header" into the string sHeader
>  - Then i convert that string to a MDHeader using a memory stream (see
below
> StrToTMDHeader)

Why didn't you use a Blob field? In my opinion i think you should.. it's
weird to save RAW data into a string. Besides it's easier...

I made 3 methods that may help you:

ReadFromBlob
WriteToBlob
BlobSize

I have used this 3 methods long ago and they work perfectly....
ReadFromBlob and WriteToBlob, works perfectly with everything.. but if you
don't know the size of the data you want to retrieve (for example a dinamyc
array, WICH IS NOT YOUR CASE), you must use BlobSize. Because in BatchUpdate
mode the size of blobs sometimes are 0.
In your case on aSize just pass the sizeof(TMDHeader) and you're done.

Procedure ReadFromBlob(aBlobField:TBlobField;var aBuffer;aSize:Longint);
var lStream:TMemoryStream;
begin
 if assigned(aBlobField) then begin
   lStream := TMemoryStream.Create;
   try
     lStream.Seek(0,soFromBeginning);
     aBlobField.SaveToStream(lStream);
     lStream.Seek(0,soFromBeginning);
     lStream.Read(aBuffer,aSize);
   finally
     lStream.Free;
   end;
 end;
end;

Procedure WriteToBlob(aBlobField:TField;const aBuffer;const aSize:Longint);
var lStream:TMemoryStream;
begin
  if assigned(aBlobField) then begin
    if aSize>0 then begin
      lStream := TMemoryStream.Create;
      try
        lStream.seek(0,soFromBeginning);
        lStream.Write(aBuffer,aSize);
        (aBlobField as TBlobField).Clear;
        lStream.seek(0,soFromBeginning);
        (aBlobField as TBlobField).LoadFromStream(lStream);
      finally
        lStream.Free;
      end;
    end else
      (aBlobField as TBlobField).Clear;
  end;
end;

Function BlobSize(aBlobField:TField):Longint;
var lStrm:TMemoryStream;
begin
  lStrm:=TMemoryStream.Create;
  try
    (aBlobField as TBlobField).SaveToStream(lStrm);
    Result:=lStrm.Size;
  finally
    lStrm.Free;
  end;
end;

Emiliano Sosa
emis...@hotmail.com
Sierra S.R.L.
www.gosierra.com

Other Threads