mirror of
https://github.com/sqlalchemy/sqlalchemy.git
synced 2026-06-02 05:48:52 -04:00
75a3f84e5f
mapper configuration; will now test for name conflicts on superclasses and subclasses, in addition to the current mapper, as these conflicts break things just as much. This is new for 0.8, but see below for a warning that will also be triggered in 0.7.11. - Improved the error message emitted when a "backref loop" is detected, that is when an attribute event triggers a bidirectional assignment between two other attributes with no end. This condition can occur not just when an object of the wrong type is assigned, but also when an attribute is mis-configured to backref into an existing backref pair. Also in 0.7.11. - A warning is emitted when a MapperProperty is assigned to a mapper that replaces an existing property, if the properties in question aren't plain column-based properties. Replacement of relationship properties is rarely (ever?) what is intended and usually refers to a mapper mis-configuration. Also in 0.7.11. [ticket:2674]
214 lines
6.7 KiB
Python
214 lines
6.7 KiB
Python
from sqlalchemy import *
|
|
from sqlalchemy import exc as sa_exc
|
|
from sqlalchemy.orm import *
|
|
from sqlalchemy.testing import assert_raises_message
|
|
from sqlalchemy.testing import fixtures
|
|
from sqlalchemy import testing
|
|
|
|
|
|
class CompileTest(fixtures.ORMTest):
|
|
"""test various mapper compilation scenarios"""
|
|
|
|
def teardown(self):
|
|
clear_mappers()
|
|
|
|
def test_with_polymorphic(self):
|
|
metadata = MetaData(testing.db)
|
|
|
|
order = Table('orders', metadata,
|
|
Column('id', Integer, primary_key=True),
|
|
Column('employee_id', Integer, ForeignKey('employees.id'), nullable=False),
|
|
Column('type', Unicode(16)))
|
|
|
|
employee = Table('employees', metadata,
|
|
Column('id', Integer, primary_key=True),
|
|
Column('name', Unicode(16), unique=True, nullable=False))
|
|
|
|
product = Table('products', metadata,
|
|
Column('id', Integer, primary_key=True),
|
|
)
|
|
|
|
orderproduct = Table('orderproducts', metadata,
|
|
Column('id', Integer, primary_key=True),
|
|
Column('order_id', Integer, ForeignKey("orders.id"), nullable=False),
|
|
Column('product_id', Integer, ForeignKey("products.id"), nullable=False),
|
|
)
|
|
|
|
class Order(object):
|
|
pass
|
|
|
|
class Employee(object):
|
|
pass
|
|
|
|
class Product(object):
|
|
pass
|
|
|
|
class OrderProduct(object):
|
|
pass
|
|
|
|
order_join = order.select().alias('pjoin')
|
|
|
|
order_mapper = mapper(Order, order,
|
|
with_polymorphic=('*', order_join),
|
|
polymorphic_on=order_join.c.type,
|
|
polymorphic_identity='order',
|
|
properties={
|
|
'orderproducts': relationship(OrderProduct, lazy='select', backref='order')}
|
|
)
|
|
|
|
mapper(Product, product,
|
|
properties={
|
|
'orderproducts': relationship(OrderProduct, lazy='select', backref='product')}
|
|
)
|
|
|
|
mapper(Employee, employee,
|
|
properties={
|
|
'orders': relationship(Order, lazy='select', backref='employee')})
|
|
|
|
mapper(OrderProduct, orderproduct)
|
|
|
|
# this requires that the compilation of order_mapper's "surrogate
|
|
# mapper" occur after the initial setup of MapperProperty objects on
|
|
# the mapper.
|
|
configure_mappers()
|
|
|
|
def test_conflicting_backref_one(self):
|
|
"""test that conflicting backrefs raises an exception"""
|
|
|
|
metadata = MetaData(testing.db)
|
|
|
|
order = Table('orders', metadata,
|
|
Column('id', Integer, primary_key=True),
|
|
Column('type', Unicode(16)))
|
|
|
|
product = Table('products', metadata,
|
|
Column('id', Integer, primary_key=True),
|
|
)
|
|
|
|
orderproduct = Table('orderproducts', metadata,
|
|
Column('id', Integer, primary_key=True),
|
|
Column('order_id', Integer, ForeignKey("orders.id"), nullable=False),
|
|
Column('product_id', Integer, ForeignKey("products.id"), nullable=False),
|
|
)
|
|
|
|
class Order(object):
|
|
pass
|
|
|
|
class Product(object):
|
|
pass
|
|
|
|
class OrderProduct(object):
|
|
pass
|
|
|
|
order_join = order.select().alias('pjoin')
|
|
|
|
order_mapper = mapper(Order, order,
|
|
with_polymorphic=('*', order_join),
|
|
polymorphic_on=order_join.c.type,
|
|
polymorphic_identity='order',
|
|
properties={
|
|
'orderproducts': relationship(OrderProduct, lazy='select', backref='product')}
|
|
)
|
|
|
|
mapper(Product, product,
|
|
properties={
|
|
'orderproducts': relationship(OrderProduct, lazy='select', backref='product')}
|
|
)
|
|
|
|
mapper(OrderProduct, orderproduct)
|
|
|
|
assert_raises_message(
|
|
sa_exc.ArgumentError,
|
|
"Error creating backref",
|
|
configure_mappers
|
|
)
|
|
|
|
def test_misc_one(self):
|
|
metadata = MetaData(testing.db)
|
|
node_table = Table("node", metadata,
|
|
Column('node_id', Integer, primary_key=True),
|
|
Column('name_index', Integer, nullable=True),
|
|
)
|
|
node_name_table = Table("node_name", metadata,
|
|
Column('node_name_id', Integer, primary_key=True),
|
|
Column('node_id', Integer, ForeignKey('node.node_id')),
|
|
Column('host_id', Integer, ForeignKey('host.host_id')),
|
|
Column('name', String(64), nullable=False),
|
|
)
|
|
host_table = Table("host", metadata,
|
|
Column('host_id', Integer, primary_key=True),
|
|
Column('hostname', String(64), nullable=False,
|
|
unique=True),
|
|
)
|
|
metadata.create_all()
|
|
try:
|
|
node_table.insert().execute(node_id=1, node_index=5)
|
|
class Node(object):pass
|
|
class NodeName(object):pass
|
|
class Host(object):pass
|
|
|
|
node_mapper = mapper(Node, node_table)
|
|
host_mapper = mapper(Host, host_table)
|
|
node_name_mapper = mapper(NodeName, node_name_table,
|
|
properties = {
|
|
'node' : relationship(Node, backref=backref('names')),
|
|
'host' : relationship(Host),
|
|
}
|
|
)
|
|
sess = create_session()
|
|
assert sess.query(Node).get(1).names == []
|
|
finally:
|
|
metadata.drop_all()
|
|
|
|
def test_conflicting_backref_two(self):
|
|
meta = MetaData()
|
|
|
|
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
|
|
|
|
mapper(A, a, properties={
|
|
'b':relationship(B, backref='a')
|
|
})
|
|
mapper(B, b, properties={
|
|
'a':relationship(A, backref='b')
|
|
})
|
|
|
|
assert_raises_message(
|
|
sa_exc.ArgumentError,
|
|
"Error creating backref",
|
|
configure_mappers
|
|
)
|
|
|
|
def test_conflicting_backref_subclass(self):
|
|
meta = MetaData()
|
|
|
|
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(B):
|
|
pass
|
|
|
|
mapper(A, a, properties={
|
|
'b': relationship(B, backref='a'),
|
|
'c': relationship(C, backref='a')
|
|
})
|
|
mapper(B, b)
|
|
mapper(C, None, inherits=B)
|
|
|
|
assert_raises_message(
|
|
sa_exc.ArgumentError,
|
|
"Error creating backref",
|
|
configure_mappers
|
|
)
|