Subject Re: [IBO] TIBOQuery & CachedUpdates - Insert not working
Author Helen Borrie
At 04:48 PM 20/03/2005 +0000, you wrote:

>I'm trying to use a simple (TDataset compatible) query with
>CachedUpdates, but I can't get it to work.
>I try:
> Query.Insert
> ...
> Transaction.StartTransaction
> ...
> Query.ApplyUpdates
> ...
> Transaction.Commit
>But nothing gets written to the table.
>Some interesting notes:
>1. Immediately after the insert I placed "IF Query.UpdatesPending THEN
>Beep" - but UpdatesPending is FALSE! How can that be if I've just
>inserted a record?

Because you haven't inserted a record in the dataset, but in a cache buffer
that is isolated from the dataset's transaction!

Your problem here is that your code separates the cache from the
transaction in which the task occurs. The sequence has to be

Query.Open (or Refresh)
(insert rows into the cache)
... (mess around inside the cache if desired)
Query.ApplyUpdates (posts all new rows)

Caching simply alters the normal course of events for updating datasets,
which is as follows:

Query.Open (or Refresh)
(insert one row, no more messing around)

Query.Post (posts the current row)

That is, it changes the "attack target" for the Post operation to be
(potentially) multiple rows, rather than just the current
row. ApplyUpdates takes each cached row, one by one, and posts a DML
statement for it.

>2. I tried tracing into the ApplyUpdates code (had to purchase IBO to
>get sources even though my app isn't ready). At some point the code
>calls CheckBrowsMode, which doesn't return to the ApplyUpdates method
>but to the Cancel method. This may be a debugger bug, but I really
>don't understand what's going on and why.

Does it help to visualise the decision that the dataset has to make when
Post (or ApplyUpdates) is called?

--- When the target is the current row (no caching, and Post is called), it
tests that the set is still in the appropriate mode and tries to post the
DML statement pertaining to that row. If the post succeeds, or Cancel is
called, the dataset returns to browse mode. If Post fails, the dataset
stays in the editing mode until Cancel is called.

--- When the target is the cached set (ApplyUpdates is called), it tests
that the set is still in the appropriate mode and proceeds to loop through
the cache, calling Post for each new/changed row. If all posts succeed, or
CancelUpdates is called, the dataset returns to browse mode. CommitUpdates
clears the cache. If any Post fails, the dataset stays in the editing
mode. Anything that was already posted stays posted (but not
committed!). If CancelUpdates is called, the remaining changes are undone
and the dataset returns to browse mode. (The already posted rows will be
committed or rolled back when you call Commit or Rollback on the transaction).

>3. I changed the Query to non-cached and tried to Post instead of
>ApplyUpdates - and it works without a problem. This indicates that my
>insert statement is ok.
>Any ideas?

Just keep in mind that all dataset operations occur in the context of a
specific transaction: the SELECT (or re-select, when Refresh is called
instead of Open), followed by one or more DML operations. Post operates on
one row, ApplyUpdates operates on all rows marked as added, changed or
deleted since ApplyUpdates was last called. Commit (followed by
CommitUpdates, in the case of cached updates) clears the slate and you
start again with a fresh view of database state.