Search code examples
delphibde

iRecords variable no change after execute DbiWriteBlock function


The value of iRecords variable no change after execute DbiWriteBlock function. Please explain this to me. Thanks!

This is my code:

procedure TMainForm.btnBDICheckClick(Sender: TObject);
var
  Table       : TTable;
  PTable      : PByte;
  RecordSize  : Integer;
  RecordCount : Integer;
  iRecords    : Integer;
begin
  Table              := TTable.Create(Self);
  Table.DatabaseName := 'D:\Temp';
  Table.TableName    := 'SrcTable.db';
  Table.Active       := True;

  RecordSize  := Table.RecordSize;
  RecordCount := Table.RecordCount;

  PTable   := nil;
  iRecords := 0;

  GetMem(PTable, RecordSize * RecordCount);
  DbiWriteBlock(Table.Handle, iRecords, PTable);

  // iRecords = 0 at here

  Table.Close;
end;

Solution

  • Variable iRecords is a pointer to the number of records to be written. On output, iRecords will have the actual number of records written. Your code should look like this:

    procedure TMainForm.btnBDICheckClick(Sender: TObject);
    var
      Table       : TTable;
      PTable      : PByte;
      RecordSize  : Integer;
      RecordCount : Integer;
      iRecords    : Integer;
    begin
       Table              := TTable.Create(Self);
       Table.DatabaseName := 'D:\Temp';
       Table.TableName    := 'SrcTable.db';
       Table.Active       := True;
    
       RecordSize  := Table.RecordSize;
       RecordCount := Table.RecordCount;
    
       //PTable   := nil;
       //iRecords := 0;
    
       iRecords := RecordCount;
       GetMem(PTable, RecordSize * RecordCount);
       DbiWriteBlock(Table.Handle, iRecords, PTable);
    
       Table.Close;
       ShowMessage('Records: ' + IntToStr(iRecords));
    end;
    

    With this code you will add empty records. Use DbiInitRecord() and DbiPutField() to fill field values.

    Below is the documentation about the DbiWriteBlock function (from BDE help file):

    Function definition:

    function DbiWriteBlock (hCursor: hDBICur; var iRecords: Longint; pBuf: Pointer): DBIResult stdcall;
    

    Description:

    DbiWriteBlock writes a block of records to the table associated with hCursor.

    Parameters:

    hCursor Type: hDBICur (Input) Specifies the cursor handle to the table.
    piRecords Type: pUINT32 (Input/Output) On input, piRecords is a pointer to the number of records to write. On output, pointer to the client variable that receives the actual number of records written. The number actually written may be less than requested if an integrity violation or other error occurred.
    pBuf Type: pBYTE (Input) Pointer to the buffer containing the records to be written.
    

    Usage:

    This function is similar to calling DbiAppendRecord for the specified number of piRecords. DbiWriteBlock can access data in blocks larger than 64Kb, depending on the size you allocate for the buffer.

    Note:

    This function cannot be used if the records contain non-empty BLOBs.

    Paradox:

    This function verifies any referential integrity requirements or validity checks that may be in place. If either fails, the write operation is canceled.

    Completion state:

    The cursor is positioned at the last record that was inserted.

    Result:

    DbiResult                   Meaning
    DBIERR_NONE                 The block of records contained in pBuf has been successfully written to the table specified by hCursor.
    DBIERR_INVALIDHNDL          The specified cursor handle is invalid or NULL, or piRecords is NULL, or pBuf is NULL.
    DBIERR_TABLEREADONLY        The table is opened read-only; cannot write to it.
    DBIERR_NOTSUFFTABLERIGHTS   Insufficient table rights to insert a record. (Paradox only.)
    DBIERR_NODISKSPACE          Insertion failed due to insufficient disk space.
    

    Example from Delphi 7 help:

    procedure fDbiWriteBlock(Customer: TTable; var RecordsToInsert: Longint);
    
    var
      pRecordsBuf, pTmpBuf: pBYTE;
      Rec: Longint;
      CustNo: Double;
    begin
      Randomize;
      GetMem(pRecordsBuf, Customer.RecordSize * RecordsToInsert);
      pTmpBuf := pRecordsBuf;
      try
        for Rec := 1 to RecordsToInsert do begin
          CustNo := Random(1000000);
          // Iterate through the entire record buffer filling each
          // individual record with information
          with Customer do begin
            Check(DbiInitRecord(Handle, pTmpBuf));
    
            Check(DbiPutField(Handle, FieldByName('CustNo').Index + 1, pTmpBuf,
              pBYTE(@CustNo)));
            Check(DbiPutField(Handle, FieldByName('Company').Index + 1, pTmpBuf,
              PChar('INPRISE Corporation')));
            Inc(pTmpBuf, RecordSize);
          end;
        end;
        Check(DbiWriteBLock(Customer.Handle, RecordsToInsert, pRecordsBuf));
      finally
        FreeMem(pRecordsBuf, Customer.RecordSize * RecordsToInsert);
      end;
    end