1. A report "Can''t read Buffer.Incorrect RecordNo" appeared on adding a new record to the database. An exception arose on trying to refresh an empty dataset.
function TRecordsCache.OldBuffer(RecordNo:integer): PChar;
begin
 if SaveChangeLog then
 begin
  if RecordNo<=FRecordCount then
   ReadRecordBuffer(RecordNo,FOldBuffer,True)
  else
   ClearOldBuffer
 end
 else
 begin
   if FOldBufRecordNumber<>RecordNo then
    if RecordNo<=FRecordCount then
     SaveOldBuffer(RecordNo)
    else
     ClearOldBuffer
 end;
 Result:=FOldBuffer
end;

procedure TRecordsCache.SaveOldBuffer(RecordNo: integer);
begin
 if SaveChangeLog then
   SaveToChangeLog(RecordNo)
 else
 begin
  if RecordNo<=FRecordCount then
   ReadRecord(RecordNo,FOldBuffer)
  else
   ClearOldBuffer;
  FOldBufRecordNumber:=RecordNo;
 end;
end;
2. Incorrect FullRefresh occurred with CacheModelKind=cmkLimitedBufferSize
unit FIBDataSet;

function TFIBCustomDataSet.RefreshAround(BaseQuery: TFIBQuery;var  
BaseRecNum:integer;
IgnoreEmptyBaseQuery:boolean = True;ReopenBaseQuery:boolean = True
):boolean;

procedure ExecCurSelect( aCurSelect:TFIBQuery; SourceObject:ISQLObject);
begin
     aCurSelect.Close;
     AssignSQLObjectParams(aCurSelect,[SourceObject]);
     aCurSelect.Params.AssignValues(FQSelect.Params);
     aCurSelect.ExecQuery;
end;

function FetchAround(aCurSelect:TFIBQuery; RecordsLimit:integer;  
Arrow:smallint;
   FromRecNum:integer =-1
):boolean;
var
   i:integer;
begin
     if FromRecNum=-1 then
      FCurrentRecord:=BaseRecNum
     else
      FCurrentRecord:=FromRecNum;
     i:=RecordsLimit;
     Result := False;
     while  (i>0) and (aCurSelect.Next<>nil)  do
     begin
       Result := True;
       Inc(FCurrentRecord,Arrow);
       FetchRecordToCache(aCurSelect, FCurrentRecord);
       if Arrow<0 then
       begin
        vPartition^.BeginPartRecordNo:=FCurrentRecord;
        if vPartition^.EndPartRecordNo=-1 then
         vPartition^.EndPartRecordNo:=vPartition^.BeginPartRecordNo
       end
       else
       begin
        vPartition^.EndPartRecordNo  :=FCurrentRecord;
        if vPartition^.BeginPartRecordNo=-1 then
         vPartition^.BeginPartRecordNo:=vPartition^.EndPartRecordNo;
       end;
       Dec(i);
     end;
     if aCurSelect.Eof then
      if Arrow<0 then
       vPartition^.IncludeBof:=True
      else
       vPartition^.IncludeEof:=True;
end;

var
    RecordSource  :ISQLObject;
    EmptyDataSet  :boolean;
    NotFetchedCount:integer;
begin
with BaseQuery do
begin
   if ReopenBaseQuery then
   begin
    Close;
    Params.AssignValues(FQSelect.Params);
    ExecQuery;
    Next;
    Result:=not Eof;
   end
   else
    Result :=RecordCount>0;

end;

EmptyDataSet :=True;

