From: Mike Bayer Date: Thu, 30 Aug 2007 15:55:41 +0000 (+0000) Subject: - fixed bugs in determining proper sync clauses from custom inherit X-Git-Tag: rel_0_4beta6~68 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=ea13716accf2d60a25414638bb8abd5403a6bd20;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git - fixed bugs in determining proper sync clauses from custom inherit conditions [ticket:769] --- diff --git a/CHANGES b/CHANGES index 239ffaa7b5..81a00cd314 100644 --- a/CHANGES +++ b/CHANGES @@ -5,6 +5,9 @@ CHANGES 0.4.0beta5 ---------- +- fixed bugs in determining proper sync clauses from custom inherit + conditions [ticket:769] + - Extended 'engine_from_config' coercion for QueuePool size / overflow. [ticket:763] diff --git a/lib/sqlalchemy/orm/sync.py b/lib/sqlalchemy/orm/sync.py index 795d76b1af..d858428611 100644 --- a/lib/sqlalchemy/orm/sync.py +++ b/lib/sqlalchemy/orm/sync.py @@ -9,7 +9,7 @@ attributes between two objects in a manner corresponding to a SQL clause that compares column values. """ -from sqlalchemy import schema, exceptions +from sqlalchemy import schema, exceptions, util from sqlalchemy.sql import visitors, operators from sqlalchemy import logging from sqlalchemy.orm import util as mapperutil @@ -53,10 +53,10 @@ class ClauseSynchronizer(object): if binary.left.table == binary.right.table: raise exceptions.ArgumentError("need foreign_keys argument for self-referential sync") - if binary.left in [f.column for f in binary.right.foreign_keys]: + if binary.left in util.Set([f.column for f in binary.right.foreign_keys]): dest_column = binary.right source_column = binary.left - elif binary.right in [f.column for f in binary.left.foreign_keys]: + elif binary.right in util.Set([f.column for f in binary.left.foreign_keys]): dest_column = binary.left source_column = binary.right else: diff --git a/test/orm/inheritance/basic.py b/test/orm/inheritance/basic.py index ae709b7c5f..870f3e8692 100644 --- a/test/orm/inheritance/basic.py +++ b/test/orm/inheritance/basic.py @@ -405,6 +405,73 @@ class DistinctPKTest(ORMTest): assert alice1.name == alice2.name == 'alice' assert bob.name == 'bob' +class SyncCompileTest(ORMTest): + """test that syncrules compile properly on custom inherit conds""" + def define_tables(self, metadata): + global _a_table, _b_table, _c_table + + _a_table = Table('a', metadata, + Column('id', Integer, primary_key=True), + Column('data1', String) + ) + + _b_table = Table('b', metadata, + Column('a_id', Integer, ForeignKey('a.id'), primary_key=True), + Column('data2', String) + ) + + _c_table = Table('c', metadata, + # Column('a_id', Integer, ForeignKey('b.a_id'), primary_key=True), #works + Column('b_a_id', Integer, ForeignKey('b.a_id'), primary_key=True), + Column('data3', String) + ) + + def test_joins(self): + for j1 in (None, _b_table.c.a_id==_a_table.c.id, _a_table.c.id==_b_table.c.a_id): + for j2 in (None, _b_table.c.a_id==_c_table.c.b_a_id, _c_table.c.b_a_id==_b_table.c.a_id): + self._do_test(j1, j2) + for t in _a_table.metadata.table_iterator(reverse=True): + t.delete().execute().close() + + def _do_test(self, j1, j2): + class A(object): + def __init__(self, **kwargs): + for key, value in kwargs.items(): + setattr(self, key, value) + + class B(A): + pass + + class C(B): + pass + + mapper(A, _a_table) + mapper(B, _b_table, inherits=A, + inherit_condition=j1 + ) + mapper(C, _c_table, inherits=B, + inherit_condition=j2 + ) + + session = create_session() + + a = A(data1='a1') + session.save(a) + + b = B(data1='b1', data2='b2') + session.save(b) + + c = C(data1='c1', data2='c2', data3='c3') + session.save(c) + + session.flush() + session.clear() + + assert len(session.query(A).all()) == 3 + assert len(session.query(B).all()) == 2 + assert len(session.query(C).all()) == 1 + + if __name__ == "__main__": testbase.main()