@_memoized_configured_property
def _sorted_tables(self):
table_to_mapper = {}
+ table_to_mapper_08 = {}
for mapper in self.base_mapper.self_and_descendants:
for t in mapper.tables:
table_to_mapper[t] = mapper
-
- sorted_ = sqlutil.sort_tables(table_to_mapper.iterkeys())
+ # emulate 0.8's approach to fix #2689
+ table_to_mapper_08.setdefault(t, mapper)
+
+ extra_dependencies = []
+ for table, mapper in table_to_mapper_08.items():
+ super_ = mapper.inherits
+ if super_:
+ extra_dependencies.extend([
+ (super_table, table)
+ for super_table in super_.tables
+ ])
+
+ sorted_ = sqlutil.sort_tables(table_to_mapper.iterkeys(),
+ extra_dependencies=extra_dependencies)
ret = util.OrderedDict()
for t in sorted_:
ret[t] = table_to_mapper[t]
"""Utility functions that build upon SQL and Schema constructs."""
-def sort_tables(tables):
+def sort_tables(tables, extra_dependencies=None):
"""sort a collection of Table objects in order of their foreign-key dependency."""
tables = list(tables)
tuples = []
+ if extra_dependencies:
+ tuples.extend(extra_dependencies)
+
def visit_foreign_key(fkey):
if fkey.use_alter:
return
for table in tables:
visitors.traverse(table,
- {'schema_visitor':True},
- {'foreign_key':visit_foreign_key})
+ {'schema_visitor': True},
+ {'foreign_key': visit_foreign_key})
tuples.extend(
[parent, table] for parent in table._extra_dependencies
sess.flush()
assert user_roles.count().scalar() == 1
+class JoinedNoFKSortingTest(fixtures.MappedTest):
+ @classmethod
+ def define_tables(cls, metadata):
+ Table("a", metadata,
+ Column('id', Integer, primary_key=True,
+ test_needs_autoincrement=True)
+ )
+ Table("b", metadata,
+ Column('id', Integer, primary_key=True)
+ )
+ Table("c", metadata,
+ Column('id', Integer, primary_key=True)
+ )
+
+ @classmethod
+ def setup_classes(cls):
+ class A(cls.Basic):
+ pass
+ class B(A):
+ pass
+ class C(A):
+ pass
+
+ @classmethod
+ def setup_mappers(cls):
+ A, B, C = cls.classes.A, cls.classes.B, cls.classes.C
+ mapper(A, cls.tables.a)
+ mapper(B, cls.tables.b, inherits=A,
+ inherit_condition=cls.tables.a.c.id == cls.tables.b.c.id)
+ mapper(C, cls.tables.c, inherits=A,
+ inherit_condition=cls.tables.a.c.id == cls.tables.c.c.id)
+
+ def test_ordering(self):
+ B, C = self.classes.B, self.classes.C
+ sess = Session()
+ sess.add_all([B(), C(), B(), C()])
+ self.assert_sql_execution(
+ testing.db,
+ sess.flush,
+ CompiledSQL(
+ "INSERT INTO a () VALUES ()",
+ {}
+ ),
+ CompiledSQL(
+ "INSERT INTO a () VALUES ()",
+ {}
+ ),
+ CompiledSQL(
+ "INSERT INTO a () VALUES ()",
+ {}
+ ),
+ CompiledSQL(
+ "INSERT INTO a () VALUES ()",
+ {}
+ ),
+ AllOf(
+ CompiledSQL(
+ "INSERT INTO b (id) VALUES (:id)",
+ [{"id": 1}, {"id": 3}]
+ ),
+ CompiledSQL(
+ "INSERT INTO c (id) VALUES (:id)",
+ [{"id": 2}, {"id": 4}]
+ )
+ )
+ )
+
class VersioningTest(fixtures.MappedTest):
@classmethod
def define_tables(cls, metadata):