]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
Rework proxy_cache fix to restore performance
authorMike Bayer <mike_mp@zzzcomputing.com>
Tue, 2 Jul 2019 22:16:38 +0000 (18:16 -0400)
committerMike Bayer <mike_mp@zzzcomputing.com>
Tue, 2 Jul 2019 22:23:06 +0000 (18:23 -0400)
Adjustment to the fix made in I7fb134cac3604f8fe62e220fb24a0945d0a1c56f.

Fixes: #4747
Change-Id: I2f1010b0abc1faa892f5e346e58f9c4a3867622f
(cherry picked from commit 9b52c8ae927ae2628dcc1763d2e31245285f4d88)

lib/sqlalchemy/sql/elements.py
lib/sqlalchemy/sql/selectable.py
test/sql/test_selectable.py

index 05199242883d77ecf3f3885802d275f87aab0f31..d36be4762691230965d9ab4a08ffcf4bf0612979 100644 (file)
@@ -761,6 +761,18 @@ class ColumnElement(operators.ColumnOperators, ClauseElement):
             s.update(c.proxy_set)
         return s
 
+    def _uncached_proxy_set(self):
+        """An 'uncached' version of proxy set.
+
+        This is so that we can read annotations from the list of columns
+        without breaking the caching of the above proxy_set.
+
+        """
+        s = util.column_set([self])
+        for c in self._proxies:
+            s.update(c._uncached_proxy_set())
+        return s
+
     def shares_lineage(self, othercolumn):
         """Return True if the given :class:`.ColumnElement`
         has a common ancestor to this :class:`.ColumnElement`."""
@@ -4628,8 +4640,6 @@ class AnnotatedColumnElement(Annotated):
     def __init__(self, element, values):
         Annotated.__init__(self, element, values)
         ColumnElement.comparator._reset(self)
-        if self._proxies:
-            ColumnElement.proxy_set._reset(self)
         for attr in ("name", "key", "table"):
             if self.__dict__.get(attr, False) is None:
                 self.__dict__.pop(attr)
index ecdb76388f1a04285d73e6cf249e62cccdaa879a..c418d1542aa51ee608addb1d8fe43f3e7a67aea3 100644 (file)
@@ -578,7 +578,7 @@ class FromClause(Selectable):
                         operator.add,
                         [
                             sc._annotations.get("weight", 1)
-                            for sc in col.proxy_set
+                            for sc in col._uncached_proxy_set()
                             if sc.shares_lineage(column)
                         ],
                     )
@@ -586,7 +586,7 @@ class FromClause(Selectable):
                         operator.add,
                         [
                             sc._annotations.get("weight", 1)
-                            for sc in c.proxy_set
+                            for sc in c._uncached_proxy_set()
                             if sc.shares_lineage(column)
                         ],
                     )
index 78ff54838627ec74dbd275b320519f3c8e465223..3d5f1e66243c0543b536f25285b96eb1cd521518 100644 (file)
@@ -1944,7 +1944,23 @@ class AnnotationsTest(fixtures.TestBase):
         # proxy_set, as corresponding_column iterates through proxy_set
         # in this way
         d = {}
-        for col in p2.proxy_set:
+        for col in p2._uncached_proxy_set():
+            d.update(col._annotations)
+        eq_(d, {"weight": 10})
+
+    def test_proxy_set_iteration_includes_annotated_two(self):
+        from sqlalchemy.schema import Column
+
+        c1 = Column("foo", Integer)
+
+        stmt = select([c1]).alias()
+        proxy = stmt.c.foo
+        c1.proxy_set
+
+        proxy._proxies = [c1._annotate({"weight": 10})]
+
+        d = {}
+        for col in proxy._uncached_proxy_set():
             d.update(col._annotations)
         eq_(d, {"weight": 10})