diff options
| author | Mike Bayer <mike_mp@zzzcomputing.com> | 2012-07-23 18:22:06 -0400 |
|---|---|---|
| committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2012-07-23 18:22:06 -0400 |
| commit | 65bdf245c6cfd4381f8463714fbec1880a950fbb (patch) | |
| tree | 8ecbc4326e4379eb6c6dd964171a8686cc1be770 /lib/sqlalchemy/sql/expression.py | |
| parent | ee0f80b4f028e27f35ae851e37e4070a9179b2a1 (diff) | |
| download | sqlalchemy-65bdf245c6cfd4381f8463714fbec1880a950fbb.tar.gz | |
- [feature] ORM entities can be passed
to select() as well as the select_from(),
correlate(), and correlate_except()
methods, where they will be unwrapped
into selectables. [ticket:2245]
Diffstat (limited to 'lib/sqlalchemy/sql/expression.py')
| -rw-r--r-- | lib/sqlalchemy/sql/expression.py | 54 |
1 files changed, 43 insertions, 11 deletions
diff --git a/lib/sqlalchemy/sql/expression.py b/lib/sqlalchemy/sql/expression.py index b9c149954..a518852d8 100644 --- a/lib/sqlalchemy/sql/expression.py +++ b/lib/sqlalchemy/sql/expression.py @@ -1426,6 +1426,19 @@ def _literal_as_text(element): "SQL expression object or string expected." ) +def _interpret_as_from(element): + insp = inspection.inspect(element, raiseerr=False) + if insp is None: + if isinstance(element, (util.NoneType, bool)): + return _const_expr(element) + elif isinstance(element, basestring): + return TextClause(unicode(element)) + elif hasattr(insp, "selectable"): + return insp.selectable + else: + raise exc.ArgumentError("FROM expression expected") + + def _const_expr(element): if element is None: return null() @@ -1445,12 +1458,15 @@ def _clause_element_as_expr(element): return element def _literal_as_column(element): - if isinstance(element, Visitable): - return element - elif hasattr(element, '__clause_element__'): - return element.__clause_element__() - else: - return literal_column(str(element)) + insp = inspection.inspect(element, raiseerr=False) + if insp is not None: + if hasattr(insp, "expression"): + return insp.expression + elif hasattr(insp, "selectable"): + return insp.selectable + elif insp.is_clause_element: + return insp + return literal_column(str(element)) def _literal_as_binds(element, name=None, type_=None): if hasattr(element, '__clause_element__'): @@ -1539,6 +1555,7 @@ class ClauseElement(Visitable): bind = None _is_clone_of = None is_selectable = False + is_clause_element = True def _clone(self): """Create a shallow copy of this ClauseElement. @@ -2174,6 +2191,15 @@ class ColumnElement(ClauseElement, CompareMixin): _alt_names = () @property + def expression(self): + """Return a column expression. + + Part of the inspection interface; returns self. + + """ + return self + + @property def _select_iterable(self): return (self, ) @@ -2973,6 +2999,10 @@ class TextClause(Executable, ClauseElement): def _select_iterable(self): return (self,) + @property + def selectable(self): + return self + _hide_froms = [] def __init__( @@ -5315,7 +5345,8 @@ class Select(SelectBase): if fromclauses and fromclauses[0] is None: self._correlate = () else: - self._correlate = set(self._correlate).union(fromclauses) + self._correlate = set(self._correlate).union( + _interpret_as_from(f) for f in fromclauses) @_generative def correlate_except(self, *fromclauses): @@ -5323,15 +5354,16 @@ class Select(SelectBase): if fromclauses and fromclauses[0] is None: self._correlate_except = () else: - self._correlate_except = set(self._correlate_except - ).union(fromclauses) + self._correlate_except = set(self._correlate_except).union( + _interpret_as_from(f) for f in fromclauses) def append_correlation(self, fromclause): """append the given correlation expression to this select() construct.""" self._should_correlate = False - self._correlate = set(self._correlate).union([fromclause]) + self._correlate = set(self._correlate).union( + _interpret_as_from(f) for f in fromclause) def append_column(self, column): """append the given column expression to the columns clause of this @@ -5387,7 +5419,7 @@ class Select(SelectBase): """ self._reset_exported() - fromclause = _literal_as_text(fromclause) + fromclause = _interpret_as_from(fromclause) self._from_obj = self._from_obj.union([fromclause]) def _populate_column_collection(self): |
