From: Mike Bayer Date: Tue, 2 Jul 2019 22:16:38 +0000 (-0400) Subject: Rework proxy_cache fix to restore performance X-Git-Tag: rel_1_3_6~23 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=60ba866fae488f1da4439ac6ab9366a7b2543070;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git Rework proxy_cache fix to restore performance Adjustment to the fix made in I7fb134cac3604f8fe62e220fb24a0945d0a1c56f. Fixes: #4747 Change-Id: I2f1010b0abc1faa892f5e346e58f9c4a3867622f (cherry picked from commit 9b52c8ae927ae2628dcc1763d2e31245285f4d88) --- diff --git a/lib/sqlalchemy/sql/elements.py b/lib/sqlalchemy/sql/elements.py index 0519924288..d36be47626 100644 --- a/lib/sqlalchemy/sql/elements.py +++ b/lib/sqlalchemy/sql/elements.py @@ -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) diff --git a/lib/sqlalchemy/sql/selectable.py b/lib/sqlalchemy/sql/selectable.py index ecdb76388f..c418d1542a 100644 --- a/lib/sqlalchemy/sql/selectable.py +++ b/lib/sqlalchemy/sql/selectable.py @@ -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) ], ) diff --git a/test/sql/test_selectable.py b/test/sql/test_selectable.py index 78ff548386..3d5f1e6624 100644 --- a/test/sql/test_selectable.py +++ b/test/sql/test_selectable.py @@ -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})