Sign in Join

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

Mailing lists / fpc-devel / 2006-04

Warning for sqldb and fpc 2.1.1 users

12 messages · 6 people · –

Reply by email Subscribe to this list Your subscription

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

Joost van der Sluis

Hi all,

In revision 3111 TBufDataset is almost completely rewritten. I've tested as much as I could, but it could be that you encounter problems with sqldb which weren't there before.

Please test if everything still works ok, and if not, tell me or submit a bug-report.

Further I have a question: now sqldb uses a linked-list record buffer, the RecordCount and RecNo properties are something strange.

What should I do with recordcount? I can add a counter which keep track of the recordcount. Ie: it does inc(recordcount) if a record is appended.

Or I can do a real count of the records, each time recordcount is called.

And what about recno? Just define it as -1, or do a quick count to get the current record number?

What are your thoughts on this?

JoJo,
Joost.

Reply by email

Michael Van Canneyt
to Joost van der Sluis
Joost van der Sluis wrote 10 lines
Hi all, In revision 3111 TBufDataset is almost completely rewritten. I've tested as much as I could, but it could be that you encounter problems with sqldb which weren't there before. Please test if everything still works ok, and if not, tell me or submit a bug-report. Further I have a question: now sqldb uses a linked-list record buffer,

Why ? This goes against the recordset idea ?

Show quoted text 13 lines
the RecordCount and RecNo properties are something strange. What should I do with recordcount? I can add a counter which keep track of the recordcount. Ie: it does inc(recordcount) if a record is appended. Or I can do a real count of the records, each time recordcount is called. And what about recno? Just define it as -1, or do a quick count to get the current record number? What are your thoughts on this?

The very idea of TBufDataset was that both recno and recordcount would always be available. So using a linked list is not so good. Why did you change that ?

Michael.

Reply by email

Joost van der Sluis
to Michael Van Canneyt
Michael Van Canneyt wrote 10 lines
> In revision 3111 TBufDataset is almost completely rewritten. I've tested > as much as I could, but it could be that you encounter problems with > sqldb which weren't there before. > > Please test if everything still works ok, and if not, tell me or submit > a bug-report. > > Further I have a question: now sqldb uses a linked-list record buffer, Why ? This goes against the recordset idea ?

Why is that against the recordset idea?

Show quoted text 17 lines
> the RecordCount and RecNo properties are something strange. > > What should I do with recordcount? I can add a counter which keep track > of the recordcount. Ie: it does inc(recordcount) if a record is > appended. > > Or I can do a real count of the records, each time recordcount is > called. > > And what about recno? Just define it as -1, or do a quick count to get > the current record number? > > What are your thoughts on this? The very idea of TBufDataset was that both recno and recordcount would always be available. So using a linked list is not so good. Why did you change that ?

Mostly because of speed-issues, and this makes the code far more easier.

With the array, if you're iterating through the data, you have to read the pointer to the buffer in the array, and subsequently the data in the buffer.

With this new code, the record buffers contain pointers to their precessor en successor. That makes searching and browsing a lot faster.

The TDataset only asks the 'next' and 'previous' records from the TBufDataset. Or it uses bookmarks. Well, bookmarks in a linked list are easy, they are just the pointers to the list-items.

And using mostly 'next' and 'previous', the linked list is the best solution.

For TDataset it's a different story.

Joost.

JoJo,
Joost.

Reply by email

Micha Nelissen
to Joost van der Sluis: In revision 3111 TBufDataset is almost completely rewritten. I've tested as much as I…
Show quoted text 6 lines
Further I have a question: now sqldb uses a linked-list record buffer, the RecordCount and RecNo properties are something strange. What should I do with recordcount? I can add a counter which keep track of the recordcount. Ie: it does inc(recordcount) if a record is appended.

Keep a counter.

Or I can do a real count of the records, each time recordcount is called.

No, too slow.

And what about recno? Just define it as -1, or do a quick count to get the current record number?

Store the recno with/in the linked list entry ?

Micha

Reply by email

Luiz Americo Pereira Camara
to Micha Nelissen
Micha Nelissen wrote 25 lines
On Sat, 01 Apr 2006 18:06:31 +0200 Joost van der Sluis wrote: > Further I have a question: now sqldb uses a linked-list record buffer, > the RecordCount and RecNo properties are something strange. > > What should I do with recordcount? I can add a counter which keep track > of the recordcount. Ie: it does inc(recordcount) if a record is > appended. > Keep a counter. > Or I can do a real count of the records, each time recordcount is > called. > No, too slow. > And what about recno? Just define it as -1, or do a quick count to get > the current record number? >

Take a look at TCustomSqliteDataset implementation. In its implementation a count is done each time.

Store the recno with/in the linked list entry ?

It has two drawbacks: increase memory usage and when inserting, deleting all following records must be updated.

Luiz

