johnf wrote:
> On Wednesday 15 August 2007 15:58, Uwe Grauer wrote:
>> Yes, i also think that we need something like ExplicitTransactions.
>>
>> We should do some sort of matrix for all possible cases.
>> The point is, the current dabo behavior doesn't support all cases.
>>
>> I can't understand why the firebird case, where i can't control the
>> transaction behavior, isn't enough to know that something is wrong.
>> How can i do a transaction over two inserts and rollback if the second
>> one throws an error?
I think we agree that the app developer should be able to have more
control over the transaction behavior. We are just exploring how to go
about doing that.
> Currently Dabo does
>
> insert ....
> commit
> insert ....
> commit
>
> and Uwe wants
> begin
> insert...
> insert...
> commit.
>
> In the general the first case works for the simple saves - IOW works with one
> table. But could cause issues for multi-table insert and updates.
If I call biz.save() to save just the current record, I would expect:
begin (could be implicit)
insert
commit
However, if I call biz.saveAll() to save all records, I would expect:
begin
insert
insert
update
...
commit
and a rollback if anything failed.
Now.. AutoCommit. As it works now, if I understand correctly, if
AutoCommit is True, that means the backend is going to automatically do
a commit() after every DML operation. IOW, the saveAll() call will
result in:
begin
insert
commit (done by the backend)
insert
commit (done by the backend)
update
commit (done by the backend)
...which isn't ideal but is convenient for simple cases. And if
AutoCommit is False, Dabo will do the commit() when needed, which may
indeed be too often if it happens multiple times in biz.saveAll().
> I just ran a simple test on Postgres (Postgres handles the 'begin') with the
> following results:
>
> Adding two records to a child table I get:
> insert
> commit
> insert
> commit
> What I would have expected.
>
> adding a new parent and two new children I get:
> insert parent
> insert child
> commit
> insert child
> commit.
You don't say if the above is the result of two save() calls, or a
single saveAll() call. I'll assume saveAll().
In essence, Dabo is assuming that the save of each parent record is a
single transaction. When bizParent.saveAll() is called, a transaction is
started for each changed parent record, and then all the inserts and
updates for that parent and children occur, followed by a commit. Then
the process is repeated for the other changed parent records.
For most of my apps, this behavior is just fine. However, I can see
wanting to do something like:
biz.beginTransaction()
try:
biz.saveAll()
except Exception, e:
# figure out what was wrong, and show the user
biz.rollbackTransaction()
biz.commitTransaction()
Dabo would have to do extra things on the rollbackTransaction(), to make
sure the dabo cursor is in the same state as it was when
beginTransaction() was called (it wouldn't be if, for instance, autoinc
primary key values were gotten from the backend and stuffed into the
cursor field).
> Larry has recently written code to support complete transactions by over
> riding Save() and SaveAll() for a bizObj. But we are currently treating the
> code as a special situation. We might have used Postgres rules or triggers
> but felt better about handling the transaction from code.
>
> I wonder if what Dabo is doing is all that bad? How does sqlalchemy handle
> the situation?
>
> Uwe could of course handle the inserts,updates,and deletes in code.
I believe the problem Uwe is having boils down to the inability to set
AutoCommit to True, because dBackend won't let him:
def setAutoCommitStatus(self, cursor, val):
if hasattr(self._connection, "autocommit"):
self._connection.autocommit(val)
self._autoCommit = val
else:
# Without an autocommit method, assume no autocommit.
self._autoCommit = False
if val:
raise ValueError, "Can't set AutoCommit to True
for this backend."
This results in the commit() happening after every changed record is
saved in saveAll(), and the inability to rollback all the saved records
because each record is getting its own transaction.
Actually, Uwe mentioned that firebird does indeed have an autocommit()
method, but firebird does something that isn't desired in autocommit, so
he wants it turned off. But, turning it off results in Dabo doing the
commits automatically.
Uwe, when you set AutoCommit to True, do you get the ValueError
exception or no?
We definitely need to review how this is working, and how it should
work. I can see from the code, for instance, that biz.saveAll() will
start a transaction and commit afterwards, with no obvious way to stop
that if AutoCommit is False (you could set the topLevel arg to False,
but that isn't intuitive and - I don't know - could cause other
side-effents).
--
pkm ~ http://paulmcnett.com
_______________________________________________
Post Messages to: [email protected]
Subscription Maintenance: http://leafe.com/mailman/listinfo/dabo-dev
Searchable Archives: http://leafe.com/archives/search/dabo-dev
This message: http://leafe.com/archives/byMID/dabo-dev/[EMAIL PROTECTED]