Re: [sqlalchemy] How-to : update A also create an update of B

2012-08-31 Thread Tony Moutaux
Le jeudi 30 août 2012 17:16:40 UTC+2, Michael Bayer a écrit :

 def after_flush(session, flush_context):
 my_bs = figure_out_bs(session)
 new_session = Session(bind=session.connection())
 new_session.add_all(my_bs)

 # this won't actually COMMIT the transaction as we are 
 # already inside one
 new_session.commit()

 As I'm not the only developer for this application, I can't use pure SQL 
commands. 

I've tried the after_flush solution. It works.


What could be the problem to use setter ? For example

Class A has attribut family_id

@family_id.setter
def family_id(self, family_id):
   self._family_id = family_id
   update_linked_entities_with_family(family_id)

with update_linked_entities_with_family a function that grab and modify Bs.


You point that it could be used only for changing Python attributs. I use 
it to change SQLAlchemy entities and fields.

What could be the drawback of this solution ?

-- 
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To view this discussion on the web visit 
https://groups.google.com/d/msg/sqlalchemy/-/h11OiMXCyloJ.
To post to this group, send email to sqlalchemy@googlegroups.com.
To unsubscribe from this group, send email to 
sqlalchemy+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en.



[sqlalchemy] How-to : update A also create an update of B

2012-08-30 Thread Tony Moutaux
Hi there !

I'm going mad looking for a solution for what seems a simple problem.

When object A is updated, I also want object B to be updated, using some 
computation based on A new values.
From now, I can detect when A is modified using after_update.

What I try is to look at event Session.after_flush, if in Session.dirty 
there is an instance of A, I call the update of B. Within after_flush I can 
see Session.dirty with the modified B. But no SQL UPDATE is issued at all.

Any tip for me ?

-- 
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To view this discussion on the web visit 
https://groups.google.com/d/msg/sqlalchemy/-/d2bO9dVrSpUJ.
To post to this group, send email to sqlalchemy@googlegroups.com.
To unsubscribe from this group, send email to 
sqlalchemy+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en.



Re: [sqlalchemy] How-to : update A also create an update of B

2012-08-30 Thread Michael Bayer

On Aug 30, 2012, at 10:32 AM, Tony Moutaux wrote:

 Hi there !
 
 I'm going mad looking for a solution for what seems a simple problem.
 
 When object A is updated, I also want object B to be updated, using some 
 computation based on A new values.
 From now, I can detect when A is modified using after_update.
 
 What I try is to look at event Session.after_flush, if in Session.dirty there 
 is an instance of A, I call the update of B. Within after_flush I can see 
 Session.dirty with the modified B. But no SQL UPDATE is issued at all.
 
 Any tip for me ?


You do this kind of thing most simply within the objects themselves, not as 
much in Session events, depending on how things are organized.   Such as in the 
__init__() method of A, or by using an event listener on an attribute of A.

Only if some computation based on A new values means that there are SQL-level 
functions which you need to get at, does the rationale for 
after_update/after_flush events to come up.Unfortunately you can't emit 
a flush() within any of these events, as they are already local to the flush() 
call itself.Nor can you change the state of the Session within any of the 
after_ events, as the Session is already doing its work.  You can add new 
state to the Session within the after_flush_postexec() method, however you'd 
need to call flush() again for those changes to be flushed.

So the options:

1. if some computation is only in-Python computation, and *not* SQL 
functions, then set the state of B within object-level events, such as the 
__init__() of A, a @property on A, @validates events on A, or attribute events 
on A.

2.if some computation involves SQL functions:

a. emit your modifications to B using only SQL statements and 
Session.execute(), not by adding any new state to the Session or re-flushing.

b. pre-execute your SQL functions for A *outside* of the flush, then apply 
values to B as needed.

c. use a second Session inside the event:

def after_flush(session, flush_context):
my_bs = figure_out_bs(session)
new_session = Session(bind=session.connection())
new_session.add_all(my_bs)

# this won't actually COMMIT the transaction as we are 
# already inside one
new_session.commit()


-- 
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To post to this group, send email to sqlalchemy@googlegroups.com.
To unsubscribe from this group, send email to 
sqlalchemy+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en.



