Subject Re: [IBO] Need help with a simple OnCallBack for a progressmeter
Author Helen Borrie
At 01:58 PM 30/06/2005 -0700, you wrote:

>My application here is just to give some indication to the user of the time to
>completion of a simple query (or cursor in this case).
>For the life of me I can't see the difference between what I'm doing and
>what is
>going on when a cursor is being used for the src dataset in a datapump.

The main difference, I suppose, is that the callback is hooked to a process
in the datapump case (TIB_Datascan is a process) whereas you are trying to
hook it to a record count (known only if you perform a select count(*)
first - extra horrible for a select SP) AND if you maintain a count of
fetches (because Row Number is meaningless for an unbuffered dataset).

>I tried using First rather than Execute (or Open) and nothing helped. Why
>I want to First...Next?

Because an ib_cursor does not buffer the rows it fetches. You use First to
"open" the cursor and position it at the first row. You use Next to
request the next row. If not, you get nothing but an open cursor with n
unfetched rows.

>BTW, I tried a First then
>While NOT EOF do begin Next end but still not firing the OnCallBack event.

A callback is an event of elapsed time, not "number of fetches". The
callback procedure itself suspends the database operation for as long as it
takes to do whatever it is that you want it to do. If you must have this
UI behaviour to reflect what is happening with the cursor, then you'll need
to 1) count the records before you start and 2) maintain a count of records
as each one is individually fetched, and have your callback procedure check
these numbers and do whatever you want to happen, e.g. advance your
progress bar. Do I need to comment that this sort of thing is very
anti-performance in a client/server system?

>For total rows I was just going to do a simple SELECT COUNT(id) thing,
>then use
>that. The UDF really slows down the query so that's the main stumbling
>block and
>the reason I want some kind of progress bar.

It sounds pretty weird to me to go to all this trouble just to retrieve a
one-row set. - which is effectively what you are doing with an
ib_cursor. Once a row has been fetched and you've finished whatever it was
you wanted to do, it is gone. Maybe you store some data in a
TStrings...perhaps an ib_cursorgrid...but you have no provisions here to
work with multiple rows on an ad hoc basis

>Its all about me trying to search an encrypted string or blob for a
>which is contained in the string--very straightforward if nothing was

In client/server, anything that takes more than a second or two should be
seriously looked at for a better way to do things. You can enclose a slow
operation in a BeginBusy...EndBusy block and display a custom cursor. This
is what Jason does in the Cursor tab of IB_SQL. He has a callback there
that periodically intervenes to display a Showmessage indicating the number
of rows fetched so far. But massive sets, or multi-row sets that are
slowed by an inefficient UDF are NOT cool for end-user applications.

>Jason's archived response to a similar plea for help suggested using the
>Procedure Suspend method of getting the OnCallBack event to fire for each
>of a row, but it just not working for me.

I'm not familiar with that particular archived response. I suppose that he
meant to maintain a record count inside the SP that gets incremented just
before the SUSPEND call and is passed across to the client as a field in
the output. Then a callback procedure could read that number...thus
avoiding the need to count the rows in on the client.

>Anymore suggestions?

Yes: but it would take a lot of time (a book, actually!) and I'm pretty
sure you wouldn't like them. :( You might like to review the TechInfo
sheet about writing apps for client/server, if you haven't
already. Processing megasets on the client in "for" loops doesn't sit well
with client/server.