Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2014-10

Why TSdfDataSet doesn't simply return FCurRec as RecNo?

12 messages · 3 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Luca Olivetti

Hello,

TFixedFormatDataSet (ancestor of TSdfDataSet) overrides GetRecNo (correct) but it does a strange contortion instead of simply returning FCurRec:

function TFixedFormatDataSet.GetRecNo: Longint;
var
  BufPtr: TRecordBuffer;
begin
  Result := -1;
  if GetActiveRecBuf(BufPtr) then
    Result := PRecInfo(BufPtr + FRecInfoOfs)^.RecordNumber;
end;

Why?

Background: if you have, say, 3 records (0,1 and 2), and you insert a new record between 1 and 2, FCurRec of the new record will be 2, while RecordNumber (hence RecNo) will be 3, with this result:

RecordNumber (RecNo) | FCurRec
-----------------------+----------
0 | 0
1 | 1
new record-> 3 | 2
2 | 3

I know that RecNo is documented not to be reliable in all cases, but it should be with this dataset, considering that FCurRec has the "correct" value.
TDBGrid apparently uses RecNo for the scrollbar, and with the above scenario the scrollbar jumps around while scrolling through the table.

OK, that (while bad) is not really my problem, I just want to know if I'm positioned at the first (RecNo=0) or the last (RecNo=RecordCount-1) record (EOF and BOF don't work unless you try to move past the last or first record).

Luckily enough FCurRec is protected, so I just subclass TSdfDataset and override the GetRecNo method to return FCurRec, but I'd like to know the reason why it doesn't do it by default.

Bye

Luca

Reply by email

Michael Van Canneyt
to Luca Olivetti
Luca Olivetti wrote 13 lines
Hello, TFixedFormatDataSet (ancestor of TSdfDataSet) overrides GetRecNo (correct) but it does a strange contortion instead of simply returning FCurRec: function TFixedFormatDataSet.GetRecNo: Longint; var BufPtr: TRecordBuffer; begin Result := -1; if GetActiveRecBuf(BufPtr) then Result := PRecInfo(BufPtr + FRecInfoOfs)^.RecordNumber;

The records in the buffer may be in a different order than they are displayed in the grid.

Michael.

Reply by email

Michael Van Canneyt
to Michael Van Canneyt
Michael Van Canneyt wrote 20 lines
On Thu, 30 Oct 2014, Luca Olivetti wrote: > Hello, > > TFixedFormatDataSet (ancestor of TSdfDataSet) overrides GetRecNo > (correct) but it does a strange contortion instead of simply returning > FCurRec: > > function TFixedFormatDataSet.GetRecNo: Longint; > var > BufPtr: TRecordBuffer; > begin > Result := -1; > if GetActiveRecBuf(BufPtr) then > Result := PRecInfo(BufPtr + FRecInfoOfs)^.RecordNumber; The records in the buffer may be in a different order than they are displayed in the grid.

Forget this. I was too quick to respond.

I have done some digging, but cannot find a reason for the current behaviour.

Michael.

Reply by email

Joost van der Sluis
to Michael Van Canneyt
Michael Van Canneyt wrote 29 lines
On Thu, 30 Oct 2014, Michael Van Canneyt wrote: > > > On Thu, 30 Oct 2014, Luca Olivetti wrote: > >> Hello, >> >> TFixedFormatDataSet (ancestor of TSdfDataSet) overrides GetRecNo >> (correct) but it does a strange contortion instead of simply returning >> FCurRec: >> >> function TFixedFormatDataSet.GetRecNo: Longint; >> var >> BufPtr: TRecordBuffer; >> begin >> Result := -1; >> if GetActiveRecBuf(BufPtr) then >> Result := PRecInfo(BufPtr + FRecInfoOfs)^.RecordNumber; > > The records in the buffer may be in a different order than they are > displayed in the grid. Forget this. I was too quick to respond. I have done some digging, but cannot find a reason for the current behaviour.

Easy: Some systems use the recno as some sort of 'bookmark'. And some people insist that this is the correct behaviour for a dataset. (Note that for TBufDataset a call to recno is really slow, as it has to iterate over all records to get the correct recno.)

So some datasets have recno's that uniquely identify a record. I've tried to unify that once, but that was not easily done. So I decided to leave this decision to the author of each dataset. Hence the GetRecNo.

But that TDBGrid uses the recno is troublesome... But I don't see a better solution.

Joost.

Reply by email

