Search code examples
delphi-2009tdataset

How can I read a whole record at once from a TDataSet?


I am fetching data from a mySQL database using a query (actually a TMyQuery from Devart, inherited from a TDataSet). Usually I process one field at a time inside a while not eof loop using fieldbyname().

As some processing is complex I'd like instead to fetch the whole record and pass that to a procedure to do the processing of each field away from the loop.

I think it might be to do with the GetCurrentRecord() method which seems to return a pointer to Byte if it's overridden but then I'm not clear on how to extract my fields from that pointer.

If this is possible to do, please can someone show me the syntax to fetch one whole record, pass it as a parameter and then extract each field?

The structure of the code I usually use

Procedure ProcessTable;
begin
    Query1.SQL.Clear;
    Query1.SQL.Add(SQL);
    Query1.Open;
    Query1.first ;
    while not Query1.Eof  do
       begin
           var1 :=  Query1.FieldByName('field1').AsString;
           var2 := Query1.FieldByName('field2').AsInteger;
           //etc.
           Query1.Next;
       end;
    Query1.close;  
end;

Pseudo code of what I would like to do

procedure ProcessRecord( TheRecord : PByte );
begin
    ..
    <extract the fields from TheRecord and process them>
    ..
end;

Procedure ProcessTable;
var 
   buffer : PByte;
begin
    Query1.SQL.Clear;
    Query1.SQL.Add(SQL);
    Query1.Open;
    Query1.first ;
    while not Query1.Eof  do
       begin
       buffer := Query1.GetCurrentRecord;
       ProcessRecord(buffer);
       Query1.Next;
       end;
    Query1.close
end;

Solution

  • The solution is not to try to pass a pointer to a buffer containing the record in question but to pass the whole query object. Then the relevant records can simply be recovered with FieldByName() as usual. The query object contains within it the position of the record currently pointed at so it doesn't need extracting into a buffer first.

    So the solution, using the same pseudocode is.

    procedure ProcessRecord( TheRecord : TQuery );
    var
      var1 : string;
      var2 : integer;
    begin
      var1 := TheRecord .FieldByName('field1').AsString;
      var2 := TheRecord .FieldByName('field2').AsInteger;
      <process var1 and var 2>
    end;
    
    Procedure ProcessTable;
    begin
        Query1.SQL.Clear;
        Query1.SQL.Add(SQL);
        Query1.Open;
        Query1.first ;
        while not Query1.Eof  do
           begin
           ProcessRecord(Query1); //pass the whole query object as type TQuery 
                                  //(or in my specific case, of type TmyQuery         Query1.Next;
           end;
        Query1.close
    end;