Recent

Author Topic: access TDataset/TCSVDataset record values as constant array?  (Read 569 times)

msocorcim

  • New member
  • *
  • Posts: 8
With TCSVDataset, Is there a way to place a complete record into a dynamic array? It seems like that would be generally useful.

I pursued GetCurrentRecord( Buffer: TRecordBuffer ), but couldn't find out how to allocate/initialize memory for a buffer.


The object is to efficiently copy a large number of records to a new CSVDataset something like:

CSVDataSetDst.AppendRecord([NewField1Value, NewField2Value,NewField3Value, SrcRecordArray])

Thanks!

dje

  • Full Member
  • ***
  • Posts: 134
Re: access TDataset/TCSVDataset record values as constant array?
« Reply #1 on: July 19, 2022, 09:23:26 am »
Other people have asked and as far as I can see, the answer is no.

A search of the FreePascal source code shows, TDataSet.GetCurrentRecord(Buffer: TRecordBuffer): Boolean; is not implemented nor is it overrided by TDataSet derived classes.

ActiveBuffer "looks" promising, but a search of FreePascal source also shows TRecordBuffer is db format specific. ie: a Simple Move() instruction didn't work for me either by using MemSize() or RecordSize.

What you are after might (?) be possible via code like below (which doesnt work as is).

Code: Pascal  [Select][+][-]
  1. procedure DataSetCopy(ASrc, ADst: TDataSet);
  2. begin
  3.   ASrc.First;
  4.   while not ASrc.EOF do begin
  5.     ADst.Append;
  6.     Move(ASrc.ActiveBuffer^, ADst.ActiveBuffer^, ADst.RecordSize);
  7.     ADst.Post;
  8.     ASrc.Next;
  9.   end;
  10. end;

It would seem the problem is, record buffers were never implemented at the TDataSet level, so each derived class implemented it own record buffer system. The code for these caching systems, looks ultra hairy, so I wouldn't even think about a trying to batch copy via TRecordBuffer.

So, no.
« Last Edit: July 19, 2022, 09:25:23 am by derek.john.evans »

cdbc

  • Hero Member
  • *****
  • Posts: 1082
    • http://www.cdbc.dk
Re: access TDataset/TCSVDataset record values as constant array?
« Reply #2 on: July 20, 2022, 10:14:11 am »
Hi
Would this be an option:
{excerpt from TMemDataset}
Code: Pascal  [Select][+][-]
  1. Procedure TMemDataset.CopyFromDataset(DataSet : TDataSet; CopyData : Boolean);
  2. Var
  3.   I  : Integer;
  4.   F,F1,F2 : TField;
  5.   L1,L2  : TList;
  6.   N : String;
  7. begin
  8.   Clear(True);
  9.   // NOT from fielddefs. The data may not be available in buffers !!
  10.   for I:= 0 to Dataset.FieldCount-1 do begin
  11.     F:= Dataset.Fields[I];
  12.     // ææ special case for ftAutoInc fields 16.02.2020 /bc
  13.     if F.DataType = ftAutoInc then TFieldDef.Create(FieldDefs,F.FieldName,ftInteger,F.Size,F.Required,F.FieldNo)
  14.     else TFieldDef.Create(FieldDefs,F.FieldName,F.DataType,F.Size,F.Required,F.FieldNo);
  15.   end;
  16.   CreateTable;
  17.   if CopyData then begin
  18.     Open;
  19.     L1:= TList.Create;
  20.     try
  21.       L2:= TList.Create;
  22.       try
  23.         for I:= 0 to FieldDefs.Count-1 do begin
  24.           N:= FieldDefs[I].Name;
  25.           F1:= FieldByName(N);
  26.           F2:= DataSet.FieldByName(N);
  27.           L1.Add(F1);
  28.           L2.Add(F2);
  29.         end;
  30.         Dataset.DisableControls;
  31.         try
  32.           Dataset.Open;
  33.           while not Dataset.EOF do begin
  34.             Append;
  35.             for I:= 0 to L1.Count-1 do begin
  36.               F1:= TField(L1[i]);
  37.               F2:= TField(L2[I]);
  38.               case F1.DataType of
  39.                 ftString   : F1.AsString:= F2.AsString;
  40.                 ftBoolean  : F1.AsBoolean:= F2.AsBoolean;
  41.                 ftFloat    : F1.AsFloat:= F2.AsFloat;
  42.                 ftLargeInt : F1.AsInteger:= F2.AsInteger;
  43.                 ftSmallInt : F1.AsInteger:= F2.AsInteger;
  44.                 ftInteger  : F1.AsInteger:= F2.AsInteger;
  45.                 ftDate     : F1.AsDateTime:= F2.AsDateTime;
  46.                 ftTime     : F1.AsDateTime:= F2.AsDateTime;
  47.                 ftDateTime : F1.AsDateTime:= F2.AsDateTime;
  48.               end;
  49.             end;
  50.             try Post; except Cancel; Raise; end;
  51.             Dataset.Next;
  52.           end;
  53.         finally Dataset.EnableControls; end;
  54.       finally L2.Free; end;
  55.     finally L1.Free; end;
  56.   end;
  57. end;
Regards Benny
If it ain't broke, don't fix it ;)
PCLinuxOS(rolling release) 64bit -> KDE5 -> FPC 3.2.2 -> Lazarus 2.2.6 up until Jan 2024 from then on it's: KDE5/QT5 -> FPC 3.3.1 -> Lazarus 3.0

 

TinyPortal © 2005-2018