Michael Van Canneyt
to Joost van der Sluis
Joost van der Sluis wrote 35 lines
On 10/30/2014 04:34 PM, Michael Van Canneyt wrote: > > > On Thu, 30 Oct 2014, Michael Van Canneyt wrote: > >> >> >> On Thu, 30 Oct 2014, Luca Olivetti wrote: >> >>> Hello, >>> >>> TFixedFormatDataSet (ancestor of TSdfDataSet) overrides GetRecNo >>> (correct) but it does a strange contortion instead of simply returning >>> FCurRec: >>> >>> function TFixedFormatDataSet.GetRecNo: Longint; >>> var >>> BufPtr: TRecordBuffer; >>> begin >>> Result := -1; >>> if GetActiveRecBuf(BufPtr) then >>> Result := PRecInfo(BufPtr + FRecInfoOfs)^.RecordNumber; >> >> The records in the buffer may be in a different order than they are >> displayed in the grid. > > Forget this. I was too quick to respond. > > I have done some digging, but cannot find a reason for the current > behaviour. Easy: Some systems use the recno as some sort of 'bookmark'. And some people insist that this is the correct behaviour for a dataset. (Note that for TBufDataset a call to recno is really slow, as it has to iterate over all records to get the correct recno.)

AFAIK RecNo has no meaning when you work with multiple indexes and filters.

So some datasets have recno's that uniquely identify a record. I've tried to unify that once, but that was not easily done. So I decided to leave this decision to the author of each dataset. Hence the GetRecNo.

I understand why the GetRecNo is there, just not why it is implemented as it is in TSDFDataset. (which is what I was investigating)

But that TDBGrid uses the recno is troublesome... But I don't see a better solution.

Delphi DBGrid does not use recno, so it must be possible... AFAIK TDatalink has special provisions to provide a window buffer.

Michael.

Reply by email

Luca Olivetti
to Michael Van Canneyt

El 30/10/14 a les 22:44, Michael Van Canneyt ha escrit:

On Thu, 30 Oct 2014, Joost van der Sluis wrote:

...

> Easy: Some systems use the recno as some sort of 'bookmark'. And some > people insist that this is the correct behaviour for a dataset. (Note

Since a dataset provides GetBookmark, GotoBookmark and FreeBookmark I always thought that was the correct procedure to, well, set a bookmark ;-)

> that for TBufDataset a call to recno is really slow, as it has to > iterate over all records to get the correct recno.)
Show quoted text 9 lines
I understand why the GetRecNo is there, just not why it is implemented as it is in TSDFDataset. (which is what I was investigating) > But that TDBGrid uses the recno is troublesome... But I don't see a > better solution. Delphi DBGrid does not use recno, so it must be possible... AFAIK TDatalink has special provisions to provide a window buffer.

Well, if you "fix" the dbgrid not to use RecNo, I'm still left with my original problem of knowing if I'm positioned at the first or the last record (specifically for a TSdfDataset, where FCurRec is the correct answer, and I still think it would be the correct value for RecNo).

Bye

Luca

Reply by email

Joost van der Sluis
to Michael Van Canneyt: AFAIK RecNo has no meaning when you work with multiple indexes and filters. I understand…
Michael Van Canneyt wrote 41 lines
On Thu, 30 Oct 2014, Joost van der Sluis wrote: > On 10/30/2014 04:34 PM, Michael Van Canneyt wrote: >> >> >> On Thu, 30 Oct 2014, Michael Van Canneyt wrote: >> >>> >>> >>> On Thu, 30 Oct 2014, Luca Olivetti wrote: >>> >>>> Hello, >>>> >>>> TFixedFormatDataSet (ancestor of TSdfDataSet) overrides GetRecNo >>>> (correct) but it does a strange contortion instead of simply returning >>>> FCurRec: >>>> >>>> function TFixedFormatDataSet.GetRecNo: Longint; >>>> var >>>> BufPtr: TRecordBuffer; >>>> begin >>>> Result := -1; >>>> if GetActiveRecBuf(BufPtr) then >>>> Result := PRecInfo(BufPtr + FRecInfoOfs)^.RecordNumber; >>> >>> The records in the buffer may be in a different order than they are >>> displayed in the grid. >> >> Forget this. I was too quick to respond. >> >> I have done some digging, but cannot find a reason for the current >> behaviour. > > Easy: Some systems use the recno as some sort of 'bookmark'. And some > people insist that this is the correct behaviour for a dataset. (Note > that for TBufDataset a call to recno is really slow, as it has to > iterate over all records to get the correct recno.) AFAIK RecNo has no meaning when you work with multiple indexes and filters.

