]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
getting things to join without subqueries, but some glitches in the compiler step
authorMike Bayer <mike_mp@zzzcomputing.com>
Sun, 2 Jun 2013 23:33:19 +0000 (19:33 -0400)
committerMike Bayer <mike_mp@zzzcomputing.com>
Sun, 2 Jun 2013 23:33:19 +0000 (19:33 -0400)
when we do query.count() are showing

lib/sqlalchemy/orm/query.py
lib/sqlalchemy/sql/compiler.py
lib/sqlalchemy/sql/expression.py
lib/sqlalchemy/sql/util.py
test/orm/inheritance/test_polymorphic_rel.py
test/orm/test_of_type.py

index beae7aba0b3d317e4f236b3717fc6312c094ec85..25ffb0127e5bd6ab8d84de5c5f4ec49415e58c31 100644 (file)
@@ -1862,19 +1862,20 @@ class Query(object):
                     (right_selectable.description,
                     right_mapper.mapped_table.description))
 
-            if not isinstance(right_selectable, expression.Alias):
-                right_selectable = right_selectable.alias()
+            if not isinstance(right_selectable, expression.Join):
+                if not isinstance(right_selectable, expression.Alias):
+                    right_selectable = right_selectable.alias()
 
+                need_adapter = True
             right = aliased(right_mapper, right_selectable)
-            need_adapter = True
 
         aliased_entity = right_mapper and \
                             not right_is_aliased and \
                             (
-                                right_mapper.with_polymorphic or
-                                isinstance(
-                                    right_mapper.mapped_table,
-                                    expression.Join)
+                                right_mapper.with_polymorphic
+                                #isinstance(
+                                #    right_mapper.mapped_table,
+                                #    expression.Join)
                             )
 
         if not need_adapter and (create_aliases or aliased_entity):
@@ -1946,7 +1947,6 @@ class Query(object):
             clause = left_selectable
 
         assert clause is not None
-
         try:
             clause = orm_join(clause, right, onclause, isouter=outerjoin)
         except sa_exc.ArgumentError as ae:
index 030d6dce93a651e0481584053dea4976f83cb4d0..27e883c8619c6bce556b52c3a3e2fb0ae0589bd7 100644 (file)
@@ -1095,14 +1095,19 @@ class SQLCompiler(engine.Compiled):
                     c._label = c._key_label = c.name
 
                 elem.right = selectable
