]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
accommodate HasEntityNamespace in context.all_selected_columns
authorMike Bayer <mike_mp@zzzcomputing.com>
Thu, 29 Apr 2021 14:40:00 +0000 (10:40 -0400)
committerMike Bayer <mike_mp@zzzcomputing.com>
Thu, 29 Apr 2021 14:41:07 +0000 (10:41 -0400)
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

doc/build/changelog/unreleased_14/6401.rst [new file with mode: 0644]
lib/sqlalchemy/orm/attributes.py
lib/sqlalchemy/orm/context.py
test/ext/test_hybrid.py

diff --git a/doc/build/changelog/unreleased_14/6401.rst b/doc/build/changelog/unreleased_14/6401.rst
new file mode 100644 (file)
index 0000000..046d682
--- /dev/null
@@ -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()``.
+
index b8974196cf46c738eb242cd75775006999e8ec9e..2f8c8f94029517465ce2a3f76312fc8a0abd2f45 100644 (file)
@@ -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):
index 55b61b19ea4f33eb9d91e52a68c0b6e83c039b3d..aeba9ed80b327c03b318ba006cca1f6c3ac0e8ab 100644 (file)
@@ -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
index ee991782ef9179369d882d8553b1ee731d4334da..9085ccc96a0f4268a94ffe0760be4a55ba6a9523 100644 (file)
@@ -492,6 +492,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(