1from sqlalchemy import and_
2from sqlalchemy import bindparam
3from sqlalchemy import Column
4from sqlalchemy import Integer
5from sqlalchemy import MetaData
6from sqlalchemy import or_
7from sqlalchemy import String
8from sqlalchemy import Table
9from sqlalchemy.sql import operators
10from sqlalchemy.sql import util as sql_util
11from sqlalchemy.sql.elements import ClauseList
12from sqlalchemy.sql.elements import ColumnElement
13from sqlalchemy.testing import eq_
14from sqlalchemy.testing import fixtures
15from sqlalchemy.testing import is_false
16from sqlalchemy.testing import is_true
17
18
19class CompareClausesTest(fixtures.TestBase):
20    def setup(self):
21        m = MetaData()
22        self.a = Table("a", m, Column("x", Integer), Column("y", Integer))
23
24        self.b = Table("b", m, Column("y", Integer), Column("z", Integer))
25
26    def test_compare_clauselist_associative(self):
27
28        l1 = and_(self.a.c.x == self.b.c.y, self.a.c.y == self.b.c.z)
29
30        l2 = and_(self.a.c.y == self.b.c.z, self.a.c.x == self.b.c.y)
31
32        l3 = and_(self.a.c.x == self.b.c.z, self.a.c.y == self.b.c.y)
33
34        is_true(l1.compare(l1))
35        is_true(l1.compare(l2))
36        is_false(l1.compare(l3))
37
38    def test_compare_clauselist_not_associative(self):
39
40        l1 = ClauseList(
41            self.a.c.x, self.a.c.y, self.b.c.y, operator=operators.sub
42        )
43
44        l2 = ClauseList(
45            self.b.c.y, self.a.c.x, self.a.c.y, operator=operators.sub
46        )
47
48        is_true(l1.compare(l1))
49        is_false(l1.compare(l2))
50
51    def test_compare_clauselist_assoc_different_operator(self):
52
53        l1 = and_(self.a.c.x == self.b.c.y, self.a.c.y == self.b.c.z)
54
55        l2 = or_(self.a.c.y == self.b.c.z, self.a.c.x == self.b.c.y)
56
57        is_false(l1.compare(l2))
58
59    def test_compare_clauselist_not_assoc_different_operator(self):
60
61        l1 = ClauseList(
62            self.a.c.x, self.a.c.y, self.b.c.y, operator=operators.sub
63        )
64
65        l2 = ClauseList(
66            self.a.c.x, self.a.c.y, self.b.c.y, operator=operators.div
67        )
68
69        is_false(l1.compare(l2))
70
71    def test_compare_binds(self):
72        b1 = bindparam("foo", type_=Integer())
73        b2 = bindparam("foo", type_=Integer())
74        b3 = bindparam("bar", type_=Integer())
75        b4 = bindparam("foo", type_=String())
76
77        def c1():
78            return 5
79
80        def c2():
81            return 6
82
83        b5 = bindparam("foo", type_=Integer(), callable_=c1)
84        b6 = bindparam("foo", type_=Integer(), callable_=c2)
85        b7 = bindparam("foo", type_=Integer(), callable_=c1)
86
87        b8 = bindparam("foo", type_=Integer, value=5)
88        b9 = bindparam("foo", type_=Integer, value=6)
89
90        is_false(b1.compare(b5))
91        is_true(b5.compare(b7))
92        is_false(b5.compare(b6))
93        is_true(b1.compare(b2))
94
95        # currently not comparing "key", as we often have to compare
96        # anonymous names.  however we should really check for that
97        is_true(b1.compare(b3))
98
99        is_false(b1.compare(b4))
100        is_false(b1.compare(b8))
101        is_false(b8.compare(b9))
102        is_true(b8.compare(b8))
103
104
105class MiscTest(fixtures.TestBase):
106    def test_column_element_no_visit(self):
107        class MyElement(ColumnElement):
108            pass
109
110        eq_(sql_util.find_tables(MyElement(), check_columns=True), [])
111