if Result or (not IgnoreEmptyBaseQuery) then
begin
     if BaseRecNum<(FCacheModelOptions.FBufferChunks div 2) then
      BaseRecNum:=FCacheModelOptions.FBufferChunks div 2;

     if Result then
     begin
       EmptyDataSet     :=False;
       FetchRecordToCache(BaseQuery, BaseRecNum);
       vPartition^.BeginPartRecordNo:=BaseRecNum;
       vPartition^.EndPartRecordNo  :=BaseRecNum;
       RecordSource:=BaseQuery
     end
     else
     begin
      RecordSource:=Self;
     end;

     vPartition^.IncludeBof:=False;
     vPartition^.IncludeEof:=False;

     ExecCurSelect(FQSelectDescPart,RecordSource);
     ExecCurSelect(FQSelectPart,RecordSource);
     if not Result then
     begin
      vPartition^.BeginPartRecordNo:=-1;
      vPartition^.EndPartRecordNo  :=-1;
     end;

     if FetchAround(FQSelectDescPart,FCacheModelOptions.FBufferChunks div  
2,-1) then
      EmptyDataSet:=False;

     if not Result then
      Dec(BaseRecNum);

     NotFetchedCount:=FCacheModelOptions.FBufferChunks-(vPartition^.EndPartRecordNo-vPartition^.BeginPartRecordNo+2);
     if FetchAround(FQSelectPart,NotFetchedCount,1) then
      EmptyDataSet:=False;

     NotFetchedCount:=FCacheModelOptions.FBufferChunks-(vPartition^.EndPartRecordNo-vPartition^.BeginPartRecordNo+2);
     if NotFetchedCount>0 then
      FetchAround(FQSelectDescPart,NotFetchedCount,-1,vPartition^.BeginPartRecordNo);

     FQSelectDescPart.Close;

     if  Result then
      FCurrentRecord:=BaseRecNum
     else
     if EmptyDataSet then
      FCurrentRecord:=-1
     else
      FCurrentRecord:=BaseRecNum+1;
     FQCurrentSelect:=FQSelectPart ;

     BaseQuery.Close;
end;
end;
3. Local sorting and the CloneCurRecord method did not work.
unit FIBDataSet;

procedure GetInspectRecBuffer;
var
   dsState:TDataSetState;
begin
    dsState:=State;
    Allocated:=
     (dsState<>dsCalcFields) and (Field.FieldKind in  
[fkLookUp,fkCalculated]);
    if Allocated then
    begin
     Buff :=AllocRecordBuffer;
     ReadRecordCache(vInspectRecno, Buff, State=dsOldValue);
     if (Field.FieldKind in [fkLookUp,fkCalculated])  then
     try
      SetTempState(dsCalcFields);
      CalculateFields(Buff);
     finally
      RestoreState(dsState);
     end
    end
    else
    begin
     Allocated:=(dsState in [dsOldValue,dsFilter]) or
      (vTypeDispositionField=dfRRecNumber);
     if Allocated then
     begin
      Buff :=AllocRecordBuffer;
      ReadRecordCache(vInspectRecno, Buff, State=dsOldValue)
     end
     else
      Buff:=GetActiveBuf;
    end;
end;
4. On saving a dataset to the repository the query dialog always opened with an empty string.
unit RegFIBPlusEditors;

procedure TFIBGenSQlEd.SaveDataSetInfo;
var
  vDescription:string;
begin
  with Component as TpFibDataSet do
    if DataSet_ID = 0 then ShowMessage(Name + SCompEditDataSet_ID)
    else
      if DataBase = nil then ShowMessage(SDataBaseNotAssigned)
      else
      begin
        if not ExistDRepositaryTable(TFIBDataset(Component).DataBase) then
        begin
          if
            MessageDlg(SCompEditInfoTableNotExist, mtConfirmation, [mbOK, mbCancel], 0
            ) <> mrOk
            then Exit;
          CreateDRepositaryTable(TFibDataSet(Component).DataBase);
        end;
        vDescription:=TpFibDataSet(Component).Description;
        if not InputQuery(SCompEditSaveDataSetProperty, SCompEditDataSetDesc, vDescription) then
         Exit;
        SaveFIBDataSetInfo(TpFibDataSet(Component),vDescription);
        TpFibDataSet(Component).Description:=vDescription;
      end;
end;
5. When creating the SQL statements at design time, FibPlus 6 invoked an error in the Refreh SQL Query.
unit fraDSSQLEdit;