Well, that depend on the dataset. Each TDataset descendant can do whatever it want. (We even got bug-reports about TBufDataset's recno, and that it was not possible to use it as a bookmark)

Show quoted text 13 lines
> So some datasets have recno's that uniquely identify a record. I've > tried to unify that once, but that was not easily done. So I decided > to leave this decision to the author of each dataset. Hence the GetRecNo. I understand why the GetRecNo is there, just not why it is implemented as it is in TSDFDataset. (which is what I was investigating) > But that TDBGrid uses the recno is troublesome... But I don't see a > better solution. Delphi DBGrid does not use recno, so it must be possible... AFAIK TDatalink has special provisions to provide a window buffer.

Indeed, there are datalink-events that passes around information about how many records there are in the buffer and by how many the buffer has scrolled.

Joost.

Reply by email

Joost van der Sluis
to Luca Olivetti: El 30/10/14 a les 22:44, Michael Van Canneyt ha escrit: ... Since a dataset provides…
Luca Olivetti wrote 8 lines
El 30/10/14 a les 22:44, Michael Van Canneyt ha escrit: > Delphi DBGrid does not use recno, so it must be possible... AFAIK > TDatalink has special provisions to provide a window buffer. Well, if you "fix" the dbgrid not to use RecNo, I'm still left with my original problem of knowing if I'm positioned at the first or the last record (specifically for a TSdfDataset, where FCurRec is the correct answer, and I still think it would be the correct value for RecNo).

With .eof and .bof? But those are not always set, you have to use 'next' or 'prior' to really know if you are at the first or last record.

(TSdfDataset is not buffered, but with a buffered dataset there really is no other way to detect the first or last record, since it could be that those records are simply not fetched yet)

Joost.

Reply by email

Luca Olivetti
to Joost van der Sluis

El 31/10/14 a les 12:13, Joost van der Sluis ha escrit:

Show quoted text 8 lines
> > Well, if you "fix" the dbgrid not to use RecNo, I'm still left with my > original problem of knowing if I'm positioned at the first or the last > record (specifically for a TSdfDataset, where FCurRec is the correct > answer, and I still think it would be the correct value for RecNo). With .eof and .bof? But those are not always set, you have to use 'next' or 'prior' to really know if you are at the first or last record.

Yes, I know it and I said so in my first message. What maybe I didn't say is that I don't want to do either of those (which would make my code more convoluted).
I happily (well, kinda) do it when there is no other option, but in this case there is and I'd prefer to avoid:

1) getting a bookmark
2) disable the dataset/datasource events (to avoid an infinite loop)
3) try to use next and prior to determine if I'm at the beginning/end of the table
4) go back to the current record
5) re-enable the events

when I can simply do a comparison based on RecNo/RecordCount

(TSdfDataset is not buffered, but with a buffered dataset there really is no other way to detect the first or last record, since it could be that those records are simply not fetched yet)

I understand that, but my question is specific to TSdfDataset, where FCurRec gives a meaningful answer to that question without the need of scrolling.

Bye

Luca

Reply by email

Luca Olivetti
to Michael Van Canneyt: AFAIK RecNo has no meaning when you work with multiple indexes and filters. I understand…

El 30/10/14 a les 22:44, Michael Van Canneyt ha escrit:

Show quoted text 16 lines
>>> On Thu, 30 Oct 2014, Luca Olivetti wrote: >>> >>>> Hello, >>>> >>>> TFixedFormatDataSet (ancestor of TSdfDataSet) overrides GetRecNo >>>> (correct) but it does a strange contortion instead of simply returning >>>> FCurRec: >>>> >>>> function TFixedFormatDataSet.GetRecNo: Longint; >>>> var >>>> BufPtr: TRecordBuffer; >>>> begin >>>> Result := -1; >>>> if GetActiveRecBuf(BufPtr) then >>>> Result := PRecInfo(BufPtr + FRecInfoOfs)^.RecordNumber; >>>

[...]

I understand why the GetRecNo is there, just not why it is implemented as it is in TSDFDataset. (which is what I was investigating)

So, what's the verdict? Will it stay this way for the foreseeable future or will it be changed?
Should I file a bug report or should it not be considered a bug?

Bye

Luca

Reply by email

Michael Van Canneyt
to Luca Olivetti
Luca Olivetti wrote 26 lines
El 30/10/14 a les 22:44, Michael Van Canneyt ha escrit: >>>> On Thu, 30 Oct 2014, Luca Olivetti wrote: >>>> >>>>> Hello, >>>>> >>>>> TFixedFormatDataSet (ancestor of TSdfDataSet) overrides GetRecNo >>>>> (correct) but it does a strange contortion instead of simply returning >>>>> FCurRec: >>>>> >>>>> function TFixedFormatDataSet.GetRecNo: Longint; >>>>> var >>>>> BufPtr: TRecordBuffer; >>>>> begin >>>>> Result := -1; >>>>> if GetActiveRecBuf(BufPtr) then >>>>> Result := PRecInfo(BufPtr + FRecInfoOfs)^.RecordNumber; >>>> [...] > I understand why the GetRecNo is there, just not why it is implemented > as it is in TSDFDataset. > (which is what I was investigating) So, what's the verdict? Will it stay this way for the foreseeable future or will it be changed? Should I file a bug report or should it not be considered a bug?

You can file a bug report so it is not forgotten.

Michael.

Reply by email