Google
 

Wednesday, November 17, 2004

FIBPlus 6.0 fixes

If you cannot wait for the service pack, you can try these quick fixes:

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;

No comments: