summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2021-04-29 10:40:00 -0400
committerMike Bayer <mike_mp@zzzcomputing.com>2021-04-29 10:41:07 -0400
commit28493bf4bc35a4802b57b02a8b389cec7b6dcbb6 (patch)
tree018e876612cf5885f60e41434a5112134225a5a8
parent9e3ef9bcf0a41bfacc4e6e836a45ed4d89c7c0fe (diff)
downloadsqlalchemy-28493bf4bc35a4802b57b02a8b389cec7b6dcbb6.tar.gz
accommodate HasEntityNamespace in context.all_selected_columns
Fixed regression in hybrid_property where a hybrid against a SQL function would generate an ``AttributeError`` when attempting to generate an entry for the ``.c`` collection of a subquery in some cases; among other things this would impact its use in cases like that of ``Query.count()``. Fixes: #6401 Change-Id: Icc243c699e9a5c88448076c6427ec389eaa8b8ed
-rw-r--r--doc/build/changelog/unreleased_14/6401.rst9
-rw-r--r--lib/sqlalchemy/orm/attributes.py1
-rw-r--r--lib/sqlalchemy/orm/context.py13
-rw-r--r--test/ext/test_hybrid.py21
4 files changed, 38 insertions, 6 deletions
diff --git a/doc/build/changelog/unreleased_14/6401.rst b/doc/build/changelog/unreleased_14/6401.rst
new file mode 100644
index 000000000..046d6825b
--- /dev/null
+++ b/doc/build/changelog/unreleased_14/6401.rst
@@ -0,0 +1,9 @@
+.. change::
+ :tags: orm, bug, regression
+ :tickets: 6401
+
+ Fixed regression in hybrid_property where a hybrid against a SQL function
+ would generate an ``AttributeError`` when attempting to generate an entry
+ for the ``.c`` collection of a subquery in some cases; among other things
+ this would impact its use in cases like that of ``Query.count()``.
+
diff --git a/lib/sqlalchemy/orm/attributes.py b/lib/sqlalchemy/orm/attributes.py
index b8974196c..2f8c8f940 100644
--- a/lib/sqlalchemy/orm/attributes.py
+++ b/lib/sqlalchemy/orm/attributes.py
@@ -483,6 +483,7 @@ class InstrumentedAttribute(Mapped):
HasEntityNamespace = util.namedtuple(
"HasEntityNamespace", ["entity_namespace"]
)
+HasEntityNamespace.is_mapper = HasEntityNamespace.is_aliased_class = False
def create_proxied_attribute(descriptor):
diff --git a/lib/sqlalchemy/orm/context.py b/lib/sqlalchemy/orm/context.py
index 55b61b19e..aeba9ed80 100644
--- a/lib/sqlalchemy/orm/context.py
+++ b/lib/sqlalchemy/orm/context.py
@@ -802,12 +802,13 @@ class ORMSelectCompileState(ORMCompileState, SelectState):
element.is_selectable
and "entity_namespace" in element._annotations
):
- for elem in _select_iterables(
- element._annotations[
- "entity_namespace"
- ]._all_column_expressions
- ):
- yield elem
+ ens = element._annotations["entity_namespace"]
+ if not ens.is_mapper and not ens.is_aliased_class:
+ for elem in _select_iterables([element]):
+ yield elem
+ else:
+ for elem in _select_iterables(ens._all_column_expressions):
+ yield elem
else:
for elem in _select_iterables([element]):
yield elem
diff --git a/test/ext/test_hybrid.py b/test/ext/test_hybrid.py
index ee991782e..9085ccc96 100644
--- a/test/ext/test_hybrid.py
+++ b/test/ext/test_hybrid.py
@@ -493,6 +493,21 @@ class PropertyMirrorTest(fixtures.TestBase, AssertsCompiledSQL):
return A
@testing.fixture
+ def _function_fixture(self):
+ Base = declarative_base()
+
+ class A(Base):
+ __tablename__ = "a"
+ id = Column(Integer, primary_key=True)
+ value = Column(Integer)
+
+ @hybrid.hybrid_property
+ def foo_value(self):
+ return func.foo(self.value)
+
+ return A
+
+ @testing.fixture
def _name_mismatch_fixture(self):
Base = declarative_base()
@@ -537,6 +552,12 @@ class PropertyMirrorTest(fixtures.TestBase, AssertsCompiledSQL):
"FROM a AS a_1 JOIN b ON a_1.id = b.aid",
)
+ def test_c_collection_func_element(self, _function_fixture):
+ A = _function_fixture
+
+ stmt = select(A.id, A.foo_value)
+ eq_(stmt.subquery().c.keys(), ["id", "foo_value"])
+
def test_filter_by_mismatched_col(self, _name_mismatch_fixture):
A, B = _name_mismatch_fixture
self.assert_compile(