Re: [sqlalchemy] How-to : update A also create an update of B

2012-08-30 Thread Tony Moutaux


Only if some computation based on A new values means that there are 
 SQL-level functions which you need to get at, does the rationale for 
 after_update/after_flush events to come up.Unfortunately you can't 
 emit a flush() within any of these events, as they are already local to the 
 flush() call itself.Nor can you change the state of the Session within 
 any of the after_ events, as the Session is already doing its work.  You 
 can add new state to the Session within the after_flush_postexec() 
 method, however you'd need to call flush() again for those changes to be 
 flushed.


The computation will modify B, which is also a map of a table. 

So the options:

 1. if some computation is only in-Python computation, and *not* SQL 
 functions, then set the state of B within object-level events, such as the 
 __init__() of A, a @property on A, @validates events on A, or attribute 
 events on A.


I've used something like this :

A has field family_id, which trigger the modification of B (and not anly B, 
but also some more tables)

@family_id.setter
def family_id(self, family_id):
self._family_id = family_id
self.update_linked_entities_with_family(family_id)

Then at session.commit(), A is updated, but also the other linked entities.

This works. But it's not really nice, because any changes, even rollbacked 
one will call the update_linked_entitites method.


 2.if some computation involves SQL functions:

 a. emit your modifications to B using only SQL statements and 
 Session.execute(), not by adding any new state to the Session or 
 re-flushing.

 b. pre-execute your SQL functions for A *outside* of the flush, then 
 apply values to B as needed.

 c. use a second Session inside the event:

 def after_flush(session, flush_context):
 my_bs = figure_out_bs(session)
 new_session = Session(bind=session.connection())
 new_session.add_all(my_bs)

 # this won't actually COMMIT the transaction as we are 
 # already inside one
 new_session.commit()


I can read this, but I don't understand how to do this and not exactly how 
it works. It is 3 solutions right , not 3 points I have to go through ?

Step A : calling only Session.execute will output direct SQL commands, thus 
not modify the Session dirty list and the state.
Seems quiet easy but less readable because of the direct SQL commands.

Step B : what *outside* of the flush means ?

Step C : I will try this one because it seems nice, using 
Session/transaction.


Thank you for the explanation. I have a lot to do to fully understand 
SQLAlchemy.

-- 
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To view this discussion on the web visit 
https://groups.google.com/d/msg/sqlalchemy/-/DuspcAQVczsJ.
To post to this group, send email to sqlalchemy@googlegroups.com.
To unsubscribe from this group, send email to 
sqlalchemy+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en.



Re: [sqlalchemy] How-to : update A also create an update of B

2012-08-30 Thread Michael Bayer

On Aug 30, 2012, at 11:12 AM, Tony Moutaux wrote:

 
 
 2.if some computation involves SQL functions:
 
 a. emit your modifications to B using only SQL statements and 
 Session.execute(), not by adding any new state to the Session or re-flushing.
 
 b. pre-execute your SQL functions for A *outside* of the flush, then 
 apply values to B as needed.
 
 c. use a second Session inside the event:
 
 def after_flush(session, flush_context):
 my_bs = figure_out_bs(session)
 new_session = Session(bind=session.connection())
 new_session.add_all(my_bs)
 
 # this won't actually COMMIT the transaction as we are 
 # already inside one
 new_session.commit()
 
 I can read this, but I don't understand how to do this and not exactly how it 
 works. It is 3 solutions right , not 3 points I have to go through ?

three different ways to do it.

 
 Step A : calling only Session.execute will output direct SQL commands, thus 
 not modify the Session dirty list and the state.
 Seems quiet easy but less readable because of the direct SQL commands.

right, but is the most efficient and simple, if the changes you're emitting are 
also simple.

 
 Step B : what *outside* of the flush means ?

This option doesn't apply here, as you aren't dependent on SQL functions.   
outside the flush means, when you have your A and B and haven't called 
flush() yet.

-- 
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To post to this group, send email to sqlalchemy@googlegroups.com.
To unsubscribe from this group, send email to 
sqlalchemy+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en.