when joinedload() or subqueryload() options
are applied to a dynamic attribute, instead
of failure / silent failure. [ticket:1864]
+
+ - Fixed bug whereby generating a Query derived
+ from one which had the same column repeated
+ with different label names, typically
+ in some UNION situations, would fail to
+ propagate the inner columns completely to
+ the outer query. [ticket:1852]
- sql
- Changed the scheme used to generate truncated
columns in a reflected table would cause an attempt
to remove the reflected constraint from the table
a second time, raising a KeyError. [ticket:1865]
+
+ - the _Label construct, i.e. the one that is produced
+ whenever you say somecol.label(), now counts itself
+ in its "proxy_set" unioned with that of it's
+ contained column's proxy set, instead of
+ directly returning that of the contained column.
+ This allows column correspondence
+ operations which depend on the identity of the
+ _Labels themselves to return the correct result
+ - fixes ORM bug [ticket:1852].
- declarative
- if @classproperty is used with a regular class-bound
self._element = element
self._type = type_
self.quote = element.quote
-
+ self.proxies = [element]
+
@util.memoized_property
def type(self):
return sqltypes.to_instance(
def element(self):
return self._element.self_group(against=operators.as_)
- def _proxy_attr(name):
- get = attrgetter(name)
- def attr(self):
- return get(self.element)
- return property(attr)
+ @property
+ def primary_key(self):
+ return self.element.primary_key
- proxies = _proxy_attr('proxies')
- base_columns = _proxy_attr('base_columns')
- proxy_set = _proxy_attr('proxy_set')
- primary_key = _proxy_attr('primary_key')
- foreign_keys = _proxy_attr('foreign_keys')
+ @property
+ def foreign_keys(self):
+ return self.element.foreign_keys
def get_children(self, **kwargs):
return self.element,
e = self.element._make_proxy(selectable, name=self.name)
else:
e = column(self.name)._make_proxy(selectable=selectable)
+
e.proxies.append(self)
return e
(User(id=10, name=u'chuck'), u'y')
]
)
+
+ c1, c2 = column('c1'), column('c2')
+ q1 = s.query(User, c1.label('foo'), c1.label('bar'))
+ q2 = s.query(User, c1.label('foo'), c2.label('bar'))
+ q3 = q1.union(q2)
+ self.assert_compile(
+ q3,
+ "SELECT anon_1.users_id AS anon_1_users_id, "
+ "anon_1.users_name AS anon_1_users_name, "
+ "anon_1.foo AS anon_1_foo, anon_1.bar AS anon_1_bar "
+ "FROM (SELECT users.id AS users_id, users.name AS users_name, "
+ "c1 AS foo, c1 AS bar FROM users UNION SELECT users.id AS "
+ "users_id, users.name AS users_name, c1 AS foo, c2 AS bar "
+ "FROM users) AS anon_1",
+ use_default_dialect=True
+ )
@testing.fails_on('mysql', "mysql doesn't support intersect")
def test_intersect(self):
class SelectableTest(TestBase, AssertsExecutionResults):
- def test_distance_on_labels(self):
-
+ def test_indirect_correspondence_on_labels(self):
+ # this test depends upon 'distance' to
+ # get the right result
+
# same column three times
s = select([table1.c.col1.label('c2'), table1.c.col1,
table1.c.col1.label('c1')])
- # didnt do this yet...col.label().make_proxy() has same
- # "distance" as col.make_proxy() so far assert
- # s.corresponding_column(table1.c.col1) is s.c.col1
+ # this tests the same thing as
+ # test_direct_correspondence_on_labels below -
+ # that the presence of label() affects the 'distance'
+ assert s.corresponding_column(table1.c.col1) is s.c.col1
assert s.corresponding_column(s.c.col1) is s.c.col1
assert s.corresponding_column(s.c.c1) is s.c.c1
+ def test_direct_correspondence_on_labels(self):
+ # this test depends on labels being part
+ # of the proxy set to get the right result
+
+ l1, l2 = table1.c.col1.label('foo'), table1.c.col1.label('bar')
+ sel = select([l1, l2])
+
+ sel2 = sel.alias()
+ assert sel2.corresponding_column(l1) is sel2.c.foo
+ assert sel2.corresponding_column(l2) is sel2.c.bar
+
+ sel2 = select([table1.c.col1.label('foo'), table1.c.col2.label('bar')])
+
+ sel3 = sel.union(sel2).alias()
+ assert sel3.corresponding_column(l1) is sel3.c.foo
+ assert sel3.corresponding_column(l2) is sel3.c.bar
+
def test_distance_on_aliases(self):
a1 = table1.alias('a1')
for s in (select([a1, table1], use_labels=True),