- The `echo_uow` flag on `Session` is deprecated, and unit-of-work
logging is now application-level only, not per-session level.
+
+- declarative
+ - Fixed bug whereby mapper couldn't initialize if a composite
+ primary key referenced another table that was not defined
+ yet [ticket:1161]
- schema
- Added "sorted_tables" accessor to MetaData, which returns
# determine primary key from argument or mapped_table pks - reduce to the minimal set of columns
if self.primary_key_argument:
primary_key = sqlutil.reduce_columns(
- self.mapped_table.corresponding_column(c)
- for c in self.primary_key_argument)
+ [self.mapped_table.corresponding_column(c) for c in self.primary_key_argument],
+ ignore_nonexistent_tables=True)
else:
primary_key = sqlutil.reduce_columns(
- self._pks_by_table[self.mapped_table])
+ self._pks_by_table[self.mapped_table], ignore_nonexistent_tables=True)
if len(primary_key) == 0:
raise sa_exc.ArgumentError("Mapper %s could not assemble any primary key columns for mapped table '%s'" % (self, self.mapped_table.description))
return ret
-def reduce_columns(columns, *clauses):
+def reduce_columns(columns, *clauses, **kw):
"""given a list of columns, return a 'reduced' set based on natural equivalents.
the set is reduced to the smallest list of columns which have no natural
\*clauses is an optional list of join clauses which will be traversed
to further identify columns that are "equivalent".
+ \**kw may specify 'ignore_nonexistent_tables' to ignore foreign keys
+ whose tables are not yet configured.
+
This function is primarily used to determine the most minimal "primary key"
from a selectable, by reducing the set of primary key columns present
in the the selectable to just those that are not repeated.
"""
+ ignore_nonexistent_tables = kw.pop('ignore_nonexistent_tables', False)
+
columns = util.OrderedSet(columns)
omit = set()
for c in columns:
if c is col:
continue
- if fk.column.shares_lineage(c):
+ try:
+ fk_col = fk.column
+ except exc.NoReferencedTableError:
+ if ignore_nonexistent_tables:
+ continue
+ else:
+ raise
+ if fk_col.shares_lineage(c):
omit.add(col)
break
Address(email='one'),
Address(email='two')])])
+ def test_pk_with_fk_init(self):
+ class Bar(Base):
+ __tablename__ = 'bar'
+
+ id = sa.Column(sa.Integer, sa.ForeignKey("foo.id"), primary_key=True)
+ ex = sa.Column(sa.Integer, primary_key=True)
+
+ class Foo(Base):
+ __tablename__ = 'foo'
+
+ id = sa.Column(sa.Integer, primary_key=True)
+ bars = sa.orm.relation(Bar)
+
+ assert Bar.__mapper__.primary_key[0] is Bar.__table__.c.id
+ assert Bar.__mapper__.primary_key[1] is Bar.__table__.c.ex
+
def test_single_inheritance(self):
class Company(Base, ComparableEntity):
__tablename__ = 'companies'