Reply by email

Martin Schreiber
to Joost van der Sluis: In revision 3111 TBufDataset is almost completely rewritten. I've tested as much as I…
Joost van der Sluis wrote 13 lines
Further I have a question: now sqldb uses a linked-list record buffer, the RecordCount and RecNo properties are something strange. What should I do with recordcount? I can add a counter which keep track of the recordcount. Ie: it does inc(recordcount) if a record is appended. Or I can do a real count of the records, each time recordcount is called. And what about recno? Just define it as -1, or do a quick count to get the current record number?

RecNo and RecordCount are frequently used in MSEgui, I found them very useful.

Martin

Reply by email

Micha Nelissen
to Luiz Americo Pereira Camara: Take a look at TCustomSqliteDataset implementation. In its implementation a count is done…
Show quoted text 10 lines
>> And what about recno? Just define it as -1, or do a quick count to get >> the current record number? >> Take a look at TCustomSqliteDataset implementation. In its implementation a count is done each time. > Store the recno with/in the linked list entry ? > > It has two drawbacks: increase memory usage and when inserting, deleting all following records must be updated.

An array of records has the same problem, no ? So these are not drawbacks IMHO.

Micha

Reply by email

Michael Van Canneyt
to Joost van der Sluis: In revision 3111 TBufDataset is almost completely rewritten. I've tested as much as I…

Hoi,

Ik heb master-detail relaties geimplementeerd voor sqldb. Het meeste zit in db.pp; Ik heb 't getest met interbase, en dat werkt correct, schijnbaar.

Als je wat tests zou kunnen doen zou ik dat appreciëren ;-)

'T werkt als volgt: als een parameter niet 'bound' is, en de datasource is ingesteld, wordt de waarde gezocht in de datasource's dataset.

De datalink die gebruikt wordt is TMasterParamsDataLink, zie datasource.ini. Descendent van TMasterDataLink (die in Delphi ook bestaat)

De enige methode waar ik zo'n beetje m'n twijfels over heb is

Procedure TMasterParamsDataLink.RefreshParamNames;

Daar wordt de 'TMasterDatalink.FieldNames' property gezet vanuit de parameters. Als de dataset beschikbaar is, wordt nagekeken welke parameters effectief als veld beschikbaar zijn. Als ie niet beschikbaar is, worden alle parameters genomen.

Dat is problematisch op 2 manieren:
1. Als dataset niet beschikbaar is, worden er parameters toegevoegd die misschien niet bestaan als veld.
2. Ook 'bound' parameters (parameters met een vaste waarde) worden opgenomen in de lijst.

Waarvoor dient die 'FieldNames': de MasterDataLink zal alleen de velden die daarin staan nagaan op veranderingen.

Als je daar ideeën rond hebt, laat maar weten.

Michael.

Reply by email

Michael Van Canneyt
to Michael Van Canneyt

On Sun, 2 Apr 2006, Michael Van Canneyt wrote:

Woops !

This was supposed to be a private communication to Joost.

For non-dutch speakers (probably the majority on the list ;))

It says that support for Master/Detail relationships is implemented in SQLDB, and that it seems to be working fine, but that some testing and optimization may be needed.

Michael.

Show quoted text 38 lines
Hoi, Ik heb master-detail relaties geimplementeerd voor sqldb. Het meeste zit in db.pp; Ik heb 't getest met interbase, en dat werkt correct, schijnbaar. Als je wat tests zou kunnen doen zou ik dat appreciëren ;-) 'T werkt als volgt: als een parameter niet 'bound' is, en de datasource is ingesteld, wordt de waarde gezocht in de datasource's dataset. De datalink die gebruikt wordt is TMasterParamsDataLink, zie datasource.ini. Descendent van TMasterDataLink (die in Delphi ook bestaat) De enige methode waar ik zo'n beetje m'n twijfels over heb is Procedure TMasterParamsDataLink.RefreshParamNames; Daar wordt de 'TMasterDatalink.FieldNames' property gezet vanuit de parameters. Als de dataset beschikbaar is, wordt nagekeken welke parameters effectief als veld beschikbaar zijn. Als ie niet beschikbaar is, worden alle parameters genomen. Dat is problematisch op 2 manieren: 1. Als dataset niet beschikbaar is, worden er parameters toegevoegd die misschien niet bestaan als veld. 2. Ook 'bound' parameters (parameters met een vaste waarde) worden opgenomen in de lijst. Waarvoor dient die 'FieldNames': de MasterDataLink zal alleen de velden die daarin staan nagaan op veranderingen. Als je daar ideeën rond hebt, laat maar weten. Michael.

Reply by email

