summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2012-10-15 17:21:38 -0400
committerMike Bayer <mike_mp@zzzcomputing.com>2012-10-15 17:21:38 -0400
commitc307df6596dab489109cd216665cf30006b70d13 (patch)
tree4ce669b36759f8289d959c0e7e92b776b77d1865 /lib
parent3510e38a772a2e48a8bb4b0a4efc6479034f649e (diff)
downloadsqlalchemy-c307df6596dab489109cd216665cf30006b70d13.tar.gz
- [feature] "scalar" selects now have a WHERE method
to help with generative building. Also slight adjustment regarding how SS "correlates" columns; the new methodology no longer applies meaning to the underlying Table column being selected. This improves some fairly esoteric situations, and the logic that was there didn't seem to have any purpose. - [feature] Some support for auto-rendering of a relationship join condition based on the mapped attribute, with usage of core SQL constructs. E.g. select([SomeClass]).where(SomeClass.somerelationship) would render SELECT from "someclass" and use the primaryjoin of "somerelationship" as the WHERE clause. This changes the previous meaning of "SomeClass.somerelationship" when used in a core SQL context; previously, it would "resolve" to the parent selectable, which wasn't generally useful. Related to [ticket:2245].
Diffstat (limited to 'lib')
-rw-r--r--lib/sqlalchemy/orm/properties.py23
-rw-r--r--lib/sqlalchemy/orm/util.py2
-rw-r--r--lib/sqlalchemy/sql/expression.py14
3 files changed, 31 insertions, 8 deletions
diff --git a/lib/sqlalchemy/orm/properties.py b/lib/sqlalchemy/orm/properties.py
index f8288f5fb..048b4fad3 100644
--- a/lib/sqlalchemy/orm/properties.py
+++ b/lib/sqlalchemy/orm/properties.py
@@ -350,6 +350,8 @@ class RelationshipProperty(StrategizedProperty):
"""
+ _of_type = None
+
def __init__(self, prop, mapper, of_type=None, adapter=None):
"""Construction of :class:`.RelationshipProperty.Comparator`
is internal to the ORM's attribute mechanics.
@@ -376,13 +378,30 @@ class RelationshipProperty(StrategizedProperty):
def parententity(self):
return self.property.parent
- def __clause_element__(self):
+ def _source_selectable(self):
elem = self.property.parent._with_polymorphic_selectable
if self.adapter:
return self.adapter(elem)
else:
return elem
+ def __clause_element__(self):
+ adapt_from = self._source_selectable()
+ if self._of_type:
+ of_type = inspect(self._of_type).mapper
+ else:
+ of_type = None
+
+ pj, sj, source, dest, \
+ secondary, target_adapter = self.property._create_joins(
+ source_selectable=adapt_from,
+ source_polymorphic=True,
+ of_type=of_type)
+ if sj is not None:
+ return pj & sj
+ else:
+ return pj
+
def of_type(self, cls):
"""Produce a construct that represents a particular 'subtype' of
attribute for the parent class.
@@ -477,7 +496,7 @@ class RelationshipProperty(StrategizedProperty):
to_selectable = None
if self.adapter:
- source_selectable = self.__clause_element__()
+ source_selectable = self._source_selectable()
else:
source_selectable = None
diff --git a/lib/sqlalchemy/orm/util.py b/lib/sqlalchemy/orm/util.py
index 750c3b298..2e38e0ce3 100644
--- a/lib/sqlalchemy/orm/util.py
+++ b/lib/sqlalchemy/orm/util.py
@@ -796,7 +796,7 @@ class _ORMJoin(expression.Join):
prop = left_mapper.get_property(onclause)
elif isinstance(onclause, attributes.QueryableAttribute):
if adapt_from is None:
- adapt_from = onclause.__clause_element__()
+ adapt_from = onclause.comparator._source_selectable()
prop = onclause.property
elif isinstance(onclause, MapperProperty):
prop = onclause
diff --git a/lib/sqlalchemy/sql/expression.py b/lib/sqlalchemy/sql/expression.py
index 63b1a4037..5b6e4d82d 100644
--- a/lib/sqlalchemy/sql/expression.py
+++ b/lib/sqlalchemy/sql/expression.py
@@ -4839,7 +4839,7 @@ class SelectBase(Executable, FromClause):
return [self]
-class ScalarSelect(Grouping):
+class ScalarSelect(Generative, Grouping):
_from_objects = []
def __init__(self, element):
@@ -4853,13 +4853,17 @@ class ScalarSelect(Grouping):
'column-level expression.')
c = columns
+ @_generative
+ def where(self, crit):
+ """Apply a WHERE clause to the SELECT statement referred to
+ by this :class:`.ScalarSelect`.
+
+ """
+ self.element = self.element.where(crit)
+
def self_group(self, **kwargs):
return self
- def _make_proxy(self, selectable, name=None, **kw):
- return list(self.inner_columns)[0]._make_proxy(
- selectable, name=name)
-
class CompoundSelect(SelectBase):
"""Forms the basis of ``UNION``, ``UNION ALL``, and other
SELECT-based set operations."""