]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
Ensure schema-level table includes annotations in caching
authorMike Bayer <mike_mp@zzzcomputing.com>
Mon, 24 Feb 2020 15:44:14 +0000 (10:44 -0500)
committerMike Bayer <mike_mp@zzzcomputing.com>
Mon, 24 Feb 2020 15:47:05 +0000 (10:47 -0500)
In 29330ec159 we ensured that annotations are part of cache keys.
However we failed to do so for the schema-level Table which
will definitely need to distinguish between ORM and non-ORM
annotated tables when caching, so ensure this is part of the
cache key.

Change-Id: I8d996873f2d7fa63230ef837db7e69a0101973b2

lib/sqlalchemy/sql/schema.py
test/sql/test_compare.py

index 79a700ad8d993b741a929a498d04e55feec2e2e9..7cece42d062f9289aefb3388d283bc353dfd85e2 100644 (file)
@@ -431,7 +431,7 @@ class Table(DialectKWArgs, SchemaItem, TableClause):
     ]
 
     def _gen_cache_key(self, anon_map, bindparams):
-        return (self,)
+        return (self,) + self._annotations_cache_key
 
     @util.deprecated_params(
         useexisting=(
index 2d0e393314a3d88ce7f1b6930169bb1623b09bbd..c594628451ca1439727fb2a7edf70eeaff77884b 100644 (file)
@@ -167,6 +167,25 @@ class CoreFixtures(object):
                 {"orm": True, "parententity": MyEntity("b", select([table_a]))}
             ),
         ),
+        lambda: (
+            table_a,
+            table_a._annotate({"orm": True}),
+            table_a._annotate({"orm": True})._annotate({"bar": False}),
+            table_a._annotate(
+                {"orm": True, "parententity": MyEntity("a", table_a)}
+            ),
+            table_a._annotate(
+                {"orm": True, "parententity": MyEntity("b", table_a)}
+            ),
+            table_a._annotate(
+                {"orm": True, "parententity": MyEntity("b", select([table_a]))}
+            ),
+        ),
+        lambda: (
+            table("a", column("x"), column("y")),
+            table("a", column("x"), column("y"))._annotate({"orm": True}),
+            table("b", column("x"), column("y"))._annotate({"orm": True}),
+        ),
         lambda: (
             cast(column("q"), Integer),
             cast(column("q"), Float),
@@ -776,7 +795,27 @@ class CompareClausesTest(fixtures.TestBase):
 
         ne_(t1._generate_cache_key(), t2._generate_cache_key())
 
-        eq_(t1._generate_cache_key().key, (t1,))
+        eq_(t1._generate_cache_key().key, (t1, "_annotations", ()))
+
+    def test_compare_metadata_tables_annotations(self):
+        # metadata Table objects cache on their own identity, not their
+        # structure.   This is mainly to reduce the size of cache keys
+        # as well as reduce computational overhead, as Table objects have
+        # very large internal state and they are also generally global
+        # objects.
+
+        t1 = Table("a", MetaData(), Column("q", Integer), Column("p", Integer))
+        t2 = Table("a", MetaData(), Column("q", Integer), Column("p", Integer))
+
+        t1 = t1._annotate({"orm": True})
+        t2 = t2._annotate({"orm": True})
+
+        ne_(t1._generate_cache_key(), t2._generate_cache_key())
+
+        eq_(
+            t1._generate_cache_key().key,
+            (t1, "_annotations", (("orm", True),)),
+        )
 
     def test_compare_adhoc_tables(self):
         # non-metadata tables compare on their structure.  these objects are