AfterFetch handler being called too early / usage of NonBlocking mode / run code when loading of all records is finished

Discussion of open issues, suggestions and bugs regarding ODAC (Oracle Data Access Components) for Delphi, C++Builder, Lazarus (and FPC)
pcz
Posts: 81
Joined: Tue 04 Aug 2015 12:53

AfterFetch handler being called too early / usage of NonBlocking mode / run code when loading of all records is finished

Post by pcz » Wed 20 Jan 2016 09:50

Hello

I got some questions about proper usage of NonBlocking query mode :roll:


1. Which event shoud I use to do things that should be done after all data is "ready" (Executing = false?)
For example calling GotoBookmark / Locate
What is the best way to wait for query to execute / fetch all data?


2. [this problem does not exist since 9.7.25 fix] Similar problem
I'd like to
- remember last active record
- refresh dataset (with NonBlocking mode)
- restore same active record as before
Should I use GotoBookmark / Locate or there is some more clever way?

What is the proper way of use GotoBookmark / Locate in NonBlocking mode?
Or are there any restrictions to follow in NonBlocking mode?



Regards
P.C.
Last edited by pcz on Fri 29 Jul 2016 09:16, edited 5 times in total.

AlexP
Devart Team
Posts: 5530
Joined: Tue 10 Aug 2010 11:35

Re: Proper use of NonBlocking query mode

Post by AlexP » Thu 21 Jan 2016 11:51

Hello,

You can use the FetchingAll property to check if all the records were retrieved.
For the time being, until all the records are fetched, you can't call RefreshAll. If all the records are fetched, you can use both methods to navigate to a record.

pcz
Posts: 81
Joined: Tue 04 Aug 2015 12:53

Re: Proper use of NonBlocking query mode

Post by pcz » Fri 22 Jan 2016 08:56

Ok
What about events?
There is no event that signalizes moment when Fetching / FetchingAll property changes?

So what should I do?...
Create a timer and check FetchingAll property periodically?... :roll:

AlexP
Devart Team
Posts: 5530
Joined: Tue 10 Aug 2010 11:35

Re: Proper use of NonBlocking query mode

Post by AlexP » Fri 22 Jan 2016 09:52

There is an AfterFetch event, that is triggered after another data "portion" is retrieved.

pcz
Posts: 81
Joined: Tue 04 Aug 2015 12:53

Re: Proper use of NonBlocking query mode

Post by pcz » Fri 22 Jan 2016 11:03

Oh...
So it's possible to write

Code: Select all

procedure TSchedulerSettingsProcess.OraQuery1AfterFetch(DataSet: TCustomDADataSet);
begin
  if not DataSet.Fetching then
    ShowMessage('Tadaaa!');
end;
and "ShowMessage" executes exactly in the moment when all of the data is ready, yes?

And I can use GotoBookmark / Locate since then? :D

AlexP
Devart Team
Posts: 5530
Joined: Tue 10 Aug 2010 11:35

Re: Proper use of NonBlocking query mode

Post by AlexP » Mon 25 Jan 2016 09:40

Yes, in your code, a message will be returned only after all records are retrieved.
Yes. After retrieving all rows, you will be able to use these methods.

pcz
Posts: 81
Joined: Tue 04 Aug 2015 12:53

Re: Proper use of NonBlocking query mode

Post by pcz » Tue 26 Jan 2016 08:58

"But wait! There is more!" :|
One more stupid problem...
I use DevExpress grid pack and I just need to recalculate all columns width after TOraQuery finishes retrieving data

Code: Select all

procedure TFormBlahBlah.OraQuery1AfterFetch(DataSet: TCustomDADataSet);
begin
  if not DataSet.Fetching then
    DoStuffWithColumns;   // this happens too early to properly do that (no idea why)
end;
So... I'm experimenting with other events... But I'm not sure if I do it right way... :roll:

Code: Select all

procedure TFormBlahBlah.OraQuery1AfterExecute(Sender: TObject; Result: Boolean);
begin
  if not DataSet.Fetching then   // do I need this line???
    DoStuffWithColumns;   // it seems to work
end;

1. Is there any big difference between AfterFetch / AfterExecute event in NonBlocking mode?
What about calling BreakExec? Does it block calling both of these events?

2. Is the execution order of AfterFetch / AfterExecute always constant?
I mean - does AfterExecute happens always after AfterFetch?

3. What is the difference between Fetching and Fetched property?
Then don't seem to be "synchronised"

AlexP
Devart Team
Posts: 5530
Joined: Tue 10 Aug 2010 11:35

Re: Proper use of NonBlocking query mode

Post by AlexP » Tue 26 Jan 2016 10:38

1, 2) Before the server starts to return data, the query must be executed on the server. After the query is executed, the AfterExecute event is triggered. Then we request data from the server. After data is returned, the AfterFetch event is triggered. I.e., the AfterExecute event always occurs before the AfterFetch event.

3) The Fetching property is set just on starting data fetching, and the Fetched property - only after data fetching is finished or canceled.

pcz
Posts: 81
Joined: Tue 04 Aug 2015 12:53

Re: Proper use of NonBlocking query mode

Post by pcz » Tue 26 Jan 2016 11:58

AfterExecute event always occurs before the AfterFetch event.
Not in my code :) (ODAC 9.6.2.1 professional / XE7 / compilation & testing @ Win XP SP3 x86)
Ok - maybe it's some random stuff - and according to You I should not to do this in such way

