[FIX] osv.query: improve support of chained explicit JOINs + corresponding tests
authorOlivier Dony <odo@openerp.com>
Fri, 1 Oct 2010 14:36:42 +0000 (16:36 +0200)
committerOlivier Dony <odo@openerp.com>
Fri, 1 Oct 2010 14:36:42 +0000 (16:36 +0200)
bzr revid: odo@openerp.com-20101001143642-z3ahichcj55csxib

bin/osv/query.py
bin/test/test_osv.py

index b04e536..5ba74e4 100644 (file)
@@ -99,13 +99,19 @@ class Query(object):
         """Returns (query_from, query_where, query_params)"""
         query_from = ''
         tables_to_process = list(self.tables)
+
+        def add_joins_for_table(table, query_from):
+            for (dest_table, lhs_col, col, join) in self.joins.get(table,[]):
+                tables_to_process.remove(dest_table)
+                query_from += ' %s %s ON (%s."%s" = %s."%s")' % \
+                    (join, dest_table, table, lhs_col, dest_table, col)
+                query_from = add_joins_for_table(dest_table, query_from)
+            return query_from
+
         for table in tables_to_process:
-            query_from += ' %s ' % table
+            query_from += table
             if table in self.joins:
-                for (dest_table, lhs_col, col, join) in self.joins[table]:
-                    tables_to_process.remove(dest_table)
-                    query_from += '%s %s ON (%s."%s" = %s."%s")' % \
-                        (join, dest_table, table, lhs_col, dest_table, col)
+                query_from = add_joins_for_table(table, query_from)
             query_from += ','
         query_from = query_from[:-1] # drop last comma
         return (query_from, " AND ".join(self.where_clause), self.where_clause_params)
index 170aa47..6e9f9c1 100644 (file)
@@ -31,10 +31,34 @@ class QueryTestCase(unittest.TestCase):
         query.join(("product_template", "product_category", "categ_id", "id"), outer=False) # add normal join
         query.join(("product_product", "res_user", "user_id", "id"), outer=True) # outer join
         self.assertEquals(query.get_sql()[0].strip(), 
-            """"product_product" LEFT JOIN "res_user" ON ("product_product"."user_id" = "res_user"."id"), "product_template" JOIN "product_category" ON ("product_template"."categ_id" = "product_category"."id") """.strip(), "Incorrect query")
-        self.assertEquals(query.get_sql()[1].strip(), """product_product.template_id = product_template.id""".strip(), "Incorrect where clause")
+            """"product_product" LEFT JOIN "res_user" ON ("product_product"."user_id" = "res_user"."id"),"product_template" JOIN "product_category" ON ("product_template"."categ_id" = "product_category"."id") """.strip())
+        self.assertEquals(query.get_sql()[1].strip(), """product_product.template_id = product_template.id""".strip())
+
+    def test_query_chained_explicit_joins(self):
+        query = Query()
+        query.tables.extend(['"product_product"','"product_template"'])
+        query.where_clause.append("product_product.template_id = product_template.id")
+        query.join(("product_template", "product_category", "categ_id", "id"), outer=False) # add normal join
+        query.join(("product_category", "res_user", "user_id", "id"), outer=True) # CHAINED outer join
+        self.assertEquals(query.get_sql()[0].strip(), 
+            """"product_product","product_template" JOIN "product_category" ON ("product_template"."categ_id" = "product_category"."id") LEFT JOIN "res_user" ON ("product_category"."user_id" = "res_user"."id")""".strip())
+        self.assertEquals(query.get_sql()[1].strip(), """product_product.template_id = product_template.id""".strip())
+
+    def test_mixed_query_chained_explicit_implicit_joins(self):
+        query = Query()
+        query.tables.extend(['"product_product"','"product_template"'])
+        query.where_clause.append("product_product.template_id = product_template.id")
+        query.join(("product_template", "product_category", "categ_id", "id"), outer=False) # add normal join
+        query.join(("product_category", "res_user", "user_id", "id"), outer=True) # CHAINED outer join
+        query.tables.append('"account.account"')
+        query.where_clause.append("product_category.expense_account_id = account_account.id") # additional implicit join 
+        self.assertEquals(query.get_sql()[0].strip(), 
+            """"product_product","product_template" JOIN "product_category" ON ("product_template"."categ_id" = "product_category"."id") LEFT JOIN "res_user" ON ("product_category"."user_id" = "res_user"."id"),"account.account" """.strip())
+        self.assertEquals(query.get_sql()[1].strip(), """product_product.template_id = product_template.id AND product_category.expense_account_id = account_account.id""".strip())
+
 
     def test_raise_missing_lhs(self):
         query = Query()
         query.tables.append('"product_product"')
-        self.assertRaises(AssertionError, query.join, ("product_template", "product_category", "categ_id", "id"), outer=False)
\ No newline at end of file
+        self.assertRaises(AssertionError, query.join, ("product_template", "product_category", "categ_id", "id"), outer=False)
+