mirror of
https://github.com/sqlalchemy/sqlalchemy.git
synced 2026-05-24 01:22:00 -04:00
Move pk on single-inh subclass check below conflict resolution check
The column conflict resolution technique discussed at
:ref:`declarative_column_conflicts` is now functional for a :class:`.Column`
that is also a primary key column. Previously, a check for primary key
columns declared on a single-inheritance subclass would occur before the
column copy were allowed to pass.
Fixes: #4352
Change-Id: Id4c025da53c28e58db6b549fe398f25f8a90d355
Pull-request: https://github.com/zzzeek/sqlalchemy/pull/483
(cherry picked from commit 3ed79a5c18)
This commit is contained in:
committed by
Mike Bayer
parent
7a1c19833e
commit
6ec2246d04
+10
@@ -0,0 +1,10 @@
|
||||
.. change::
|
||||
:tags: bug, orm, declarative
|
||||
:tickets: 4352
|
||||
|
||||
The column conflict resolution technique discussed at
|
||||
:ref:`declarative_column_conflicts` is now functional for a :class:`.Column`
|
||||
that is also a primary key column. Previously, a check for primary key
|
||||
columns declared on a single-inheritance subclass would occur before the
|
||||
column copy were allowed to pass.
|
||||
|
||||
@@ -88,6 +88,8 @@ The attribute exclusion logic is provided by the
|
||||
behavior can be disabled by passing an explicit ``exclude_properties``
|
||||
collection (empty or otherwise) to the ``__mapper_args__``.
|
||||
|
||||
.. _declarative_column_conflicts:
|
||||
|
||||
Resolving Column Conflicts
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
||||
@@ -534,11 +534,6 @@ class _MapperConfig(object):
|
||||
)
|
||||
# add any columns declared here to the inherited table.
|
||||
for c in declared_columns:
|
||||
if c.primary_key:
|
||||
raise exc.ArgumentError(
|
||||
"Can't place primary key columns on an inherited "
|
||||
"class with no table."
|
||||
)
|
||||
if c.name in inherited_table.c:
|
||||
if inherited_table.c[c.name] is c:
|
||||
continue
|
||||
@@ -547,6 +542,11 @@ class _MapperConfig(object):
|
||||
"existing column '%s'" %
|
||||
(c, cls, inherited_table.c[c.name])
|
||||
)
|
||||
if c.primary_key:
|
||||
raise exc.ArgumentError(
|
||||
"Can't place primary key columns on an inherited "
|
||||
"class with no table."
|
||||
)
|
||||
inherited_table.append_column(c)
|
||||
if inherited_mapped_table is not None and \
|
||||
inherited_mapped_table is not inherited_table:
|
||||
|
||||
@@ -762,6 +762,75 @@ class DeclarativeInheritanceTest(DeclarativeTestBase):
|
||||
session.commit()
|
||||
eq_(session.query(Engineer).first().target, o1)
|
||||
|
||||
def test_columns_single_inheritance_conflict_resolution_pk(self):
|
||||
"""Test #2472 in terms of a primary key column. This is
|
||||
#4352.
|
||||
|
||||
"""
|
||||
class Person(Base):
|
||||
__tablename__ = 'person'
|
||||
id = Column(Integer, primary_key=True)
|
||||
|
||||
target_id = Column(Integer, primary_key=True)
|
||||
|
||||
class Engineer(Person):
|
||||
|
||||
"""single table inheritance"""
|
||||
|
||||
@declared_attr
|
||||
def target_id(cls):
|
||||
return cls.__table__.c.get(
|
||||
'target_id',
|
||||
Column(Integer, primary_key=True))
|
||||
|
||||
class Manager(Person):
|
||||
|
||||
"""single table inheritance"""
|
||||
|
||||
@declared_attr
|
||||
def target_id(cls):
|
||||
return cls.__table__.c.get(
|
||||
'target_id',
|
||||
Column(Integer, primary_key=True))
|
||||
|
||||
is_(
|
||||
Engineer.target_id.property.columns[0],
|
||||
Person.__table__.c.target_id
|
||||
)
|
||||
is_(
|
||||
Manager.target_id.property.columns[0],
|
||||
Person.__table__.c.target_id
|
||||
)
|
||||
|
||||
def test_columns_single_inheritance_cascading_resolution_pk(self):
|
||||
"""An additional test for #4352 in terms of the requested use case.
|
||||
|
||||
"""
|
||||
class TestBase(Base):
|
||||
__abstract__ = True
|
||||
|
||||
@declared_attr.cascading
|
||||
def id(cls):
|
||||
col_val = None
|
||||
if TestBase not in cls.__bases__:
|
||||
col_val = cls.__table__.c.get('id')
|
||||
if col_val is None:
|
||||
col_val = Column(Integer, primary_key=True)
|
||||
return col_val
|
||||
|
||||
class Person(TestBase):
|
||||
"""single table base class"""
|
||||
__tablename__ = 'person'
|
||||
|
||||
class Engineer(Person):
|
||||
""" single table inheritance, no extra cols """
|
||||
|
||||
class Manager(Person):
|
||||
""" single table inheritance, no extra cols """
|
||||
|
||||
is_(Engineer.id.property.columns[0], Person.__table__.c.id)
|
||||
is_(Manager.id.property.columns[0], Person.__table__.c.id)
|
||||
|
||||
def test_joined_from_single(self):
|
||||
|
||||
class Company(Base, fixtures.ComparableEntity):
|
||||
|
||||
Reference in New Issue
Block a user