So... I need to know the moment that <TOraQuery>.Fetched changes to True and trigger things then
But there is no event related?

Code: Select all

procedure TFormBlahBlah.OraQuery1AfterFetch(DataSet: TCustomDADataSet);
begin
  if DataSet.Fetched then   // (not DataSet.Fetching) can be True here, but DataSet.Fetched NEVER does
    DoStuffWithColumns;   // the problem is that this line never executes
end;
Doing this in such a primitive way

Code: Select all

procedure TFormBlahBlah.OraQuery1AfterFetch(DataSet: TCustomDADataSet);
begin
  if not DataSet.Fetching then
  begin
    Timer1.Interval := 10;
    Timer1.Enabled := True;
  end;
end;

procedure TFormBlahBlah.Timer1Timer(Sender: TObject);
begin
  if OraQuery1.Fetched then
  begin
    Timer1.Enabled := False;
    DoStuffWithColumns;
  end;
end;
is absurd (but it's working)

pcz
Posts: 81
Joined: Tue 04 Aug 2015 12:53

Re: Proper usage of NonBlocking query mode / fire code when all records are fetched

Post by pcz » Fri 29 Jan 2016 07:20

Any idea?... :(

AlexP
Devart Team
Posts: 5530
Joined: Tue 10 Aug 2010 11:35

Re: Proper usage of NonBlocking query mode / fire code when all records are fetched

Post by AlexP » Fri 29 Jan 2016 13:05

The Fetched property is set after the last AfterFetch event occurrence.

pcz
Posts: 81
Joined: Tue 04 Aug 2015 12:53

Re: Proper usage of NonBlocking query mode / fire code when all records are fetched

Post by pcz » Fri 29 Jan 2016 14:26

The Fetched property is set after the last AfterFetch event occurrence.
Yes, but exact timing depends on some cases...:

Code: Select all

procedure TForm1.OraQuery1AfterFetch(DataSet: TCustomDADataSet);
begin
  if not DataSet.Fetching then
  begin
    ShowMessage('This line executes in Blocking & NonBlocking mode');
    ShowMessage('### LAST FETCH ###');
    GridDBTableView.ApplyBestFit;   // PROBLEM HERE - happens both in Blocking and NonBlocking mode...
  end;
  if DataSet.Fetched then
    ShowMessage('This line executes olny in Blocking mode or after calling GridDBTableView.BeginUpdate');
end;
I use DevExpress Quantum Grid with TOraQuery - and I can't figure out which of them have problem / bug

At first glance it looks for me that last OnAfterFetch happens to early to react
And there is no other event...
It would be nice to have event like "OnFetched"...? (and it would be the best solution)
It looks that detecting moment when TOraQuery finished fetching of records is hard to achieve with OnAfterFetch event
so I'm unable to use features of DevExpress grids while using NonBlocking mode :( :( :(
Last edited by pcz on Tue 02 Feb 2016 11:10, edited 6 times in total.

pcz
Posts: 81
Joined: Tue 04 Aug 2015 12:53

Re: Proper use of NonBlocking query mode

Post by pcz » Fri 29 Jan 2016 15:01

AlexP wrote:1, 2) Before the server starts to return data, the query must be executed on the server. After the query is executed, the AfterExecute event is triggered. Then we request data from the server. After data is returned, the AfterFetch event is triggered. I.e., the AfterExecute event always occurs before the AfterFetch event.
It's true only when TOraQuery.FetchAll = False;
When switchcing TOraQuery.FetchAll to True the order of these events is opposite

Why is the TOraDataSet.FetchAll Property affecting order of AfterExecute / AfterFetch events at all?...

pcz
Posts: 81
Joined: Tue 04 Aug 2015 12:53

Re: Proper usage of NonBlocking query mode / fire code when all records are fetched

Post by pcz » Tue 02 Feb 2016 09:41

Funny fact
After calling GridDBTableView.BeginUpdate and setting FetchAll to True this code starts working

Code: Select all

GridDBTableView.BeginUpdate;
OraQuery1.FetchAll := True;
OraQuery1.Open;
...
procedure TForm1.OraQuery1AfterFetch(DataSet: TCustomDADataSet);
begin
  if DataSet.Fetched then
    ShowMessage('This line executes only after GridDBTableView.BeginUpdate...');
end;

pcz
Posts: 81
Joined: Tue 04 Aug 2015 12:53

Re: Proper usage of NonBlocking query mode / fire code when all records are fetched

Post by pcz » Tue 02 Feb 2016 11:09

Looks like there is some friction between TOraQuery and default behaviour of DevExpress TcxGridDBTableView...

Code: Select all

GridDBTableView.BeginUpdate;
OraQuery1.FetchAll := True;
OraQuery1.Open;
...
procedure TForm1.OraQuery1AfterFetch(DataSet: TCustomDADataSet);
begin
  if not DataSet.Fetching then
  begin
    GridDBTableView.EndUpdate;
    GridDBTableView.ApplyBestFit;
  end;
end;
It seems like grid have been not properly informed that data is ready without calling BeginUpdate / EndUpdate...
I have no idea whether problem is in grid class itself or TOraQuery...

Regards
P.C.
Last edited by pcz on Tue 02 Feb 2016 12:36, edited 1 time in total.

Post Reply