diff -ruw Django-1.2.1.orig/django/db/models/query.py Django-1.2.1/django/db/models/query.py
--- Django-1.2.1.orig/django/db/models/query.py	2010-04-30 09:32:48.000000000 -0700
+++ Django-1.2.1/django/db/models/query.py	2010-05-25 21:14:52.000000000 -0700
@@ -653,14 +653,14 @@
         return obj
 
     def extra(self, select=None, where=None, params=None, tables=None,
-              order_by=None, select_params=None):
+              order_by=None, select_params=None, join=None):
         """
         Adds extra SQL fragments to the query.
         """
         assert self.query.can_filter(), \
                 "Cannot change a query once a slice has been taken"
         clone = self._clone()
-        clone.query.add_extra(select, select_params, where, params, tables, order_by)
+        clone.query.add_extra(select, select_params, where, params, tables, order_by, join)
         return clone
 
     def reverse(self):
diff -ruw Django-1.2.1.orig/django/db/models/sql/compiler.py Django-1.2.1/django/db/models/sql/compiler.py
--- Django-1.2.1.orig/django/db/models/sql/compiler.py	2010-04-23 07:25:29.000000000 -0700
+++ Django-1.2.1/django/db/models/sql/compiler.py	2010-05-25 21:14:52.000000000 -0700
@@ -77,6 +77,9 @@
         result.extend(from_)
         params.extend(f_params)
 
+        if self.query.extra_join:
+            result.append(' '.join(self.query.extra_join))
+
         if where:
             result.append('WHERE %s' % where)
             params.extend(w_params)
diff -ruw Django-1.2.1.orig/django/db/models/sql/query.py Django-1.2.1/django/db/models/sql/query.py
--- Django-1.2.1.orig/django/db/models/sql/query.py	2010-04-30 09:32:48.000000000 -0700
+++ Django-1.2.1/django/db/models/sql/query.py	2010-05-25 21:14:52.000000000 -0700
@@ -151,6 +151,7 @@
 
         self.extra_tables = ()
         self.extra_order_by = ()
+        self.extra_join = ()
 
         # A tuple that is a set of model field names and either True, if these
         # are the fields to defer, or False if these are the only fields to
@@ -284,6 +285,7 @@
             obj._extra_select_cache = self._extra_select_cache.copy()
         obj.extra_tables = self.extra_tables
         obj.extra_order_by = self.extra_order_by
+        obj.extra_join = self.extra_join
         obj.deferred_loading = deepcopy(self.deferred_loading, memo=memo)
         if self.filter_is_sticky and self.used_aliases:
             obj.used_aliases = self.used_aliases.copy()
@@ -404,7 +406,7 @@
 
     def has_results(self, using):
         q = self.clone()
-        q.add_extra({'a': 1}, None, None, None, None, None)
+        q.add_extra({'a': 1}, None, None, None, None, None, None)
         q.select = []
         q.select_fields = []
         q.default_cols = False
@@ -1609,7 +1611,7 @@
         self.related_select_cols = []
         self.related_select_fields = []
 
-    def add_extra(self, select, select_params, where, params, tables, order_by):
+    def add_extra(self, select, select_params, where, params, tables, order_by, join):
         """
         Adds data to the various extra_* attributes for user-created additions
         to the query.
@@ -1640,6 +1642,8 @@
             self.extra_tables += tuple(tables)
         if order_by:
             self.extra_order_by = order_by
+        if join:
+            self.extra_join += tuple(join)
 
     def clear_deferred_loading(self):
         """
