diff options
| author | Mike Bayer <mike_mp@zzzcomputing.com> | 2019-07-07 11:12:31 -0400 |
|---|---|---|
| committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2019-07-11 14:20:10 -0400 |
| commit | aceefb508ccd0911f52ff0e50324b3fefeaa3f16 (patch) | |
| tree | e57124d3ea8b0e2cd7fe1d3ad22170fa956bcafb /lib/sqlalchemy/sql/elements.py | |
| parent | 5c16367ee78fa1a41d6b715152dcc58f45323d2e (diff) | |
| download | sqlalchemy-aceefb508ccd0911f52ff0e50324b3fefeaa3f16.tar.gz | |
Allow duplicate columns in from clauses and selectables
The :func:`.select` construct and related constructs now allow for
duplication of column labels and columns themselves in the columns clause,
mirroring exactly how column expressions were passed in. This allows
the tuples returned by an executed result to match what was SELECTed
for in the first place, which is how the ORM :class:`.Query` works, so
this establishes better cross-compatibility between the two constructs.
Additionally, it allows column-positioning-sensitive structures such as
UNIONs (i.e. :class:`.CompoundSelect`) to be more intuitively constructed
in those cases where a particular column might appear in more than one
place. To support this change, the :class:`.ColumnCollection` has been
revised to support duplicate columns as well as to allow integer index
access.
Fixes: #4753
Change-Id: Ie09a8116f05c367995c1e43623c51e07971d3bf0
Diffstat (limited to 'lib/sqlalchemy/sql/elements.py')
| -rw-r--r-- | lib/sqlalchemy/sql/elements.py | 28 |
1 files changed, 15 insertions, 13 deletions
diff --git a/lib/sqlalchemy/sql/elements.py b/lib/sqlalchemy/sql/elements.py index 5b4442222..735a125d7 100644 --- a/lib/sqlalchemy/sql/elements.py +++ b/lib/sqlalchemy/sql/elements.py @@ -184,6 +184,7 @@ class ClauseElement(roles.SQLRole, Visitable): _is_returns_rows = False _is_text_clause = False _is_from_container = False + _is_select_container = False _is_select_statement = False _order_by_label_element = None @@ -856,8 +857,7 @@ class ColumnElement( co._proxies = [self] if selectable._is_clone_of is not None: co._is_clone_of = selectable._is_clone_of.columns.get(key) - selectable._columns[key] = co - return co + return key, co def cast(self, type_): """Produce a type cast, i.e. ``CAST(<expression> AS <type>)``. @@ -887,6 +887,12 @@ class ColumnElement( """ return Label(name, self, self.type) + def _anon_label(self, seed): + while self._is_clone_of is not None: + self = self._is_clone_of + + return _anonymous_label("%%(%d %s)s" % (id(self), seed or "anon")) + @util.memoized_property def anon_label(self): """provides a constant 'anonymous label' for this ColumnElement. @@ -901,12 +907,11 @@ class ColumnElement( expressions and function calls. """ - while self._is_clone_of is not None: - self = self._is_clone_of + return self._anon_label(getattr(self, "name", None)) - return _anonymous_label( - "%%(%d %s)s" % (id(self), getattr(self, "name", "anon")) - ) + @util.memoized_property + def _label_anon_label(self): + return self._anon_label(getattr(self, "_label", None)) class BindParameter(roles.InElementRole, ColumnElement): @@ -3951,7 +3956,7 @@ class Label(roles.LabeledColumnExprRole, ColumnElement): return self.element._from_objects def _make_proxy(self, selectable, name=None, **kw): - e = self.element._make_proxy( + key, e = self.element._make_proxy( selectable, name=name if name else self.name, disallow_is_literal=True, @@ -3959,7 +3964,7 @@ class Label(roles.LabeledColumnExprRole, ColumnElement): e._proxies.append(self) if self._type is not None: e.type = self._type - return e + return key, e class ColumnClause(roles.LabeledColumnExprRole, Immutable, ColumnElement): @@ -4214,7 +4219,6 @@ class ColumnClause(roles.LabeledColumnExprRole, Immutable, ColumnElement): self, selectable, name=None, - attach=True, name_is_truncatable=False, disallow_is_literal=False, **kw @@ -4249,9 +4253,7 @@ class ColumnClause(roles.LabeledColumnExprRole, Immutable, ColumnElement): if selectable._is_clone_of is not None: c._is_clone_of = selectable._is_clone_of.columns.get(c.key) - if attach: - selectable._columns[c.key] = c - return c + return c.key, c class CollationClause(ColumnElement): |