procedure TfDSSQLEdit.cmbTablesChange(Sender: TObject);
begin
with cmbTables do
  if ItemIndex>-1 then
  begin
   FUpdTableSynonym:=
    FormatIdentifier(FDatabase.SQLDialect,AliasForTable(SelectSQLEdit.SQLText,cmbTables.Text))    +'.';
   if FUpdTableSynonym[1]='@' then FUpdTableSynonym:='';     
  end
  else
   FUpdTableSynonym:='';

  LstKeyFields.Clear;  LstUpdFields.Clear;
  btnGetFieldsClick(btnGetFields);   
end;
6. On trying to connect to the database in design-time FIBPlus used the client library gds32.dll, though the LibraryName property had fbclient.dll.
unit pFIBDBEdit;

procedure TDBEditForm.TestBClick(Sender: TObject);
var TempDB : TFIBDatabase;
begin
  TestB.Enabled := false;
  TempDB := TFIBDatabase.Create(nil);
  try
    if LocalC.Checked then
      TempDB.DBName := DBNameE.Text
    else
      case ProtocolC.ItemIndex of
        0: TempDB.DBName := Format('\\%s\%s', [ServerE.Text, DBNameE.Text]);
        1: TempDB.DBName := Format('%s@%s', [ServerE.Text, DBNameE.Text]);
        2: TempDB.DBName := Format('%s:%s', [ServerE.Text, DBNameE.Text]);
      end;
    TempDB.DBParams.Assign(ParamsM.Lines);
    TempDB.UseLoginPrompt := UseLoginC.Checked;
/////////////
    TempDB.LibraryName    := aDatabase.LibraryName;
////^^^^^^^^^ to add

    TempDB.SQLDialect :=  DialectC.ItemIndex + 1;
    TempDB.Connected := True;
    ShowMessage(SDBEditSuccessConnection);
  finally
    TempDB.Free;
    TestB.Enabled := true;
  end;
end;
6. If Select uses macro, refresh did not work.
function TFIBCustomDataSet.InternalRefreshRow(Qry: TFIBQuery; Buff:Pointer):boolean;
var
  iCurScreenState: Integer;
begin
  ChangeScreenCursor(iCurScreenState);
  Result:=False;
  try
    if Buff=nil then
     Exit;
    if not EmptyStrings(Qry.SQL)  and (Active) then
    begin
     if not FCachedUpdates and (CacheModelOptions.CacheModelKind=cmkStandard) then
      SaveOldBuffer(Buff);
     if  not (Qry.Open  or Qry.ProcExecuted) then
     begin
      SetQueryParams(Qry, Buff);
      PrepareQuery(skRefresh);
      if (poStartTransaction in Options) and
        not Qry.Transaction.InTransaction
      then
       Qry.Transaction.StartTransaction;
      Qry.ExecQuery;
     end;
     if Qry.Open then
      with PRecordData(Buff)^ do
      try
        if (Qry.SQLType = SQLExecProcedure) or  (Qry.Next <> nil) then
        begin
          FetchCurrentRecordToBuffer(Qry,PRecordData(Buff)^.rdRecordNumber,Buff);
          Result:=True;
        end
        else
        if poRefreshDeletedRecord in Options then
        begin
          if (CacheModelOptions.CacheModelKind=cmkStandard) then
          begin
           CacheDelete;
           DoAfterRefresh;
          end;
        end;
      finally
        Qry.Close;
      end;
    end
    else
    if RecordCount>0 then
      FIBError(feCannotRefresh, [CmpFullName(Self)]);
  finally
   RestoreScreenCursor(iCurScreenState);
  end;
end;

Preview text: Use these hot fixes for FIBPlus 6.0 if you would not like to wait for FIBPlus 6.0 Service Pack
Prices in Euro:

235 (1 copy)
1250 (unlimited)

Volume discounts are available...

Navigation



When I had to find the best component to connect to my Firebird databases, FIBPlus imposed itself with its rapidity and reliability. Most importantly, it continued to evolve to be even better and whenever we had a problem, it was fixed promptly by Devrace team. We use FIBPlus in many projects related to Healthcare. We have hundreds of users who access databases up to 8 GB in size. I think there are many good third-party components out there, but not so many with an excellent support like the one provided for FIBPlus components. Thanks to you. >>

Evelyne Girard, Canada
FOR CUSTOMERS
Download full versions and updates in your Personal Area