summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy/sql/elements.py
diff options
context:
space:
mode:
authormike bayer <mike_mp@zzzcomputing.com>2019-08-30 15:21:08 +0000
committerGerrit Code Review <gerrit@bbpush.zzzcomputing.com>2019-08-30 15:21:08 +0000
commitf499671ccc30cd42d6e3beb6ddec60e104bff9c5 (patch)
treedef2ccba55e3d4231bc2019472c69a5e2eaa6d97 /lib/sqlalchemy/sql/elements.py
parent2b042b6d18dc527c12b2ef1239bfe5ee2b658930 (diff)
parent3bb402ff8ed980ae393def7462b1da49c0e0a8a7 (diff)
downloadsqlalchemy-f499671ccc30cd42d6e3beb6ddec60e104bff9c5.tar.gz
Merge "Label simple column transformations as the column name"
Diffstat (limited to 'lib/sqlalchemy/sql/elements.py')
-rw-r--r--lib/sqlalchemy/sql/elements.py54
1 files changed, 51 insertions, 3 deletions
diff --git a/lib/sqlalchemy/sql/elements.py b/lib/sqlalchemy/sql/elements.py
index e2df1adc2..669519d1a 100644
--- a/lib/sqlalchemy/sql/elements.py
+++ b/lib/sqlalchemy/sql/elements.py
@@ -914,6 +914,42 @@ class ColumnElement(
return self._anon_label(getattr(self, "_label", None))
+class WrapsColumnExpression(object):
+ """Mixin that defines a :class:`.ColumnElement` as a wrapper with special
+ labeling behavior for an expression that already has a name.
+
+ .. versionadded:: 1.4
+
+ .. seealso::
+
+ :ref:`change_4449`
+
+
+ """
+
+ @property
+ def wrapped_column_expression(self):
+ raise NotImplementedError()
+
+ @property
+ def _label(self):
+ wce = self.wrapped_column_expression
+ if hasattr(wce, "_label"):
+ return wce._label
+ else:
+ return None
+
+ @property
+ def anon_label(self):
+ wce = self.wrapped_column_expression
+ if hasattr(wce, "name"):
+ return wce.name
+ elif hasattr(wce, "anon_label"):
+ return wce.anon_label
+ else:
+ return super(WrapsColumnExpression, self).anon_label
+
+
class BindParameter(roles.InElementRole, ColumnElement):
r"""Represent a "bound expression".
@@ -2477,7 +2513,7 @@ def literal_column(text, type_=None):
return ColumnClause(text, type_=type_, is_literal=True)
-class Cast(ColumnElement):
+class Cast(WrapsColumnExpression, ColumnElement):
"""Represent a ``CAST`` expression.
:class:`.Cast` is produced using the :func:`.cast` factory function,
@@ -2582,8 +2618,12 @@ class Cast(ColumnElement):
def _from_objects(self):
return self.clause._from_objects
+ @property
+ def wrapped_column_expression(self):
+ return self.clause
+
-class TypeCoerce(ColumnElement):
+class TypeCoerce(WrapsColumnExpression, ColumnElement):
"""Represent a Python-side type-coercion wrapper.
:class:`.TypeCoerce` supplies the :func:`.expression.type_coerce`
@@ -2694,6 +2734,10 @@ class TypeCoerce(ColumnElement):
else:
return self.clause
+ @property
+ def wrapped_column_expression(self):
+ return self.clause
+
class Extract(ColumnElement):
"""Represent a SQL EXTRACT clause, ``extract(field FROM expr)``."""
@@ -3162,7 +3206,7 @@ class CollectionAggregate(UnaryExpression):
)
-class AsBoolean(UnaryExpression):
+class AsBoolean(WrapsColumnExpression, UnaryExpression):
def __init__(self, element, operator, negate):
self.element = element
self.type = type_api.BOOLEANTYPE
@@ -3172,6 +3216,10 @@ class AsBoolean(UnaryExpression):
self.wraps_column_expression = True
self._is_implicitly_boolean = element._is_implicitly_boolean
+ @property
+ def wrapped_column_expression(self):
+ return self.element
+
def self_group(self, against=None):
# type: (Optional[Any]) -> ClauseElement
return self