Hi Alan -

this idea has been mentioned before, and i have a mention about it in  
the docs (probably should add to the FAQ).  basically, if you are  
playing around with the foreign key identifiers, SA's core ORM has no  
awareness of that...its interaction with the database is much simpler  
than that (it tries to be as simple as possible).   it has no idea  
about the meaning of a foreign key identifier until its inside of a  
flush().   my impression is that it would be a lot more complicated,  
and add significant latency to attribute operations, for it to  
reconcile foreign key values as attributes are attached and detached  
to each other.  if we consider the other direction, such as  if i say  
x.user_id=27, and there is no 27 in the identity map..its ambiguous  
what should happen then.  I could do a lazy load (adds latency that  
might not be desired), or throw an error message.  But then, what if  
you just assigned #27 as the primary key on a transient (unsaved)  
user object...we arent tracking that either, as transient instances  
dont have an "identity" until they are flushed.  or #27 exists with  
an identity but it was marked for deletion.  There are a lot of  
complicated conditions that immediately arise, and by keeping tabs on  
all primary/foreign key values and their status in memory, we're  
starting to duplicate the functionality of the entire database.   as  
soon as SA is duplicating functionality that is already in the  
database, thats its primary "red flag" that its going down a path it  
shouldnt be.

now, if someone were really ambitious, they could create their own  
attribute plugins to attempt this functionality; it is reasonably  
straightforward to add event handlers to the attributes created by  
relation() (just not documented as of yet).  if someone wants to get  
into that, im not opposed; but its definitely something for an  
extension or external project, since it would complicate and slow  
down things considerably for it to be built in the core (and also i  
dont think it would ever work completely the way someone expects).

- mike

On Aug 22, 2006, at 10:04 AM, Alan Franzoni wrote:

> Hello, I've found what I think is an unexpected behaviour in  
> sqlalchemy; it
> has to do with mapped objects and foreign keys handling. Check out  
> this
> snippet:
>
> #begin
> # -*- coding: iso-8859-1 -*-
> #main.py
>
> from sqlalchemy import *
>
> db = create_engine("sqlite://testdb.db")
>
>
> metadata = BoundMetaData(db)
>
> users = Table("users", metadata,
>        Column("user_id", Integer, primary_key=True),
>        Column("text", String),
> )
>
> addresses = Table("addresses", metadata,
>           Column("address_id", Integer, primary_key=True),
>           Column("user_id", Integer, ForeignKey("users.user_id"))
>                   )
>
> users.create(checkfirst=True)
> addresses.create(checkfirst=True)
>
> class User(object):
>     pass
>
> class Address(object):
>     pass
>
>
> def print_user_and_id(obj):
>     print "user is %s, user_id is %s" % (obj.user, obj.user_id)
>
> Address.mapper = mapper(Address, addresses)
> User.mapper = mapper(User, users, properties = {"addresses":
> relation(Address, backref="user")})
>
> session = create_session(bind_to=db)
>
> trans = session.create_transaction()
>
> user1 = User()
> user1.user_id = 10
> user1.text = "Hello World"
>
> user2 = User()
> user2.user_id = 20
> user2.text = "Hello World 2"
>
> addr1 = Address()
>
> session.save(user1)
> session.save(user2)
> session.save(addr1)
>
> addr1.user_id = user1.user_id
>
> print_user_and_id(addr1)
>
> session.flush()
>
> print_user_and_id(addr1)
>
> session.refresh(addr1)
>
> print_user_and_id(addr1)
>
> addr1.user = user2
> addr1.user_id = 10
>
> print_user_and_id(addr1)
>
> session.flush()
>
> print_user_and_id(addr1)
> #end
>
> this is the output:
>
> user is None, user_id is 10
> user is None, user_id is 10
> user is <__main__.User object at 0x00C90030>, user_id is 10
> user is <__main__.User object at 0x00C90050>, user_id is 10
> user is <__main__.User object at 0x00C90050>, user_id is 20
>
>
> What I think is unexpected is the missing constant 'link' between the
> helper property (user), which accepts User objects, and the mapped  
> property
> (user_id), which accepts integers. I would imagine that, if I  
> changed the
> 'user' property, the 'user_id' would immediately reflect that  
> change, and
> viceversa - after all, why not? I can't think of any possible  
> drawback.
>
> This way, in order to get the correct values, I need to do a
> session.refresh(obj), which can be a bit messy (it's a bit of pain  
> to do it
> again and again).
>
> Also, the final code snippet is not clear:
>
> addr1.user = user2
> addr1.user_id = 10
>
> In this case, it seems that the 'user' property has priority (when  
> flushed,
> the addr1 object has a user_id of 20), even though the user_id gets  
> set
> later; is it always the case or might this change depending on what  
> code is
> written?
>
> IMHO the objects should either react immediately to a related property
> change, or they shouldn't be both directly accessible, e.g. I  
> should only
> be able to use either user_id or user on an Address object at a  
> time, not
> both.
>
> -- 
> Alan Franzoni <[EMAIL PROTECTED]>
> -
> Togli .xyz dalla mia email per contattarmi.
> Rremove .xyz from my address in order to contact me.
> -
> GPG Key Fingerprint:
> 5C77 9DC3 BD5B 3A28 E7BC 921A 0255 42AA FE06 8F3E
> -
> Blog: http://laterradeglieroi.verdiperronchi.com
>
>
> ---------------------------------------------------------------------- 
> ---
> Using Tomcat but need to do more? Need to support web services,  
> security?
> Get stuff done quickly with pre-integrated technology to make your  
> job easier
> Download IBM WebSphere Application Server v.1.0.1 based on Apache  
> Geronimo
> http://sel.as-us.falkag.net/sel? 
> cmd=lnk&kid=120709&bid=263057&dat=121642
> _______________________________________________
> Sqlalchemy-users mailing list
> Sqlalchemy-users@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/sqlalchemy-users


-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
Sqlalchemy-users mailing list
Sqlalchemy-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/sqlalchemy-users

Reply via email to