TOraTable.SetRange
-
h.hasenack
- Posts: 48
- Joined: Tue 20 Jan 2009 12:35
TOraTable.SetRange
The SetRange method is missing, but the mastersource property is available as well as a KeyFields and Masterfields property.
Checking the Good Old VCL reveils that master/detail handling is implemented with SetRange calls for TTable, and also for nexus and flashfiler implementations.
Any tips on how to emulate a setrange call for tOraTable? Maybe using parametered SQL?
Regards - Hans
Checking the Good Old VCL reveils that master/detail handling is implemented with SetRange calls for TTable, and also for nexus and flashfiler implementations.
Any tips on how to emulate a setrange call for tOraTable? Maybe using parametered SQL?
Regards - Hans
-
h.hasenack
- Posts: 48
- Joined: Tue 20 Jan 2009 12:35
In my code a template like this often is used
While it is fairly easy to replace this with equivalent code
The equivalent code does not set the Progress.Max to a correct value (records in the range) but to the total # of records in the table.
Generally, I use setrange quite a lot to process my data on a record-by-record basis. This because the processing itself cannot be translated to SQL.
Apart from that, it is very common to use Setrange for cursor based access (Let's say TTable clones) in delphi. Well, at least to us it is.
Regards
Code: Select all
aTable.SetRange([MasterID],[MasterID]);
Progress.Max:=aTable.RecordCOunt;
cnt:=0;
while not aTable.EOF do
begin
Progress.Pos:=cnt;
ProcessRecordData
aTable.Next;
inc(cnt);
end;
Code: Select all
Progress.Max:=aTable.RecordCOunt;
cnt:=0;
if aTable.FindKey([aMasterID]) then
repeat
Progress.Pos:=cnt;
ProcessRecordData
aTable.Next;
inc(cnt);
until aTable.EOF or (aTable.FieldByName('masterField').ValueaMasterID);
Generally, I use setrange quite a lot to process my data on a record-by-record basis. This because the processing itself cannot be translated to SQL.
Apart from that, it is very common to use Setrange for cursor based access (Let's say TTable clones) in delphi. Well, at least to us it is.
Regards
You can use the Filter property for this code:
Code: Select all
aTable.Filtered := True;
aTable.Filter := 'MasterID = ' + IntToStr(MasterID);
Progress.Max:=aTable.RecordCOunt;
cnt:=0;
while not aTable.EOF do
begin
Progress.Pos:=cnt;
ProcessRecordData
aTable.Next;
inc(cnt);
end; -
h.hasenack
- Posts: 48
- Joined: Tue 20 Jan 2009 12:35
Is Filter property evaluated clientside or serverside? (ODAC implementation)
Does it use the available indexes?
The standard VCL implementation is client side and scans all available records, apply filter for each record just to calculate the record count. You probably don't want that to happen with a table of 10M records.
Regards - hans
Does it use the available indexes?
The standard VCL implementation is client side and scans all available records, apply filter for each record just to calculate the record count. You probably don't want that to happen with a table of 10M records.
Regards - hans
The Filter property is checked on the client side.
But TOraTable has also the FilterSQL property. The value of this property is added to the WHERE clause of SQL statement generated by TOraTable. So data are filtered on the server side, and indexes are used by the server.
After you set the FilterSQL property you need to reopen the TOraTable component:
But TOraTable has also the FilterSQL property. The value of this property is added to the WHERE clause of SQL statement generated by TOraTable. So data are filtered on the server side, and indexes are used by the server.
After you set the FilterSQL property you need to reopen the TOraTable component:
Code: Select all
aTable.Close;
aTable.FilterSQL := 'MasterID = ' + IntToStr(MasterID);
aTable.Open;
Progress.Max:=aTable.RecordCount;
cnt:=0;
while not aTable.EOF do
begin
Progress.Pos:=cnt;
ProcessRecordData
aTable.Next;
inc(cnt);
end;-
h.hasenack
- Posts: 48
- Joined: Tue 20 Jan 2009 12:35
Yes, that could prove to be a good replacement for the SetRange call. I'll give a try!
I guess this won't interfere with the regular Filter settings? (So both will be applied)
It's a pity though that the dataset needs to be re-opened for the SQLFilter to be applied. This means I have to change my fields to static fields or remap all my TField pointers after the dataset has been reopened...
That's what I like so much about the setrange call: It is fast, and doesn't have many side effects. I even don't have to call DisableCOntrols/EnableControls to avoid controls slowing things down.
No Chance SetRange will be implemented in the (near) future?
Regards
I guess this won't interfere with the regular Filter settings? (So both will be applied)
It's a pity though that the dataset needs to be re-opened for the SQLFilter to be applied. This means I have to change my fields to static fields or remap all my TField pointers after the dataset has been reopened...
That's what I like so much about the setrange call: It is fast, and doesn't have many side effects. I even don't have to call DisableCOntrols/EnableControls to avoid controls slowing things down.
No Chance SetRange will be implemented in the (near) future?
Regards
-
h.hasenack
- Posts: 48
- Joined: Tue 20 Jan 2009 12:35
We have investigated this problem in more details, and have come to a conclusion that the behaviour of the FilterSQL property should not be changed. Such change can cause some problems. TOraTable has different architecture than BDE TTable. The BDE component is based on indexes while TOraTable works like TOraQuery. It has the SQL property which it opens and fetches sequentially.
You should reassign your fields pointers after you change the FilterSQL property.
You should reassign your fields pointers after you change the FilterSQL property.