[View Borland Home Page][View Product List][Search This Web Site][View Available Downloads][Join Borland Online][Enter Discussion Area][Send Email To Webmaster]

BDE API Examples (DbiReadBlock, DbiWriteBlock, DbiSetFieldMap)

(DbiReadBlock)Reads a specified number of records (starting from the next position of the cursor) into a buffer.
(DbiSetFieldMap)Sets a field map of the table associated with the given cursor.
(DbiWriteBlock)Writes a block of records to the table associated with the cursor.

Move data from one table to another table with a different structure in the fastest way possible.

This example uses the following input:
MoveFast(STable, DTable, [2, 3, 5], [4, 1, 7], 1024000);
NOTE: This procedure will take two tables of the same type and move data between the two even if they have a different structure. The above input example maps source table fields 2, 3 and 5 to 4, 1 and 7 respectively. The matching fields must be of same type and size because no field level translation is being done. Changing the BlockSize parameter can have an effect of speed. If you are moving massive amounts of data and have plenty of RAM in the machine, experiment with increasing the BlockSize parameter.
procedure MoveFast(SourceTable, DestTable: TTable; const SourceMap,
             DestMap: array of word; BlockSize: longint);
var
  pRecBuffs: pBYTE;
  TotalSize, Records, RecordsToRead, RecordsProcessed: longint;
  pSMapFields, pSFields, pDMapFields, pDFields, pD, pS: pFLDDesc;
  MapFieldCount, B: byte;
  Props: CURProps;


begin
  if sizeof(SourceMap) <> sizeof(DestMap) then
    raise EDatabaseError.Create('Source and destination field mappings must be same in size');

  pRecBuffs := nil;  pSFields := nil; pSMapFields := nil;
  pDFields := nil; pDMapFields := nil; RecordsProcessed := 0;
  try
    Check(DbiSetToBegin(SourceTable.Handle));

    MapFieldCount := sizeof(SourceMap) div sizeof(WORD);
    pSMapFields := AllocMem(MapFieldCount * sizeof(FLDDesc));

    pSFields := AllocMem(SourceTable.FieldCount * sizeof(FLDDesc));
    Check(DbiGetFieldDescs(SourceTable.Handle, pSFields));
    // Create the source field mappings...
    for B := 0 to MapFieldCount - 1 do
    begin
      Inc(pSFields, SourceMap[B] - 1);
      Move(pSFields^, pSMapFields^, sizeof(FLDDesc));
      Inc(pSMapFields);
      Dec(pSFields, SourceMap[B] - 1);
    end;
    Dec(pSMapFields, MapFieldCount);

    pDMapFields := AllocMem(MapFieldCount * sizeof(FLDDesc));

    pDFields := AllocMem(DestTable.FieldCount * sizeof(FLDDesc));
    Check(DbiGetFieldDescs(DestTable.Handle, pDFields));
    // Create the destination field mappings...
    for B := 0 to MapFieldCount - 1 do
    begin
      Inc(pDFields, DestMap[B] - 1);
      Move(pDFields^, pDMapFields^, sizeof(FLDDesc));
      Inc(pDMapFields);
      Dec(pDFields, DestMap[B] - 1);
    end;
    Dec(pDMapFields, MapFieldCount);
    // Check all fields to make sure they are comparable types and sizes...
    pS := pSMapFields;
    pD := pDMapFields;
    for B := 1 to MapFieldCount do
    begin
      if pS^.iFldType <> pD^.iFldType then
         raise EDatabaseError.Create('Source field: ' + pS^.szName + ' Type (' +
            IntToStr(pS^.iFldType) + ') is not the same base type as the ' +
            'destination field: ' + pD^.szName + ' Type (' +
            IntToStr(pD^.iFldType) + ')');
      if (pS^.iUnits1 <> pD^.iUnits1) or  (pS^.iUnits1 <> pD^.iUnits1) then
         raise EDatabaseError.Create('Source field size: ' + pS^.szName + ' Size (' +
            IntToStr(pS^.iUnits1) + ', ' + IntToStr(pS^.iUnits1) +
            ') is not the same base type as the destination size: ' + pD^.szName + ' Size (' +
            IntToStr(pD^.iUnits1) + ', ' + IntToStr(pD^.iUnits1) + ')');
      Inc(pS);
      Inc(pD);
    end;
    // Set the field maps on the tables...
    Check(DbiSetFieldMap(SourceTable.Handle, MapFieldCount, pSMapFields));
    Check(DbiSetFieldMap(DestTable.Handle, MapFieldCount, pDMapFields));

    Check(DbiGetCursorProps(DestTable.Handle, Props));

    // Determine the amount of records that can be move in the block size given...
    Check(DbiGetRecordCount(SourceTable.Handle, Records));
    TotalSize := Props.iRecBufSize * Records;
    if TotalSize < BlockSize then
      BlockSize := TotalSize;
    RecordsToRead := BlockSize div Props.iRecBufSize;
    pRecBuffs := AllocMem(BlockSize * sizeof(BYTE));
    // Read and write the data...
    while RecordsToRead > 0 do
    begin
      Check(DbiReadBlock(SourceTable.Handle, RecordsToRead, pRecBuffs));
      Check(DbiWriteBlock(DestTable.Handle, RecordsToRead, pRecBuffs));
      Inc(RecordsProcessed, RecordsToRead);
      if RecordsToRead > (Records - RecordsProcessed) then
        RecordsToRead := (Records - RecordsProcessed);
    end;

  finally
    if pRecBuffs <> nil then
      FreeMem(pRecBuffs);
    if pSFields <> nil then
      FreeMem(pSFields);
    if pSMapFields <> nil then
      FreeMem(pSMapFields);
    if pDFields <> nil then
      FreeMem(pDFields);
    if pDMapFields <> nil then
      FreeMem(pDMapFields);

    Check(DbiSetFieldMap(SourceTable.Handle, 0, pSFields));
    Check(DbiSetFieldMap(DestTable.Handle, 0, pDFields));    
  end;
end;

Back to BDE API Reference Page


DISCLAIMER: You have the right to use this technical information subject to the terms of the No-Nonsense License Statement that you received with the Borland product to which this information pertains.
Trademarks & Copyright © 1998 Borland International, Inc.