Bram Kuijvenhoven
to Micha Nelissen: On Sat, 01 Apr 2006 18:33:10 -0300 An array of records has the same problem, no ? So…
Micha Nelissen wrote 16 lines
On Sat, 01 Apr 2006 18:33:10 -0300 Luiz Americo Pereira Camara wrote: >>> And what about recno? Just define it as -1, or do a quick count to get >>> the current record number? >>> > Take a look at TCustomSqliteDataset implementation. In its > implementation a count is done each time. >> Store the recno with/in the linked list entry ? >> >> > It has two drawbacks: increase memory usage and when inserting, deleting > all following records must be updated. An array of records has the same problem, no ? So these are not drawbacks IMHO.

I think, when using an array, the RecNo is implicit from the position in the array.

Implementing the RecordCount property is not so much a problem (using increments/decrements on changes), but updating RecNo's can be troublesome I think.

I can imagine it is possible to store some kind of relative RecNo's with only a sparse subset of the record in a smart way, allowing O(log N) times for inserting/deleting records and O(log N) time for getting RecNo's. I do not know whether this is indeed possible, and the implementation would not be easy I think.

Another option is to update the RecNo's only when requested, i.e.:
- each record stores a record number
- when inserting/deleting, all RecNo's from that record on are marked as 'dirty' (this needs only storage of a LowestDirtyRecNoIndex)
- when requesting the RecNo of an item with 'dirty' stored RecNo, one could recalculate the RecNo's of record LowestDirtyRecNoIndex until the record whose RecNo is requested at that time

To prevent the memory overhead of storing RecNo's, it is even possible to only allocate the RecNo storage space only when some RecNo is retrieved for the first time. This allows people to save memory by never using RecNo, but still use RecNo if they really need.

Of course, using Bookmarks is a very good substitute for RecNo's! And if one wants to enumerate the records, one can still do so by keeping a private counter while traversing the dataset with calls to Next. (In one of my applications I even have an array of Bookmarks -- I think I overlooked the RecNo property, which would take away the necessity of using such an array, if I'm understanding things correctly).

Regards,

Bram Kuijvenhoven

Reply by email

Micha Nelissen
to Bram Kuijvenhoven
- when requesting the RecNo of an item with 'dirty' stored RecNo, one could recalculate the RecNo's of record LowestDirtyRecNoIndex until the record whose RecNo is requested at that time

Sounds like a good idea to me. Walk backwards until you have a non-dirty node, then update all RecNos in the nodes between, increasing the RecNo while walking "back".

Micha

Reply by email

Luiz Americo Pereira Camara
to Bram Kuijvenhoven: I think, when using an array, the RecNo is implicit from the position in the array.…
Bram Kuijvenhoven wrote 53 lines
Micha Nelissen wrote: > On Sat, 01 Apr 2006 18:33:10 -0300 > Luiz Americo Pereira Camara wrote: > >>>> And what about recno? Just define it as -1, or do a quick count to >>>> get >>>> the current record number? >>>> >> Take a look at TCustomSqliteDataset implementation. In its >> implementation a count is done each time. >>> Store the recno with/in the linked list entry ? >>> >>> >> It has two drawbacks: increase memory usage and when inserting, >> deleting all following records must be updated. > > An array of records has the same problem, no ? So these are not > drawbacks > IMHO. I think, when using an array, the RecNo is implicit from the position in the array. Implementing the RecordCount property is not so much a problem (using increments/decrements on changes), but updating RecNo's can be troublesome I think. I can imagine it is possible to store some kind of relative RecNo's with only a sparse subset of the record in a smart way, allowing O(log N) times for inserting/deleting records and O(log N) time for getting RecNo's. I do not know whether this is indeed possible, and the implementation would not be easy I think. Another option is to update the RecNo's only when requested, i.e.: - each record stores a record number - when inserting/deleting, all RecNo's from that record on are marked as 'dirty' (this needs only storage of a LowestDirtyRecNoIndex) - when requesting the RecNo of an item with 'dirty' stored RecNo, one could recalculate the RecNo's of record LowestDirtyRecNoIndex until the record whose RecNo is requested at that time To prevent the memory overhead of storing RecNo's, it is even possible to only allocate the RecNo storage space only when some RecNo is retrieved for the first time. This allows people to save memory by never using RecNo, but still use RecNo if they really need. Of course, using Bookmarks is a very good substitute for RecNo's! And if one wants to enumerate the records, one can still do so by keeping a private counter while traversing the dataset with calls to Next. (In one of my applications I even have an array of Bookmarks -- I think I overlooked the RecNo property, which would take away the necessity of using such an array, if I'm understanding things correctly).

This is what you get in TSqliteDataset: while RecNo is something expensive (both to get and to set the RecNo it walks through the linked list), BookMarks are almost inexpensive (both in memory requirements and to set/retrive) because the bookmark is really the list item pointer (Take a look at the implementation). Every time you choose a design (any) you have strengths :-) and weakness :-( . It's a matter of what you want, what's the priority.

Luiz

Reply by email