summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy
diff options
context:
space:
mode:
Diffstat (limited to 'lib/sqlalchemy')
-rw-r--r--lib/sqlalchemy/sql/coercions.py26
-rw-r--r--lib/sqlalchemy/sql/elements.py1
-rw-r--r--lib/sqlalchemy/sql/traversals.py1
3 files changed, 22 insertions, 6 deletions
diff --git a/lib/sqlalchemy/sql/coercions.py b/lib/sqlalchemy/sql/coercions.py
index 36ac507ad..82068d768 100644
--- a/lib/sqlalchemy/sql/coercions.py
+++ b/lib/sqlalchemy/sql/coercions.py
@@ -151,12 +151,25 @@ def expect(
is_clause_element = False
- while hasattr(element, "__clause_element__"):
+ # this is a special performance optimization for ORM
+ # joins used by JoinTargetImpl that we don't go through the
+ # work of creating __clause_element__() when we only need the
+ # original QueryableAttribute, as the former will do clause
+ # adaption and all that which is just thrown away here.
+ if (
+ impl._skip_clauseelement_for_target_match
+ and isinstance(element, role)
+ and hasattr(element, "__clause_element__")
+ ):
is_clause_element = True
- if not getattr(element, "is_clause_element", False):
- element = element.__clause_element__()
- else:
- break
+ else:
+ while hasattr(element, "__clause_element__"):
+ is_clause_element = True
+
+ if not getattr(element, "is_clause_element", False):
+ element = element.__clause_element__()
+ else:
+ break
if not is_clause_element:
if impl._use_inspection:
@@ -230,6 +243,7 @@ class RoleImpl(object):
_post_coercion = None
_resolve_literal_only = False
+ _skip_clauseelement_for_target_match = False
def __init__(self, role_class):
self._role_class = role_class
@@ -860,6 +874,8 @@ class HasCTEImpl(ReturnsRowsImpl):
class JoinTargetImpl(RoleImpl):
__slots__ = ()
+ _skip_clauseelement_for_target_match = True
+
def _literal_coercion(self, element, legacy=False, **kw):
if isinstance(element, str):
return element
diff --git a/lib/sqlalchemy/sql/elements.py b/lib/sqlalchemy/sql/elements.py
index f212cb079..213f47c40 100644
--- a/lib/sqlalchemy/sql/elements.py
+++ b/lib/sqlalchemy/sql/elements.py
@@ -4395,6 +4395,7 @@ class Label(roles.LabeledColumnExprRole, ColumnElement):
return self.element.foreign_keys
def _copy_internals(self, clone=_clone, anonymize_labels=False, **kw):
+ self._reset_memoizations()
self._element = clone(self._element, **kw)
if anonymize_labels:
self.name = self._resolve_label = _anonymous_label.safe_construct(
diff --git a/lib/sqlalchemy/sql/traversals.py b/lib/sqlalchemy/sql/traversals.py
index e64eff6a4..35f2bd62f 100644
--- a/lib/sqlalchemy/sql/traversals.py
+++ b/lib/sqlalchemy/sql/traversals.py
@@ -737,7 +737,6 @@ class HasCopyInternals(object):
continue
if obj is not None:
-
result = meth(attrname, self, obj, **kw)
if result is not None:
setattr(self, attrname, result)