-                adapters.append(
-                        sql_util.ClauseAdapter(selectable,
+                import pdb
+                pdb.set_trace()
+                adapter = sql_util.ClauseAdapter(selectable,
                                         traverse_options=traverse_options)
-                )
+                adapter.__traverse_options__.pop('stop_on')
+                adapters.append(adapter)
 
         select = visitors.cloned_traverse(select,
                                     traverse_options, {"join": visit_join})
 
+        if adapters:
+            import pdb
+            pdb.set_trace()
         for adap in reversed(adapters):
             select = adap.traverse(select)
         return select
index 5820cb10610760cc2dce9ea8453f294489da0cde..edab9e2901274546d3fad34207f525e44fbada8e 100644 (file)
@@ -4212,10 +4212,10 @@ class FromGrouping(FromClause):
 
     @property
     def foreign_keys(self):
-        # this could be
-        # self.element.foreign_keys
-        # see SelectableTest.test_join_condition
-        return set()
+        return self.element.foreign_keys
+
+    def is_derived_from(self, element):
+        return self.element.is_derived_from(element)
 
     @property
     def _hide_froms(self):
index ffa07d3df5fcc875687156e521ed77fa8e72ec20..6a267752e9e5bc3fbf7255ea7d6da023547fe302 100644 (file)
@@ -833,6 +833,7 @@ class ClauseAdapter(visitors.ReplacingCloningVisitor):
         return newcol
 
     def replace(self, col):
+        print "COL!", col
         if isinstance(col, expression.FromClause) and \
             self.selectable.is_derived_from(col):
             return self.selectable
index 8c1f22114ffd39b60a0a29690bad534ac14d17c1..eecfb036b889e81674b9980484de156f7e64bce2 100644 (file)
@@ -37,6 +37,7 @@ class _PolymorphicTestBase(object):
         e1, e2, e3, b1, m1 = \
             cls.e1, cls.e2, cls.e3, cls.b1, cls.m1
 
+
     def test_loads_at_once(self):
         """
         Test that all objects load from the full query, when
@@ -672,7 +673,17 @@ class _PolymorphicTestBase(object):
               expected)
         self.assert_sql_count(testing.db, go, 1)
 
+    def test_subqueryload_on_subclass(self):
         sess = create_session()
+        expected = [
+            Engineer(
+                name="dilbert",
+                engineer_name="dilbert",
+                primary_language="java",
+                status="regular engineer",
+                machines=[
+                    Machine(name="IBM ThinkPad"),
+                    Machine(name="IPhone")])]
         def go():
             # test load People with subqueryload to engineers + machines
             eq_(sess.query(Person)
@@ -726,6 +737,14 @@ class _PolymorphicTestBase(object):
                 .join(Engineer.machines).all(),
             [c1, c2])
 
+    def test_join_to_subclass_six_point_five(self):
+        sess = create_session()
+        eq_(sess.query(Company)
+                .join(people.join(engineers), 'employees')
+                .join(Engineer.machines)
+                .filter(Engineer.name == 'dilbert').all(),
+            [c1])
+
     def test_join_to_subclass_seven(self):
         sess = create_session()
         eq_(sess.query(Company)
@@ -898,7 +917,8 @@ class _PolymorphicTestBase(object):
                 .filter(Paperwork.description.like('%#%')).all(),
             [c1, c2])
 
-    def test_explicit_polymorphic_join(self):
+
+    def test_explicit_polymorphic_join_one(self):
         sess = create_session()
 
         # join from Company to Engineer; join condition formulated by
@@ -910,6 +930,9 @@ class _PolymorphicTestBase(object):
                 .filter(Engineer.engineer_name == 'vlad').one(),
             c2)
 
+    def test_explicit_polymorphic_join_two(self):
+        sess = create_session()
+
         # same, using explicit join condition.  Query.join() must
         # adapt the on clause here to match the subquery wrapped around
         # "people join engineers".
index 17ffebc3d8fcc037c2c8ef15587c35c5922d88ca..150673560504155c7fcb4568f0a08bff53c9fef6 100644 (file)
@@ -69,12 +69,16 @@ class _PolymorphicTestBase(object):
                 .filter(Engineer.primary_language == 'java').count(),
             1)
 
+    def test_join_to_subclass_four(self):
+        sess = Session()
         # test [ticket:2093]
         eq_(sess.query(Company.company_id, Engineer)
                 .join(Company.employees.of_type(Engineer))
                 .filter(Engineer.primary_language == 'java').count(),
             1)
 
+    def test_join_to_subclass_five(self):
+        sess = Session()
         eq_(sess.query(Company)
                 .join(Company.employees.of_type(Engineer))
                 .filter(Engineer.primary_language == 'java').count(),
@@ -185,6 +189,7 @@ class _PolymorphicTestBase(object):
             )
         self.assert_sql_count(testing.db, go, 3)
 
+
 class PolymorphicPolymorphicTest(_PolymorphicTestBase, _PolymorphicPolymorphic):
     def _polymorphic_join_target(self, cls):
         from sqlalchemy.orm import class_mapper
@@ -524,11 +529,8 @@ class SubclassRelationshipTest(testing.AssertsCompiledSQL, fixtures.DeclarativeM
         self.assert_compile(q,
             "SELECT data_container.id AS data_container_id, "
             "data_container.name AS data_container_name "
-            "FROM data_container JOIN (SELECT job.id AS job_id, "
-            "job.type AS job_type, job.container_id AS job_container_id, "
-            "subjob.id AS subjob_id, subjob.attr AS subjob_attr "
-            "FROM job JOIN subjob ON job.id = subjob.id) AS anon_1 "
-            "ON data_container.id = anon_1.job_container_id"
+            "FROM data_container JOIN (job JOIN subjob ON job.id = subjob.id) "
+            "ON data_container.id = job.container_id"
         )
 
     def test_join_wpoly_innerjoin(self):