Declaring a relationship twice - could SqlAlchemy auto-detect problems like this?

18 views
Skip to first unread message

Barry Hart

unread,
Oct 24, 2007, 4:16:39 PM10/24/07
to sqlal...@googlegroups.com
This subject came up on the TurboGears list and someone suggested I post here.

I noticed a while back that in SqlAlchemy 0.3.x, if you have two mapped classes A and B, and you define the same relationship (with a backref) on both classes, you won't get an error message but the two relationships interfere with each other. For example, you might set the value of the relationship and it won't be saved to the database. Would it be possible to detect and flag this as an error at model compilation time?

Perhaps there are other model problems like this which could be detected automatically. If so, I think it would really flatten the learning curve for SqlAlchemy newbies.

Barry



__________________________________________________
Do You Yahoo!?
Tired of spam? Yahoo! Mail has the best spam protection around
http://mail.yahoo.com

Michael Bayer

unread,
Oct 24, 2007, 4:41:46 PM10/24/07
to sqlal...@googlegroups.com

On Oct 24, 2007, at 4:16 PM, Barry Hart wrote:

This subject came up on the TurboGears list and someone suggested I post here.

I noticed a while back that in SqlAlchemy 0.3.x, if you have two mapped classes A and B, and you define the same relationship (with a backref) on both classes, you won't get an error message but the two relationships interfere with each other. For example, you might set the value of the relationship and it won't be saved to the database. Would it be possible to detect and flag this as an error at model compilation time?


hey Barry -

that would be a bug, and I cant reproduce it, at least the bug i think youre describing, in neither 0.3 nor 0.4:

from sqlalchemy import *
from sqlalchemy.orm import *

engine = create_engine('sqlite://')
meta = MetaData(engine)

a = Table('a', meta, Column('id', Integer, primary_key=True))
b = Table('b', meta, Column('id', Integer, primary_key=True), Column('a_id', Integer, ForeignKey('a.id')))
c = Table('c', meta, Column('id', Integer, primary_key=True), Column('a_id', Integer, ForeignKey('a.id')))

class A(object):pass
class B(object):pass
class C(object):pass

mapper(A, a)
mapper(B, b, properties={
    'a':relation(A, backref='thebackref')
})
mapper(C, c, properties={
    'a':relation(A, backref='thebackref')
})

compile_mappers()

output:

<stack trace>
sqlalchemy.exceptions.ArgumentError: Backrefs do not match:  backref 'thebackref' expects to connect to <class '__main__.C'>, but found a backref already connected to <class '__main__.B'>


can you produce a test case ?




Barry Hart

unread,
Oct 24, 2007, 5:02:20 PM10/24/07
to sqlal...@googlegroups.com
Here's what I had in mind. This set of mappings compiles without errors in 0.3.11:


from sqlalchemy import *
from sqlalchemy.orm import *

engine = create_engine('sqlite://')
meta = MetaData(engine)

a = Table('a', meta, Column('id', Integer, primary_key=True))
b = Table('b', meta, Column('id', Integer, primary_key=True), Column('a_id', Integer, ForeignKey('a.id')))

class A(object):pass
class B(object):pass
class C(object):pass

mapper(A, a, properties={
    'b':relation(B, backref='a')
})
mapper(B, b, properties={
    'a':relation(A, backref='b')
})

compile_mappers()

Barry

Michael Bayer

unread,
Oct 24, 2007, 5:42:57 PM10/24/07
to sqlal...@googlegroups.com
On Oct 24, 2007, at 5:02 PM, Barry Hart wrote:

Here's what I had in mind. This set of mappings compiles without errors in 0.3.11:

ok barry, the fix for this will be in 0.4.xx and will require some tinkering, since backrefs when they configure do expect to find names in both directions, so their creation logic will have to be made a little more savvy. ticket is #832.  in the majority of cases we already do detect duplicate relation definitions.

- mike


Michael Bayer

unread,
Oct 24, 2007, 7:26:39 PM10/24/07
to sqlal...@googlegroups.com
On Oct 24, 2007, at 5:02 PM, Barry Hart wrote:

Here's what I had in mind. This set of mappings compiles without errors in 0.3.11:

from sqlalchemy import *


OK, thanks very much for pointing this one out, as it came across a big heap of egregious cruft in the backref code which I graciously flattened (it even included the phrase "if not x is not None"...so embarrassing...).  It also raised a few surprises as there were a very small number of unit tests that were actually defining conflicting properties in this manner...so when people upgrade to 0.4.1 some people might get a few surprises (that alone makes it more controversial of a candidate for the 0.3 series, which is in "maintenance" mode).  changeset is rev 3660.


Barry Hart

unread,
Oct 24, 2007, 9:58:28 PM10/24/07
to sqlal...@googlegroups.com
That is awesome -- thanks. I would've reported it sooner, but I thought maybe I was the only one silly enough to make these mistakes in my mappers. :-)

Barry

----- Original Message ----
From: Michael Bayer <mik...@zzzcomputing.com>
To: sqlal...@googlegroups.com
Sent: Wednesday, October 24, 2007 7:26:39 PM
Subject: [sqlalchemy] Re: Declaring a relationship twice - could SqlAlchemy auto-detect problems like this?


Reply all
Reply to author
Forward
0 new messages