2
from test.lib.testing import eq_, assert_raises, assert_raises_message
2
from sqlalchemy.testing import eq_, assert_raises, assert_raises_message
3
3
from sqlalchemy import *
4
4
from sqlalchemy import exc as sa_exc, util, event
5
5
from sqlalchemy.orm import *
6
from sqlalchemy.orm.util import instance_str
6
7
from sqlalchemy.orm import exc as orm_exc, attributes
7
from test.lib.assertsql import AllOf, CompiledSQL
8
from sqlalchemy.testing.assertsql import AllOf, CompiledSQL
8
9
from sqlalchemy.sql import table, column
9
from test.lib import testing, engines
10
from test.lib import fixtures
10
from sqlalchemy import testing
11
from sqlalchemy.testing import engines
12
from sqlalchemy.testing import fixtures
11
13
from test.orm import _fixtures
12
from test.lib.schema import Table, Column
14
from sqlalchemy.testing.schema import Table, Column
15
from sqlalchemy import inspect
16
from sqlalchemy.ext.declarative import declarative_base
17
from sqlalchemy.testing.util import gc_collect
14
19
class O2MTest(fixtures.MappedTest):
15
20
"""deals with inheritance and one-to-many relationships"""
68
73
l = sess.query(Blub).all()
69
74
result = ','.join([repr(l[0]), repr(l[1]),
70
75
repr(l[0].parent_foo), repr(l[1].parent_foo)])
73
self.assert_(compare == result)
74
self.assert_(l[0].parent_foo.data == 'foo #1'
75
and l[1].parent_foo.data == 'foo #1')
77
eq_(l[0].parent_foo.data, 'foo #1')
78
eq_(l[1].parent_foo.data, 'foo #1')
80
class PolymorphicResolutionMultiLevel(fixtures.DeclarativeMappedTest,
81
testing.AssertsCompiledSQL):
82
run_setup_mappers = 'once'
83
__dialect__ = 'default'
86
def setup_classes(cls):
87
Base = cls.DeclarativeBasic
90
id = Column(Integer, primary_key=True)
93
id = Column(Integer, ForeignKey('a.id'), primary_key=True)
96
id = Column(Integer, ForeignKey('a.id'), primary_key=True)
99
id = Column(Integer, ForeignKey('b.id'), primary_key=True)
101
def test_ordered_b_d(self):
102
a_mapper = inspect(self.classes.A)
104
a_mapper._mappers_from_spec(
105
[self.classes.B, self.classes.D], None),
106
[a_mapper, inspect(self.classes.B), inspect(self.classes.D)]
110
a_mapper = inspect(self.classes.A)
112
a_mapper._mappers_from_spec(
113
[self.classes.A], None),
117
def test_b_d_selectable(self):
118
a_mapper = inspect(self.classes.A)
119
spec = [self.classes.D, self.classes.B]
121
a_mapper._mappers_from_spec(
123
self.classes.B.__table__.join(self.classes.D.__table__)
125
[inspect(self.classes.B), inspect(self.classes.D)]
128
def test_d_selectable(self):
129
a_mapper = inspect(self.classes.A)
130
spec = [self.classes.D]
132
a_mapper._mappers_from_spec(
134
self.classes.B.__table__.join(self.classes.D.__table__)
136
[inspect(self.classes.D)]
139
def test_reverse_d_b(self):
140
a_mapper = inspect(self.classes.A)
141
spec = [self.classes.D, self.classes.B]
143
a_mapper._mappers_from_spec(
145
[a_mapper, inspect(self.classes.B), inspect(self.classes.D)]
147
mappers, selectable = a_mapper._with_polymorphic_args(spec=spec)
148
self.assert_compile(selectable,
149
"a LEFT OUTER JOIN b ON a.id = b.id "
150
"LEFT OUTER JOIN d ON b.id = d.id")
152
def test_d_b_missing(self):
153
a_mapper = inspect(self.classes.A)
154
spec = [self.classes.D]
156
a_mapper._mappers_from_spec(
158
[a_mapper, inspect(self.classes.B), inspect(self.classes.D)]
160
mappers, selectable = a_mapper._with_polymorphic_args(spec=spec)
161
self.assert_compile(selectable,
162
"a LEFT OUTER JOIN b ON a.id = b.id "
163
"LEFT OUTER JOIN d ON b.id = d.id")
165
def test_d_c_b(self):
166
a_mapper = inspect(self.classes.A)
167
spec = [self.classes.D, self.classes.C, self.classes.B]
168
ms = a_mapper._mappers_from_spec(spec, None)
171
ms[-1], inspect(self.classes.D)
175
set(ms[1:3]), set(a_mapper._inheriting_mappers)
77
178
class PolymorphicOnNotLocalTest(fixtures.MappedTest):
429
class SortOnlyOnImportantFKsTest(fixtures.MappedTest):
431
def define_tables(cls, metadata):
433
Column('id', Integer, primary_key=True,
434
test_needs_autoincrement=True),
435
Column('b_id', Integer,
436
ForeignKey('b.id', use_alter=True, name='b'))
439
Column('id', Integer, ForeignKey('a.id'), primary_key=True)
443
def setup_classes(cls):
444
Base = declarative_base()
449
id = Column(Integer, primary_key=True,
450
test_needs_autoincrement=True)
451
b_id = Column(Integer, ForeignKey('b.id'))
456
id = Column(Integer, ForeignKey('a.id'), primary_key=True)
458
__mapper_args__ = {'inherit_condition': id == A.id}
463
def test_flush(self):
464
s = Session(testing.db)
465
s.add(self.classes.B())
329
468
class FalseDiscriminatorTest(fixtures.MappedTest):
414
555
Table('table_b', metadata,
415
556
Column('id', Integer, ForeignKey('table_a.id'),
416
557
primary_key=True),
417
Column('class_name', String(50))
558
Column('class_name', String(50)),
419
560
Table('table_c', metadata,
420
561
Column('id', Integer, ForeignKey('table_b.id'),
563
Column('data', String(10))
472
618
assert isinstance(sess.query(A).first(), C)
474
def test_assignment(self):
475
C, B = self.classes.C, self.classes.B
620
def test_valid_assignment_upwards(self):
621
"""test that we can assign 'd' to a B, since B/D
622
both involve the same set of tables.
624
D, B = self.classes.D, self.classes.B
632
assert isinstance(sess.query(B).first(), D)
634
def test_invalid_assignment_downwards(self):
635
"""test that we warn on assign of 'b' to a C, since this adds
636
a row to the C table we'd never load.
644
assert_raises_message(
646
"Flushing object %s with incompatible "
647
"polymorphic identity 'b'; the object may not "
648
"refresh and/or load correctly" % instance_str(c1),
652
def test_invalid_assignment_upwards(self):
653
"""test that we warn on assign of 'c' to a B, since we will have a
654
"C" row that has no joined row, which will cause object
479
661
b1.class_name = 'c'
483
assert isinstance(sess.query(B).first(), C)
663
assert_raises_message(
665
"Flushing object %s with incompatible "
666
"polymorphic identity 'c'; the object may not "
667
"refresh and/or load correctly" % instance_str(b1),
671
def test_entirely_oob_assignment(self):
672
"""test warn on an unknown polymorphic identity.
678
b1.class_name = 'xyz'
680
assert_raises_message(
682
"Flushing object %s with incompatible "
683
"polymorphic identity 'xyz'; the object may not "
684
"refresh and/or load correctly" % instance_str(b1),
688
def test_not_set_on_upate(self):
700
def test_validate_on_upate(self):
710
assert_raises_message(
712
"Flushing object %s with incompatible "
713
"polymorphic identity 'b'; the object may not "
714
"refresh and/or load correctly" % instance_str(c1),
485
718
class CascadeTest(fixtures.MappedTest):
486
719
"""that cascades on polymorphic relationships continue
916
1149
assert user_roles.count().scalar() == 1
1151
class JoinedNoFKSortingTest(fixtures.MappedTest):
1153
def define_tables(cls, metadata):
1154
Table("a", metadata,
1155
Column('id', Integer, primary_key=True,
1156
test_needs_autoincrement=True)
1158
Table("b", metadata,
1159
Column('id', Integer, primary_key=True)
1161
Table("c", metadata,
1162
Column('id', Integer, primary_key=True)
1166
def setup_classes(cls):
1175
def setup_mappers(cls):
1176
A, B, C = cls.classes.A, cls.classes.B, cls.classes.C
1177
mapper(A, cls.tables.a)
1178
mapper(B, cls.tables.b, inherits=A,
1179
inherit_condition=cls.tables.a.c.id == cls.tables.b.c.id)
1180
mapper(C, cls.tables.c, inherits=A,
1181
inherit_condition=cls.tables.a.c.id == cls.tables.c.c.id)
1183
def test_ordering(self):
1184
B, C = self.classes.B, self.classes.C
1186
sess.add_all([B(), C(), B(), C()])
1187
self.assert_sql_execution(
1191
"INSERT INTO a () VALUES ()",
1195
"INSERT INTO a () VALUES ()",
1199
"INSERT INTO a () VALUES ()",
1203
"INSERT INTO a () VALUES ()",
1208
"INSERT INTO b (id) VALUES (:id)",
1209
[{"id": 1}, {"id": 3}]
1212
"INSERT INTO c (id) VALUES (:id)",
1213
[{"id": 2}, {"id": 4}]
918
1218
class VersioningTest(fixtures.MappedTest):
920
1220
def define_tables(cls, metadata):
1430
1730
Column('b', String(10))
1733
def test_no_optimize_on_map_to_join(self):
1734
base, sub = self.tables.base, self.tables.sub
1736
class Base(fixtures.ComparableEntity):
1739
class JoinBase(fixtures.ComparableEntity):
1741
class SubJoinBase(JoinBase):
1745
mapper(JoinBase, base.outerjoin(sub), properties=util.OrderedDict(
1746
[('id', [base.c.id, sub.c.id]),
1747
('counter', [base.c.counter, sub.c.counter])])
1749
mapper(SubJoinBase, inherits=JoinBase)
1752
sess.add(Base(data='data'))
1755
sjb = sess.query(SubJoinBase).one()
1759
# this should not use the optimized load,
1760
# which assumes discrete tables
1762
eq_(sjb.data, 'data')
1764
self.assert_sql_execution(
1768
"SELECT base.id AS base_id, sub.id AS sub_id, "
1769
"base.counter AS base_counter, sub.counter AS sub_counter, "
1770
"base.data AS base_data, "
1771
"base.type AS base_type, sub.sub AS sub_sub, "
1772
"sub.counter2 AS sub_counter2 FROM base "
1773
"LEFT OUTER JOIN sub ON base.id = sub.id "
1774
"WHERE base.id = :param_1",
1433
1780
def test_optimized_passes(self):
1434
1781
""""test that the 'optimized load' routine doesn't crash when
1435
1782
a column in the join condition is not available."""
2010
class TransientInheritingGCTest(fixtures.TestBase):
2011
__requires__ = ('cpython',)
2014
Base = declarative_base()
2018
id = Column(Integer, primary_key=True,
2019
test_needs_autoincrement=True)
2020
data = Column(String(10))
2025
self.Base = self._fixture()
2028
self.Base.metadata.drop_all(testing.db)
2032
def _do_test(self, go):
2034
self.Base.metadata.create_all(testing.db)
2035
sess = Session(testing.db)
2036
sess.add(B(data='some b'))
2039
b1 = sess.query(B).one()
2040
assert isinstance(b1, B)
2049
len(self.A.__subclasses__()),
2052
def test_single(self):
2059
@testing.fails_if(lambda: True,
2060
"not supported for joined inh right now.")
2061
def test_joined(self):
2065
id = Column(Integer, ForeignKey('a.id'),
1663
2070
class NoPKOnSubTableWarningTest(fixtures.TestBase):
1665
2072
def _fixture(self):