Mike Bayer avatar Mike Bayer committed e495630

- reopened #2453, needed to put in the original patch as well to cover the case
of column_property() objs building off each other

Comments (0)

Files changed (2)

lib/sqlalchemy/sql/expression.py

 
         toremove = set(itertools.chain(*[f._hide_froms for f in froms]))
         if toremove:
+            # if we're maintaining clones of froms,
+            # add the copies out to the toremove list
+            if self._from_cloned:
+                toremove.update(
+                    self._from_cloned[f] for f in 
+                    toremove.intersection(self._from_cloned)
+                )
+            # filter out to FROM clauses not in the list,
+            # using a list to maintain ordering
             froms = [f for f in froms if f not in toremove]
 
         if len(froms) > 1 or self._correlate:

test/sql/test_selectable.py

 
     def test_annotate_unique_traversal(self):
         """test that items are copied only once during
-        annotate, deannotate traversal"""
+        annotate, deannotate traversal
+
+        #2453
+        """
         table1 = table('table1', column('x'))
-        table2 = table('table1', column('y'))
+        table2 = table('table2', column('y'))
         a1 = table1.alias()
         s = select([a1.c.x]).select_from(
                 a1.join(table2, a1.c.x==table2.c.y)
             assert sel._froms[0] is sel._froms[1].left
             eq_(str(s), str(sel))
 
+    def test_annotate_fromlist_preservation(self):
+        """test the FROM list in select still works
+        even when multiple annotate runs have created
+        copies of the same selectable
+
+        #2453, continued
+
+        """
+        table1 = table('table1', column('x'))
+        table2 = table('table2', column('y'))
+        a1 = table1.alias()
+        s = select([a1.c.x]).select_from(
+                a1.join(table2, a1.c.x==table2.c.y)
+            )
+
+        assert_s = select([select([s])])
+        for fn in (
+            sql_util._deep_deannotate,
+            lambda s: sql_util._deep_annotate(s, {'foo':'bar'}),
+            lambda s:visitors.cloned_traverse(s, {}, {}),
+            lambda s:visitors.replacement_traverse(s, {}, lambda x:None)
+        ):
+
+            sel = fn(select([fn(select([fn(s)]))]))
+            eq_(str(assert_s), str(sel))
+
+
     def test_bind_unique_test(self):
         t1 = table('t', column('a'), column('b'))
 
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.