mirror of
https://github.com/sqlalchemy/sqlalchemy.git
synced 2026-05-28 03:26:01 -04:00
772374735d
tested using pycodestyle version 2.2.0 Fixes: #3885 Change-Id: I5df43adc3aefe318f9eeab72a078247a548ec566 Pull-request: https://github.com/zzzeek/sqlalchemy/pull/343
1240 lines
45 KiB
Python
1240 lines
45 KiB
Python
from sqlalchemy.testing import assert_raises_message, eq_, \
|
|
AssertsCompiledSQL, is_
|
|
from sqlalchemy.testing import fixtures
|
|
from sqlalchemy.orm import relationships, foreign, remote
|
|
from sqlalchemy import MetaData, Table, Column, ForeignKey, Integer, \
|
|
select, ForeignKeyConstraint, exc, func, and_, String, Boolean
|
|
from sqlalchemy.orm.interfaces import ONETOMANY, MANYTOONE, MANYTOMANY
|
|
from sqlalchemy.testing import mock
|
|
|
|
|
|
class _JoinFixtures(object):
|
|
@classmethod
|
|
def setup_class(cls):
|
|
m = MetaData()
|
|
cls.left = Table('lft', m,
|
|
Column('id', Integer, primary_key=True),
|
|
Column('x', Integer),
|
|
Column('y', Integer))
|
|
cls.right = Table('rgt', m,
|
|
Column('id', Integer, primary_key=True),
|
|
Column('lid', Integer, ForeignKey('lft.id')),
|
|
Column('x', Integer),
|
|
Column('y', Integer))
|
|
cls.right_multi_fk = Table('rgt_multi_fk', m,
|
|
Column('id', Integer, primary_key=True),
|
|
Column('lid1', Integer,
|
|
ForeignKey('lft.id')),
|
|
Column('lid2', Integer,
|
|
ForeignKey('lft.id')))
|
|
|
|
cls.selfref = Table('selfref', m,
|
|
Column('id', Integer, primary_key=True),
|
|
Column('sid', Integer, ForeignKey('selfref.id')))
|
|
cls.composite_selfref = Table('composite_selfref', m,
|
|
Column('id', Integer, primary_key=True),
|
|
Column('group_id', Integer,
|
|
primary_key=True),
|
|
Column('parent_id', Integer),
|
|
ForeignKeyConstraint(
|
|
['parent_id', 'group_id'],
|
|
['composite_selfref.id',
|
|
'composite_selfref.group_id']))
|
|
cls.m2mleft = Table('m2mlft', m,
|
|
Column('id', Integer, primary_key=True))
|
|
cls.m2mright = Table('m2mrgt', m,
|
|
Column('id', Integer, primary_key=True))
|
|
cls.m2msecondary = Table('m2msecondary', m,
|
|
Column('lid', Integer, ForeignKey(
|
|
'm2mlft.id'), primary_key=True),
|
|
Column('rid', Integer, ForeignKey(
|
|
'm2mrgt.id'), primary_key=True))
|
|
cls.m2msecondary_no_fks = Table('m2msecondary_no_fks', m,
|
|
Column('lid', Integer,
|
|
primary_key=True),
|
|
Column('rid', Integer,
|
|
primary_key=True))
|
|
cls.m2msecondary_ambig_fks = Table('m2msecondary_ambig_fks', m,
|
|
Column('lid1', Integer, ForeignKey(
|
|
'm2mlft.id'), primary_key=True),
|
|
Column('rid1', Integer, ForeignKey(
|
|
'm2mrgt.id'), primary_key=True),
|
|
Column('lid2', Integer, ForeignKey(
|
|
'm2mlft.id'), primary_key=True),
|
|
Column('rid2', Integer, ForeignKey(
|
|
'm2mrgt.id'), primary_key=True))
|
|
cls.base_w_sub_rel = Table('base_w_sub_rel', m,
|
|
Column('id', Integer, primary_key=True),
|
|
Column('sub_id', Integer,
|
|
ForeignKey('rel_sub.id')))
|
|
cls.rel_sub = Table('rel_sub', m,
|
|
Column('id', Integer,
|
|
ForeignKey('base_w_sub_rel.id'),
|
|
primary_key=True))
|
|
cls.base = Table('base', m,
|
|
Column('id', Integer, primary_key=True),
|
|
Column('flag', Boolean))
|
|
cls.sub = Table('sub', m,
|
|
Column('id', Integer, ForeignKey('base.id'),
|
|
primary_key=True))
|
|
cls.sub_w_base_rel = Table('sub_w_base_rel', m,
|
|
Column('id', Integer, ForeignKey('base.id'),
|
|
primary_key=True),
|
|
Column('base_id', Integer,
|
|
ForeignKey('base.id')))
|
|
cls.sub_w_sub_rel = Table('sub_w_sub_rel', m,
|
|
Column('id', Integer, ForeignKey('base.id'),
|
|
primary_key=True),
|
|
Column('sub_id', Integer,
|
|
ForeignKey('sub.id'))
|
|
)
|
|
cls.right_w_base_rel = Table('right_w_base_rel', m,
|
|
Column('id', Integer, primary_key=True),
|
|
Column('base_id', Integer,
|
|
ForeignKey('base.id')))
|
|
|
|
cls.three_tab_a = Table('three_tab_a', m,
|
|
Column('id', Integer, primary_key=True))
|
|
cls.three_tab_b = Table('three_tab_b', m,
|
|
Column('id', Integer, primary_key=True),
|
|
Column('aid', Integer, ForeignKey(
|
|
'three_tab_a.id')))
|
|
cls.three_tab_c = Table('three_tab_c', m,
|
|
Column('id', Integer, primary_key=True),
|
|
Column('aid', Integer, ForeignKey(
|
|
'three_tab_a.id')),
|
|
Column('bid', Integer, ForeignKey(
|
|
'three_tab_b.id')))
|
|
|
|
cls.composite_target = Table('composite_target', m,
|
|
Column('uid', Integer, primary_key=True),
|
|
Column('oid', Integer, primary_key=True))
|
|
|
|
cls.composite_multi_ref = Table(
|
|
'composite_multi_ref', m,
|
|
Column('uid1', Integer),
|
|
Column('uid2', Integer),
|
|
Column('oid', Integer),
|
|
ForeignKeyConstraint(("uid1", "oid"),
|
|
("composite_target.uid",
|
|
"composite_target.oid")),
|
|
ForeignKeyConstraint(("uid2", "oid"),
|
|
("composite_target.uid",
|
|
"composite_target.oid")))
|
|
|
|
cls.purely_single_col = Table('purely_single_col', m,
|
|
Column('path', String))
|
|
|
|
def _join_fixture_overlapping_three_tables(self, **kw):
|
|
def _can_sync(*cols):
|
|
for c in cols:
|
|
if self.three_tab_c.c.contains_column(c):
|
|
return False
|
|
else:
|
|
return True
|
|
return relationships.JoinCondition(
|
|
self.three_tab_a,
|
|
self.three_tab_b,
|
|
self.three_tab_a,
|
|
self.three_tab_b,
|
|
support_sync=False,
|
|
can_be_synced_fn=_can_sync,
|
|
primaryjoin=and_(
|
|
self.three_tab_a.c.id == self.three_tab_b.c.aid,
|
|
self.three_tab_c.c.bid == self.three_tab_b.c.id,
|
|
self.three_tab_c.c.aid == self.three_tab_a.c.id
|
|
)
|
|
)
|
|
|
|
def _join_fixture_m2m(self, **kw):
|
|
return relationships.JoinCondition(
|
|
self.m2mleft,
|
|
self.m2mright,
|
|
self.m2mleft,
|
|
self.m2mright,
|
|
secondary=self.m2msecondary,
|
|
**kw
|
|
)
|
|
|
|
def _join_fixture_m2m_backref(self, **kw):
|
|
"""return JoinCondition in the same way RelationshipProperty
|
|
calls it for a backref on an m2m.
|
|
|
|
"""
|
|
j1 = self._join_fixture_m2m()
|
|
return j1, relationships.JoinCondition(
|
|
self.m2mright,
|
|
self.m2mleft,
|
|
self.m2mright,
|
|
self.m2mleft,
|
|
secondary=self.m2msecondary,
|
|
primaryjoin=j1.secondaryjoin_minus_local,
|
|
secondaryjoin=j1.primaryjoin_minus_local
|
|
)
|
|
|
|
def _join_fixture_o2m(self, **kw):
|
|
return relationships.JoinCondition(
|
|
self.left,
|
|
self.right,
|
|
self.left,
|
|
self.right,
|
|
**kw
|
|
)
|
|
|
|
def _join_fixture_m2o(self, **kw):
|
|
return relationships.JoinCondition(
|
|
self.right,
|
|
self.left,
|
|
self.right,
|
|
self.left,
|
|
**kw
|
|
)
|
|
|
|
def _join_fixture_o2m_selfref(self, **kw):
|
|
return relationships.JoinCondition(
|
|
self.selfref,
|
|
self.selfref,
|
|
self.selfref,
|
|
self.selfref,
|
|
**kw
|
|
)
|
|
|
|
def _join_fixture_m2o_selfref(self, **kw):
|
|
return relationships.JoinCondition(
|
|
self.selfref,
|
|
self.selfref,
|
|
self.selfref,
|
|
self.selfref,
|
|
remote_side=set([self.selfref.c.id]),
|
|
**kw
|
|
)
|
|
|
|
def _join_fixture_o2m_composite_selfref(self, **kw):
|
|
return relationships.JoinCondition(
|
|
self.composite_selfref,
|
|
self.composite_selfref,
|
|
self.composite_selfref,
|
|
self.composite_selfref,
|
|
**kw
|
|
)
|
|
|
|
def _join_fixture_m2o_composite_selfref(self, **kw):
|
|
return relationships.JoinCondition(
|
|
self.composite_selfref,
|
|
self.composite_selfref,
|
|
self.composite_selfref,
|
|
self.composite_selfref,
|
|
remote_side=set([self.composite_selfref.c.id,
|
|
self.composite_selfref.c.group_id]),
|
|
**kw
|
|
)
|
|
|
|
def _join_fixture_o2m_composite_selfref_func(self, **kw):
|
|
return relationships.JoinCondition(
|
|
self.composite_selfref,
|
|
self.composite_selfref,
|
|
self.composite_selfref,
|
|
self.composite_selfref,
|
|
primaryjoin=and_(
|
|
self.composite_selfref.c.group_id ==
|
|
func.foo(self.composite_selfref.c.group_id),
|
|
self.composite_selfref.c.parent_id ==
|
|
self.composite_selfref.c.id
|
|
),
|
|
**kw
|
|
)
|
|
|
|
def _join_fixture_o2m_composite_selfref_func_remote_side(self, **kw):
|
|
return relationships.JoinCondition(
|
|
self.composite_selfref,
|
|
self.composite_selfref,
|
|
self.composite_selfref,
|
|
self.composite_selfref,
|
|
primaryjoin=and_(
|
|
self.composite_selfref.c.group_id ==
|
|
func.foo(self.composite_selfref.c.group_id),
|
|
self.composite_selfref.c.parent_id ==
|
|
self.composite_selfref.c.id
|
|
),
|
|
remote_side=set([self.composite_selfref.c.parent_id]),
|
|
**kw
|
|
)
|
|
|
|
def _join_fixture_o2m_composite_selfref_func_annotated(self, **kw):
|
|
return relationships.JoinCondition(
|
|
self.composite_selfref,
|
|
self.composite_selfref,
|
|
self.composite_selfref,
|
|
self.composite_selfref,
|
|
primaryjoin=and_(
|
|
remote(self.composite_selfref.c.group_id) ==
|
|
func.foo(self.composite_selfref.c.group_id),
|
|
remote(self.composite_selfref.c.parent_id) ==
|
|
self.composite_selfref.c.id
|
|
),
|
|
**kw
|
|
)
|
|
|
|
def _join_fixture_compound_expression_1(self, **kw):
|
|
return relationships.JoinCondition(
|
|
self.left,
|
|
self.right,
|
|
self.left,
|
|
self.right,
|
|
primaryjoin=(self.left.c.x + self.left.c.y) ==
|
|
relationships.remote(relationships.foreign(
|
|
self.right.c.x * self.right.c.y
|
|
)),
|
|
**kw
|
|
)
|
|
|
|
def _join_fixture_compound_expression_2(self, **kw):
|
|
return relationships.JoinCondition(
|
|
self.left,
|
|
self.right,
|
|
self.left,
|
|
self.right,
|
|
primaryjoin=(self.left.c.x + self.left.c.y) ==
|
|
relationships.foreign(
|
|
self.right.c.x * self.right.c.y
|
|
),
|
|
**kw
|
|
)
|
|
|
|
def _join_fixture_compound_expression_1_non_annotated(self, **kw):
|
|
return relationships.JoinCondition(
|
|
self.left,
|
|
self.right,
|
|
self.left,
|
|
self.right,
|
|
primaryjoin=(self.left.c.x + self.left.c.y) ==
|
|
(
|
|
self.right.c.x * self.right.c.y
|
|
),
|
|
**kw
|
|
)
|
|
|
|
def _join_fixture_base_to_joined_sub(self, **kw):
|
|
# see test/orm/inheritance/test_abc_inheritance:TestaTobM2O
|
|
# and others there
|
|
right = self.base_w_sub_rel.join(
|
|
self.rel_sub,
|
|
self.base_w_sub_rel.c.id == self.rel_sub.c.id
|
|
)
|
|
return relationships.JoinCondition(
|
|
self.base_w_sub_rel,
|
|
right,
|
|
self.base_w_sub_rel,
|
|
self.rel_sub,
|
|
primaryjoin=self.base_w_sub_rel.c.sub_id ==
|
|
self.rel_sub.c.id,
|
|
**kw
|
|
)
|
|
|
|
def _join_fixture_o2m_joined_sub_to_base(self, **kw):
|
|
left = self.base.join(self.sub_w_base_rel,
|
|
self.base.c.id == self.sub_w_base_rel.c.id)
|
|
return relationships.JoinCondition(
|
|
left,
|
|
self.base,
|
|
self.sub_w_base_rel,
|
|
self.base,
|
|
primaryjoin=self.sub_w_base_rel.c.base_id == self.base.c.id
|
|
)
|
|
|
|
def _join_fixture_m2o_joined_sub_to_sub_on_base(self, **kw):
|
|
# this is a late add - a variant of the test case
|
|
# in #2491 where we join on the base cols instead. only
|
|
# m2o has a problem at the time of this test.
|
|
left = self.base.join(self.sub, self.base.c.id == self.sub.c.id)
|
|
right = self.base.join(self.sub_w_base_rel,
|
|
self.base.c.id == self.sub_w_base_rel.c.id)
|
|
return relationships.JoinCondition(
|
|
left,
|
|
right,
|
|
self.sub,
|
|
self.sub_w_base_rel,
|
|
primaryjoin=self.sub_w_base_rel.c.base_id == self.base.c.id,
|
|
)
|
|
|
|
def _join_fixture_o2m_joined_sub_to_sub(self, **kw):
|
|
left = self.base.join(self.sub, self.base.c.id == self.sub.c.id)
|
|
right = self.base.join(self.sub_w_sub_rel,
|
|
self.base.c.id == self.sub_w_sub_rel.c.id)
|
|
return relationships.JoinCondition(
|
|
left,
|
|
right,
|
|
self.sub,
|
|
self.sub_w_sub_rel,
|
|
primaryjoin=self.sub.c.id == self.sub_w_sub_rel.c.sub_id
|
|
)
|
|
|
|
def _join_fixture_m2o_sub_to_joined_sub(self, **kw):
|
|
# see test.orm.test_mapper:MapperTest.test_add_column_prop_deannotate,
|
|
right = self.base.join(self.right_w_base_rel,
|
|
self.base.c.id == self.right_w_base_rel.c.id)
|
|
return relationships.JoinCondition(
|
|
self.right_w_base_rel,
|
|
right,
|
|
self.right_w_base_rel,
|
|
self.right_w_base_rel,
|
|
)
|
|
|
|
def _join_fixture_m2o_sub_to_joined_sub_func(self, **kw):
|
|
# see test.orm.test_mapper:MapperTest.test_add_column_prop_deannotate,
|
|
right = self.base.join(self.right_w_base_rel,
|
|
self.base.c.id == self.right_w_base_rel.c.id)
|
|
return relationships.JoinCondition(
|
|
self.right_w_base_rel,
|
|
right,
|
|
self.right_w_base_rel,
|
|
self.right_w_base_rel,
|
|
primaryjoin=self.right_w_base_rel.c.base_id ==
|
|
func.foo(self.base.c.id)
|
|
)
|
|
|
|
def _join_fixture_o2o_joined_sub_to_base(self, **kw):
|
|
left = self.base.join(self.sub,
|
|
self.base.c.id == self.sub.c.id)
|
|
|
|
# see test_relationships->AmbiguousJoinInterpretedAsSelfRef
|
|
return relationships.JoinCondition(
|
|
left,
|
|
self.sub,
|
|
left,
|
|
self.sub,
|
|
)
|
|
|
|
def _join_fixture_o2m_to_annotated_func(self, **kw):
|
|
return relationships.JoinCondition(
|
|
self.left,
|
|
self.right,
|
|
self.left,
|
|
self.right,
|
|
primaryjoin=self.left.c.id ==
|
|
foreign(func.foo(self.right.c.lid)),
|
|
**kw
|
|
)
|
|
|
|
def _join_fixture_o2m_to_oldstyle_func(self, **kw):
|
|
return relationships.JoinCondition(
|
|
self.left,
|
|
self.right,
|
|
self.left,
|
|
self.right,
|
|
primaryjoin=self.left.c.id ==
|
|
func.foo(self.right.c.lid),
|
|
consider_as_foreign_keys=[self.right.c.lid],
|
|
**kw
|
|
)
|
|
|
|
def _join_fixture_overlapping_composite_fks(self, **kw):
|
|
return relationships.JoinCondition(
|
|
self.composite_target,
|
|
self.composite_multi_ref,
|
|
self.composite_target,
|
|
self.composite_multi_ref,
|
|
consider_as_foreign_keys=[self.composite_multi_ref.c.uid2,
|
|
self.composite_multi_ref.c.oid],
|
|
**kw
|
|
)
|
|
|
|
cls.left = Table('lft', m,
|
|
Column('id', Integer, primary_key=True),
|
|
Column('x', Integer),
|
|
Column('y', Integer))
|
|
cls.right = Table('rgt', m,
|
|
Column('id', Integer, primary_key=True),
|
|
Column('lid', Integer, ForeignKey('lft.id')),
|
|
Column('x', Integer),
|
|
Column('y', Integer))
|
|
|
|
def _join_fixture_o2m_o_side_none(self, **kw):
|
|
return relationships.JoinCondition(
|
|
self.left,
|
|
self.right,
|
|
self.left,
|
|
self.right,
|
|
primaryjoin=and_(self.left.c.id == self.right.c.lid,
|
|
self.left.c.x == 5),
|
|
**kw
|
|
)
|
|
|
|
def _join_fixture_purely_single_o2m(self, **kw):
|
|
return relationships.JoinCondition(
|
|
self.purely_single_col,
|
|
self.purely_single_col,
|
|
self.purely_single_col,
|
|
self.purely_single_col,
|
|
support_sync=False,
|
|
primaryjoin=self.purely_single_col.c.path.like(
|
|
remote(
|
|
foreign(
|
|
self.purely_single_col.c.path.concat('%')
|
|
)
|
|
)
|
|
)
|
|
)
|
|
|
|
def _join_fixture_purely_single_m2o(self, **kw):
|
|
return relationships.JoinCondition(
|
|
self.purely_single_col,
|
|
self.purely_single_col,
|
|
self.purely_single_col,
|
|
self.purely_single_col,
|
|
support_sync=False,
|
|
primaryjoin=remote(self.purely_single_col.c.path).like(
|
|
foreign(self.purely_single_col.c.path.concat('%'))
|
|
)
|
|
)
|
|
|
|
def _join_fixture_remote_local_multiple_ref(self, **kw):
|
|
def fn(a, b): return ((a == b) | (b == a))
|
|
return relationships.JoinCondition(
|
|
self.selfref, self.selfref,
|
|
self.selfref, self.selfref,
|
|
support_sync=False,
|
|
primaryjoin=fn(
|
|
# we're putting a do-nothing annotation on
|
|
# "a" so that the left/right is preserved;
|
|
# annotation vs. non seems to affect __eq__ behavior
|
|
self.selfref.c.sid._annotate({"foo": "bar"}),
|
|
foreign(remote(self.selfref.c.sid)))
|
|
)
|
|
|
|
def _join_fixture_inh_selfref_w_entity(self, **kw):
|
|
fake_logger = mock.Mock(info=lambda *arg, **kw: None)
|
|
prop = mock.Mock(
|
|
parent=mock.Mock(),
|
|
mapper=mock.Mock(),
|
|
logger=fake_logger
|
|
)
|
|
local_selectable = self.base.join(self.sub)
|
|
remote_selectable = self.base.join(self.sub_w_sub_rel)
|
|
|
|
sub_w_sub_rel__sub_id = self.sub_w_sub_rel.c.sub_id._annotate(
|
|
{'parentmapper': prop.mapper})
|
|
sub__id = self.sub.c.id._annotate({'parentmapper': prop.parent})
|
|
sub_w_sub_rel__flag = self.base.c.flag._annotate(
|
|
{"parentmapper": prop.mapper})
|
|
return relationships.JoinCondition(
|
|
local_selectable, remote_selectable,
|
|
local_selectable, remote_selectable,
|
|
primaryjoin=and_(
|
|
sub_w_sub_rel__sub_id == sub__id,
|
|
sub_w_sub_rel__flag == True # noqa
|
|
),
|
|
prop=prop
|
|
)
|
|
|
|
def _assert_non_simple_warning(self, fn):
|
|
assert_raises_message(
|
|
exc.SAWarning,
|
|
"Non-simple column elements in "
|
|
"primary join condition for property "
|
|
r"None - consider using remote\(\) "
|
|
"annotations to mark the remote side.",
|
|
fn
|
|
)
|
|
|
|
def _assert_raises_no_relevant_fks(self, fn, expr, relname,
|
|
primary, *arg, **kw):
|
|
assert_raises_message(
|
|
exc.ArgumentError,
|
|
r"Could not locate any relevant foreign key columns "
|
|
r"for %s join condition '%s' on relationship %s. "
|
|
r"Ensure that referencing columns are associated with "
|
|
r"a ForeignKey or ForeignKeyConstraint, or are annotated "
|
|
r"in the join condition with the foreign\(\) annotation."
|
|
% (
|
|
primary, expr, relname
|
|
),
|
|
fn, *arg, **kw
|
|
)
|
|
|
|
def _assert_raises_no_equality(self, fn, expr, relname,
|
|
primary, *arg, **kw):
|
|
assert_raises_message(
|
|
exc.ArgumentError,
|
|
"Could not locate any simple equality expressions "
|
|
"involving locally mapped foreign key columns for %s join "
|
|
"condition '%s' on relationship %s. "
|
|
"Ensure that referencing columns are associated with a "
|
|
"ForeignKey or ForeignKeyConstraint, or are annotated in "
|
|
r"the join condition with the foreign\(\) annotation. "
|
|
"To allow comparison operators other than '==', "
|
|
"the relationship can be marked as viewonly=True." % (
|
|
primary, expr, relname
|
|
),
|
|
fn, *arg, **kw
|
|
)
|
|
|
|
def _assert_raises_ambig_join(self, fn, relname, secondary_arg,
|
|
*arg, **kw):
|
|
if secondary_arg is not None:
|
|
assert_raises_message(
|
|
exc.AmbiguousForeignKeysError,
|
|
"Could not determine join condition between "
|
|
"parent/child tables on relationship %s - "
|
|
"there are multiple foreign key paths linking the "
|
|
"tables via secondary table '%s'. "
|
|
"Specify the 'foreign_keys' argument, providing a list "
|
|
"of those columns which should be counted as "
|
|
"containing a foreign key reference from the "
|
|
"secondary table to each of the parent and child tables."
|
|
% (relname, secondary_arg),
|
|
fn, *arg, **kw)
|
|
else:
|
|
assert_raises_message(
|
|
exc.AmbiguousForeignKeysError,
|
|
"Could not determine join condition between "
|
|
"parent/child tables on relationship %s - "
|
|
"there are no foreign keys linking these tables. "
|
|
% (relname,),
|
|
fn, *arg, **kw)
|
|
|
|
def _assert_raises_no_join(self, fn, relname, secondary_arg,
|
|
*arg, **kw):
|
|
if secondary_arg is not None:
|
|
assert_raises_message(
|
|
exc.NoForeignKeysError,
|
|
"Could not determine join condition between "
|
|
"parent/child tables on relationship %s - "
|
|
"there are no foreign keys linking these tables "
|
|
"via secondary table '%s'. "
|
|
"Ensure that referencing columns are associated "
|
|
"with a ForeignKey "
|
|
"or ForeignKeyConstraint, or specify 'primaryjoin' and "
|
|
"'secondaryjoin' expressions"
|
|
% (relname, secondary_arg),
|
|
fn, *arg, **kw)
|
|
else:
|
|
assert_raises_message(
|
|
exc.NoForeignKeysError,
|
|
"Could not determine join condition between "
|
|
"parent/child tables on relationship %s - "
|
|
"there are no foreign keys linking these tables. "
|
|
"Ensure that referencing columns are associated "
|
|
"with a ForeignKey "
|
|
"or ForeignKeyConstraint, or specify a 'primaryjoin' "
|
|
"expression."
|
|
% (relname,),
|
|
fn, *arg, **kw)
|
|
|
|
|
|
class ColumnCollectionsTest(_JoinFixtures, fixtures.TestBase,
|
|
AssertsCompiledSQL):
|
|
def test_determine_local_remote_pairs_o2o_joined_sub_to_base(self):
|
|
joincond = self._join_fixture_o2o_joined_sub_to_base()
|
|
eq_(
|
|
joincond.local_remote_pairs,
|
|
[(self.base.c.id, self.sub.c.id)]
|
|
)
|
|
|
|
def test_determine_synchronize_pairs_o2m_to_annotated_func(self):
|
|
joincond = self._join_fixture_o2m_to_annotated_func()
|
|
eq_(
|
|
joincond.synchronize_pairs,
|
|
[(self.left.c.id, self.right.c.lid)]
|
|
)
|
|
|
|
def test_determine_synchronize_pairs_o2m_to_oldstyle_func(self):
|
|
joincond = self._join_fixture_o2m_to_oldstyle_func()
|
|
eq_(
|
|
joincond.synchronize_pairs,
|
|
[(self.left.c.id, self.right.c.lid)]
|
|
)
|
|
|
|
def test_determinelocal_remote_m2o_joined_sub_to_sub_on_base(self):
|
|
joincond = self._join_fixture_m2o_joined_sub_to_sub_on_base()
|
|
eq_(
|
|
joincond.local_remote_pairs,
|
|
[(self.base.c.id, self.sub_w_base_rel.c.base_id)]
|
|
)
|
|
|
|
def test_determine_local_remote_base_to_joined_sub(self):
|
|
joincond = self._join_fixture_base_to_joined_sub()
|
|
eq_(
|
|
joincond.local_remote_pairs,
|
|
[
|
|
(self.base_w_sub_rel.c.sub_id, self.rel_sub.c.id)
|
|
]
|
|
)
|
|
|
|
def test_determine_local_remote_o2m_joined_sub_to_base(self):
|
|
joincond = self._join_fixture_o2m_joined_sub_to_base()
|
|
eq_(
|
|
joincond.local_remote_pairs,
|
|
[
|
|
(self.sub_w_base_rel.c.base_id, self.base.c.id)
|
|
]
|
|
)
|
|
|
|
def test_determine_local_remote_m2o_sub_to_joined_sub(self):
|
|
joincond = self._join_fixture_m2o_sub_to_joined_sub()
|
|
eq_(
|
|
joincond.local_remote_pairs,
|
|
[
|
|
(self.right_w_base_rel.c.base_id, self.base.c.id)
|
|
]
|
|
)
|
|
|
|
def test_determine_remote_columns_o2m_joined_sub_to_sub(self):
|
|
joincond = self._join_fixture_o2m_joined_sub_to_sub()
|
|
eq_(
|
|
joincond.local_remote_pairs,
|
|
[
|
|
(self.sub.c.id, self.sub_w_sub_rel.c.sub_id)
|
|
]
|
|
)
|
|
|
|
def test_determine_remote_columns_compound_1(self):
|
|
joincond = self._join_fixture_compound_expression_1(
|
|
support_sync=False)
|
|
eq_(
|
|
joincond.remote_columns,
|
|
set([self.right.c.x, self.right.c.y])
|
|
)
|
|
|
|
def test_determine_local_remote_compound_1(self):
|
|
joincond = self._join_fixture_compound_expression_1(
|
|
support_sync=False)
|
|
eq_(
|
|
joincond.local_remote_pairs,
|
|
[
|
|
(self.left.c.x, self.right.c.x),
|
|
(self.left.c.x, self.right.c.y),
|
|
(self.left.c.y, self.right.c.x),
|
|
(self.left.c.y, self.right.c.y)
|
|
]
|
|
)
|
|
|
|
def test_determine_local_remote_compound_2(self):
|
|
joincond = self._join_fixture_compound_expression_2(
|
|
support_sync=False)
|
|
eq_(
|
|
joincond.local_remote_pairs,
|
|
[
|
|
(self.left.c.x, self.right.c.x),
|
|
(self.left.c.x, self.right.c.y),
|
|
(self.left.c.y, self.right.c.x),
|
|
(self.left.c.y, self.right.c.y)
|
|
]
|
|
)
|
|
|
|
def test_determine_local_remote_compound_3(self):
|
|
joincond = self._join_fixture_compound_expression_1()
|
|
eq_(
|
|
joincond.local_remote_pairs,
|
|
[
|
|
(self.left.c.x, self.right.c.x),
|
|
(self.left.c.x, self.right.c.y),
|
|
(self.left.c.y, self.right.c.x),
|
|
(self.left.c.y, self.right.c.y),
|
|
]
|
|
)
|
|
|
|
def test_err_local_remote_compound_1(self):
|
|
self._assert_raises_no_relevant_fks(
|
|
self._join_fixture_compound_expression_1_non_annotated,
|
|
r'lft.x \+ lft.y = rgt.x \* rgt.y',
|
|
"None", "primary"
|
|
)
|
|
|
|
def test_determine_remote_columns_compound_2(self):
|
|
joincond = self._join_fixture_compound_expression_2(
|
|
support_sync=False)
|
|
eq_(
|
|
joincond.remote_columns,
|
|
set([self.right.c.x, self.right.c.y])
|
|
)
|
|
|
|
def test_determine_remote_columns_o2m(self):
|
|
joincond = self._join_fixture_o2m()
|
|
eq_(
|
|
joincond.remote_columns,
|
|
set([self.right.c.lid])
|
|
)
|
|
|
|
def test_determine_remote_columns_o2m_selfref(self):
|
|
joincond = self._join_fixture_o2m_selfref()
|
|
eq_(
|
|
joincond.remote_columns,
|
|
set([self.selfref.c.sid])
|
|
)
|
|
|
|
def test_determine_local_remote_pairs_o2m_composite_selfref(self):
|
|
joincond = self._join_fixture_o2m_composite_selfref()
|
|
eq_(
|
|
joincond.local_remote_pairs,
|
|
[
|
|
(self.composite_selfref.c.group_id,
|
|
self.composite_selfref.c.group_id),
|
|
(self.composite_selfref.c.id,
|
|
self.composite_selfref.c.parent_id),
|
|
]
|
|
)
|
|
|
|
def test_determine_local_remote_pairs_o2m_composite_selfref_func_warning(
|
|
self):
|
|
self._assert_non_simple_warning(
|
|
self._join_fixture_o2m_composite_selfref_func
|
|
)
|
|
|
|
def test_determine_local_remote_pairs_o2m_composite_selfref_func_rs(self):
|
|
# no warning
|
|
self._join_fixture_o2m_composite_selfref_func_remote_side()
|
|
|
|
def test_determine_local_remote_pairs_o2m_overlap_func_warning(self):
|
|
self._assert_non_simple_warning(
|
|
self._join_fixture_m2o_sub_to_joined_sub_func
|
|
)
|
|
|
|
def test_determine_local_remote_pairs_o2m_composite_selfref_func_annotated(
|
|
self):
|
|
joincond = self._join_fixture_o2m_composite_selfref_func_annotated()
|
|
eq_(
|
|
joincond.local_remote_pairs,
|
|
[
|
|
(self.composite_selfref.c.group_id,
|
|
self.composite_selfref.c.group_id),
|
|
(self.composite_selfref.c.id,
|
|
self.composite_selfref.c.parent_id),
|
|
]
|
|
)
|
|
|
|
def test_determine_remote_columns_m2o_composite_selfref(self):
|
|
joincond = self._join_fixture_m2o_composite_selfref()
|
|
eq_(
|
|
joincond.remote_columns,
|
|
set([self.composite_selfref.c.id,
|
|
self.composite_selfref.c.group_id])
|
|
)
|
|
|
|
def test_determine_remote_columns_m2o(self):
|
|
joincond = self._join_fixture_m2o()
|
|
eq_(
|
|
joincond.remote_columns,
|
|
set([self.left.c.id])
|
|
)
|
|
|
|
def test_determine_local_remote_pairs_o2m(self):
|
|
joincond = self._join_fixture_o2m()
|
|
eq_(
|
|
joincond.local_remote_pairs,
|
|
[(self.left.c.id, self.right.c.lid)]
|
|
)
|
|
|
|
def test_determine_synchronize_pairs_m2m(self):
|
|
joincond = self._join_fixture_m2m()
|
|
eq_(
|
|
joincond.synchronize_pairs,
|
|
[(self.m2mleft.c.id, self.m2msecondary.c.lid)]
|
|
)
|
|
eq_(
|
|
joincond.secondary_synchronize_pairs,
|
|
[(self.m2mright.c.id, self.m2msecondary.c.rid)]
|
|
)
|
|
|
|
def test_determine_local_remote_pairs_o2m_backref(self):
|
|
joincond = self._join_fixture_o2m()
|
|
joincond2 = self._join_fixture_m2o(
|
|
primaryjoin=joincond.primaryjoin_reverse_remote,
|
|
)
|
|
eq_(
|
|
joincond2.local_remote_pairs,
|
|
[(self.right.c.lid, self.left.c.id)]
|
|
)
|
|
|
|
def test_determine_local_remote_pairs_m2m(self):
|
|
joincond = self._join_fixture_m2m()
|
|
eq_(
|
|
joincond.local_remote_pairs,
|
|
[(self.m2mleft.c.id, self.m2msecondary.c.lid),
|
|
(self.m2mright.c.id, self.m2msecondary.c.rid)]
|
|
)
|
|
|
|
def test_determine_local_remote_pairs_m2m_backref(self):
|
|
j1, j2 = self._join_fixture_m2m_backref()
|
|
eq_(
|
|
j1.local_remote_pairs,
|
|
[(self.m2mleft.c.id, self.m2msecondary.c.lid),
|
|
(self.m2mright.c.id, self.m2msecondary.c.rid)]
|
|
)
|
|
eq_(
|
|
j2.local_remote_pairs,
|
|
[
|
|
(self.m2mright.c.id, self.m2msecondary.c.rid),
|
|
(self.m2mleft.c.id, self.m2msecondary.c.lid),
|
|
]
|
|
)
|
|
|
|
def test_determine_local_columns_m2m_backref(self):
|
|
j1, j2 = self._join_fixture_m2m_backref()
|
|
eq_(
|
|
j1.local_columns,
|
|
set([self.m2mleft.c.id])
|
|
)
|
|
eq_(
|
|
j2.local_columns,
|
|
set([self.m2mright.c.id])
|
|
)
|
|
|
|
def test_determine_remote_columns_m2m_backref(self):
|
|
j1, j2 = self._join_fixture_m2m_backref()
|
|
eq_(
|
|
j1.remote_columns,
|
|
set([self.m2msecondary.c.lid, self.m2msecondary.c.rid])
|
|
)
|
|
eq_(
|
|
j2.remote_columns,
|
|
set([self.m2msecondary.c.lid, self.m2msecondary.c.rid])
|
|
)
|
|
|
|
def test_determine_remote_columns_m2o_selfref(self):
|
|
joincond = self._join_fixture_m2o_selfref()
|
|
eq_(
|
|
joincond.remote_columns,
|
|
set([self.selfref.c.id])
|
|
)
|
|
|
|
def test_determine_local_remote_cols_three_tab_viewonly(self):
|
|
joincond = self._join_fixture_overlapping_three_tables()
|
|
eq_(
|
|
joincond.local_remote_pairs,
|
|
[(self.three_tab_a.c.id, self.three_tab_b.c.aid)]
|
|
)
|
|
eq_(
|
|
joincond.remote_columns,
|
|
set([self.three_tab_b.c.id, self.three_tab_b.c.aid])
|
|
)
|
|
|
|
def test_determine_local_remote_overlapping_composite_fks(self):
|
|
joincond = self._join_fixture_overlapping_composite_fks()
|
|
|
|
eq_(
|
|
joincond.local_remote_pairs,
|
|
[
|
|
(self.composite_target.c.uid,
|
|
self.composite_multi_ref.c.uid2,),
|
|
(self.composite_target.c.oid, self.composite_multi_ref.c.oid,)
|
|
]
|
|
)
|
|
|
|
def test_determine_local_remote_pairs_purely_single_col_o2m(self):
|
|
joincond = self._join_fixture_purely_single_o2m()
|
|
eq_(
|
|
joincond.local_remote_pairs,
|
|
[(self.purely_single_col.c.path, self.purely_single_col.c.path)]
|
|
)
|
|
|
|
def test_determine_local_remote_pairs_inh_selfref_w_entities(self):
|
|
joincond = self._join_fixture_inh_selfref_w_entity()
|
|
eq_(
|
|
joincond.local_remote_pairs,
|
|
[(self.sub.c.id, self.sub_w_sub_rel.c.sub_id)]
|
|
)
|
|
eq_(
|
|
joincond.remote_columns,
|
|
set([self.base.c.flag, self.sub_w_sub_rel.c.sub_id])
|
|
)
|
|
|
|
|
|
class DirectionTest(_JoinFixtures, fixtures.TestBase, AssertsCompiledSQL):
|
|
def test_determine_direction_compound_2(self):
|
|
joincond = self._join_fixture_compound_expression_2(
|
|
support_sync=False)
|
|
is_(
|
|
joincond.direction,
|
|
ONETOMANY
|
|
)
|
|
|
|
def test_determine_direction_o2m(self):
|
|
joincond = self._join_fixture_o2m()
|
|
is_(joincond.direction, ONETOMANY)
|
|
|
|
def test_determine_direction_o2m_selfref(self):
|
|
joincond = self._join_fixture_o2m_selfref()
|
|
is_(joincond.direction, ONETOMANY)
|
|
|
|
def test_determine_direction_m2o_selfref(self):
|
|
joincond = self._join_fixture_m2o_selfref()
|
|
is_(joincond.direction, MANYTOONE)
|
|
|
|
def test_determine_direction_o2m_composite_selfref(self):
|
|
joincond = self._join_fixture_o2m_composite_selfref()
|
|
is_(joincond.direction, ONETOMANY)
|
|
|
|
def test_determine_direction_m2o_composite_selfref(self):
|
|
joincond = self._join_fixture_m2o_composite_selfref()
|
|
is_(joincond.direction, MANYTOONE)
|
|
|
|
def test_determine_direction_m2o(self):
|
|
joincond = self._join_fixture_m2o()
|
|
is_(joincond.direction, MANYTOONE)
|
|
|
|
def test_determine_direction_purely_single_o2m(self):
|
|
joincond = self._join_fixture_purely_single_o2m()
|
|
is_(joincond.direction, ONETOMANY)
|
|
|
|
def test_determine_direction_purely_single_m2o(self):
|
|
joincond = self._join_fixture_purely_single_m2o()
|
|
is_(joincond.direction, MANYTOONE)
|
|
|
|
|
|
class DetermineJoinTest(_JoinFixtures, fixtures.TestBase, AssertsCompiledSQL):
|
|
__dialect__ = 'default'
|
|
|
|
def test_determine_join_o2m(self):
|
|
joincond = self._join_fixture_o2m()
|
|
self.assert_compile(
|
|
joincond.primaryjoin,
|
|
"lft.id = rgt.lid"
|
|
)
|
|
|
|
def test_determine_join_o2m_selfref(self):
|
|
joincond = self._join_fixture_o2m_selfref()
|
|
self.assert_compile(
|
|
joincond.primaryjoin,
|
|
"selfref.id = selfref.sid"
|
|
)
|
|
|
|
def test_determine_join_m2o_selfref(self):
|
|
joincond = self._join_fixture_m2o_selfref()
|
|
self.assert_compile(
|
|
joincond.primaryjoin,
|
|
"selfref.id = selfref.sid"
|
|
)
|
|
|
|
def test_determine_join_o2m_composite_selfref(self):
|
|
joincond = self._join_fixture_o2m_composite_selfref()
|
|
self.assert_compile(
|
|
joincond.primaryjoin,
|
|
"composite_selfref.group_id = composite_selfref.group_id "
|
|
"AND composite_selfref.id = composite_selfref.parent_id"
|
|
)
|
|
|
|
def test_determine_join_m2o_composite_selfref(self):
|
|
joincond = self._join_fixture_m2o_composite_selfref()
|
|
self.assert_compile(
|
|
joincond.primaryjoin,
|
|
"composite_selfref.group_id = composite_selfref.group_id "
|
|
"AND composite_selfref.id = composite_selfref.parent_id"
|
|
)
|
|
|
|
def test_determine_join_m2o(self):
|
|
joincond = self._join_fixture_m2o()
|
|
self.assert_compile(
|
|
joincond.primaryjoin,
|
|
"lft.id = rgt.lid"
|
|
)
|
|
|
|
def test_determine_join_ambiguous_fks_o2m(self):
|
|
assert_raises_message(
|
|
exc.AmbiguousForeignKeysError,
|
|
"Could not determine join condition between "
|
|
"parent/child tables on relationship None - "
|
|
"there are multiple foreign key paths linking "
|
|
"the tables. Specify the 'foreign_keys' argument, "
|
|
"providing a list of those columns which "
|
|
"should be counted as containing a foreign "
|
|
"key reference to the parent table.",
|
|
relationships.JoinCondition,
|
|
self.left,
|
|
self.right_multi_fk,
|
|
self.left,
|
|
self.right_multi_fk,
|
|
)
|
|
|
|
def test_determine_join_no_fks_o2m(self):
|
|
self._assert_raises_no_join(
|
|
relationships.JoinCondition,
|
|
"None", None,
|
|
self.left,
|
|
self.selfref,
|
|
self.left,
|
|
self.selfref,
|
|
)
|
|
|
|
def test_determine_join_ambiguous_fks_m2m(self):
|
|
|
|
self._assert_raises_ambig_join(
|
|
relationships.JoinCondition,
|
|
"None", self.m2msecondary_ambig_fks,
|
|
self.m2mleft,
|
|
self.m2mright,
|
|
self.m2mleft,
|
|
self.m2mright,
|
|
secondary=self.m2msecondary_ambig_fks
|
|
)
|
|
|
|
def test_determine_join_no_fks_m2m(self):
|
|
self._assert_raises_no_join(
|
|
relationships.JoinCondition,
|
|
"None", self.m2msecondary_no_fks,
|
|
self.m2mleft,
|
|
self.m2mright,
|
|
self.m2mleft,
|
|
self.m2mright,
|
|
secondary=self.m2msecondary_no_fks
|
|
)
|
|
|
|
def _join_fixture_fks_ambig_m2m(self):
|
|
return relationships.JoinCondition(
|
|
self.m2mleft,
|
|
self.m2mright,
|
|
self.m2mleft,
|
|
self.m2mright,
|
|
secondary=self.m2msecondary_ambig_fks,
|
|
consider_as_foreign_keys=[
|
|
self.m2msecondary_ambig_fks.c.lid1,
|
|
self.m2msecondary_ambig_fks.c.rid1]
|
|
)
|
|
|
|
def test_determine_join_w_fks_ambig_m2m(self):
|
|
joincond = self._join_fixture_fks_ambig_m2m()
|
|
self.assert_compile(
|
|
joincond.primaryjoin,
|
|
"m2mlft.id = m2msecondary_ambig_fks.lid1"
|
|
)
|
|
self.assert_compile(
|
|
joincond.secondaryjoin,
|
|
"m2mrgt.id = m2msecondary_ambig_fks.rid1"
|
|
)
|
|
|
|
|
|
class AdaptedJoinTest(_JoinFixtures, fixtures.TestBase, AssertsCompiledSQL):
|
|
__dialect__ = 'default'
|
|
|
|
def test_join_targets_o2m_selfref(self):
|
|
joincond = self._join_fixture_o2m_selfref()
|
|
left = select([joincond.parent_selectable]).alias('pj')
|
|
pj, sj, sec, adapter, ds = joincond.join_targets(
|
|
left,
|
|
joincond.child_selectable,
|
|
True)
|
|
self.assert_compile(
|
|
pj, "pj.id = selfref.sid"
|
|
)
|
|
|
|
right = select([joincond.child_selectable]).alias('pj')
|
|
pj, sj, sec, adapter, ds = joincond.join_targets(
|
|
joincond.parent_selectable,
|
|
right,
|
|
True)
|
|
self.assert_compile(
|
|
pj, "selfref.id = pj.sid"
|
|
)
|
|
|
|
def test_join_targets_o2m_plain(self):
|
|
joincond = self._join_fixture_o2m()
|
|
pj, sj, sec, adapter, ds = joincond.join_targets(
|
|
joincond.parent_selectable,
|
|
joincond.child_selectable,
|
|
False)
|
|
self.assert_compile(
|
|
pj, "lft.id = rgt.lid"
|
|
)
|
|
|
|
def test_join_targets_o2m_left_aliased(self):
|
|
joincond = self._join_fixture_o2m()
|
|
left = select([joincond.parent_selectable]).alias('pj')
|
|
pj, sj, sec, adapter, ds = joincond.join_targets(
|
|
left,
|
|
joincond.child_selectable,
|
|
True)
|
|
self.assert_compile(
|
|
pj, "pj.id = rgt.lid"
|
|
)
|
|
|
|
def test_join_targets_o2m_right_aliased(self):
|
|
joincond = self._join_fixture_o2m()
|
|
right = select([joincond.child_selectable]).alias('pj')
|
|
pj, sj, sec, adapter, ds = joincond.join_targets(
|
|
joincond.parent_selectable,
|
|
right,
|
|
True)
|
|
self.assert_compile(
|
|
pj, "lft.id = pj.lid"
|
|
)
|
|
|
|
def test_join_targets_o2m_composite_selfref(self):
|
|
joincond = self._join_fixture_o2m_composite_selfref()
|
|
right = select([joincond.child_selectable]).alias('pj')
|
|
pj, sj, sec, adapter, ds = joincond.join_targets(
|
|
joincond.parent_selectable,
|
|
right,
|
|
True)
|
|
self.assert_compile(
|
|
pj,
|
|
"pj.group_id = composite_selfref.group_id "
|
|
"AND composite_selfref.id = pj.parent_id"
|
|
)
|
|
|
|
def test_join_targets_m2o_composite_selfref(self):
|
|
joincond = self._join_fixture_m2o_composite_selfref()
|
|
right = select([joincond.child_selectable]).alias('pj')
|
|
pj, sj, sec, adapter, ds = joincond.join_targets(
|
|
joincond.parent_selectable,
|
|
right,
|
|
True)
|
|
self.assert_compile(
|
|
pj,
|
|
"pj.group_id = composite_selfref.group_id "
|
|
"AND pj.id = composite_selfref.parent_id"
|
|
)
|
|
|
|
|
|
class LazyClauseTest(_JoinFixtures, fixtures.TestBase, AssertsCompiledSQL):
|
|
__dialect__ = 'default'
|
|
|
|
def test_lazy_clause_o2m(self):
|
|
joincond = self._join_fixture_o2m()
|
|
lazywhere, bind_to_col, equated_columns = joincond.create_lazy_clause()
|
|
self.assert_compile(
|
|
lazywhere,
|
|
":param_1 = rgt.lid"
|
|
)
|
|
|
|
def test_lazy_clause_o2m_reverse(self):
|
|
joincond = self._join_fixture_o2m()
|
|
lazywhere, bind_to_col, equated_columns =\
|
|
joincond.create_lazy_clause(reverse_direction=True)
|
|
self.assert_compile(
|
|
lazywhere,
|
|
"lft.id = :param_1"
|
|
)
|
|
|
|
def test_lazy_clause_o2m_o_side_none(self):
|
|
# test for #2948. When the join is "o.id == m.oid
|
|
# AND o.something == something",
|
|
# we don't want 'o' brought into the lazy load for 'm'
|
|
joincond = self._join_fixture_o2m_o_side_none()
|
|
lazywhere, bind_to_col, equated_columns = joincond.create_lazy_clause()
|
|
self.assert_compile(
|
|
lazywhere,
|
|
":param_1 = rgt.lid AND :param_2 = :x_1",
|
|
checkparams={'param_1': None, 'param_2': None, 'x_1': 5}
|
|
)
|
|
|
|
def test_lazy_clause_o2m_o_side_none_reverse(self):
|
|
# continued test for #2948.
|
|
joincond = self._join_fixture_o2m_o_side_none()
|
|
lazywhere, bind_to_col, equated_columns = joincond.create_lazy_clause(
|
|
reverse_direction=True)
|
|
self.assert_compile(
|
|
lazywhere,
|
|
"lft.id = :param_1 AND lft.x = :x_1",
|
|
checkparams={'param_1': None, 'x_1': 5}
|
|
)
|
|
|
|
def test_lazy_clause_remote_local_multiple_ref(self):
|
|
joincond = self._join_fixture_remote_local_multiple_ref()
|
|
lazywhere, bind_to_col, equated_columns = joincond.create_lazy_clause()
|
|
|
|
self.assert_compile(
|
|
lazywhere,
|
|
":param_1 = selfref.sid OR selfref.sid = :param_1",
|
|
checkparams={'param_1': None}
|
|
)
|