Commits

Anonymous committed f37e365

[soc2009/multidb] A couple of cleanups of multi-db support for raw queries, including a using() call on raw query sets. Patch from Russell Keith-Magee.

Comments (0)

Files changed (6)

django/db/models/manager.py

         obj = copy.copy(self)
         obj._db = alias
         return obj
-    
+
     @property
     def db(self):
         return self._db or DEFAULT_DB_ALIAS
 
     def using(self, *args, **kwargs):
         return self.get_query_set().using(*args, **kwargs)
-    
+
     def exists(self, *args, **kwargs):
         return self.get_query_set().exists(*args, **kwargs)
 
     def _update(self, values, **kwargs):
         return self.get_query_set()._update(values, **kwargs)
 
-    def raw(self, query, params=None, *args, **kwargs):
-        kwargs["using"] = self.db
-        return RawQuerySet(model=self.model, query=query, params=params, *args, **kwargs)
+    def raw(self, raw_query, params=None, *args, **kwargs):
+        return RawQuerySet(raw_query=raw_query, model=self.model, params=params, using=self.db, *args, **kwargs)
 
 class ManagerDescriptor(object):
     # This class ensures managers aren't accessible via model instances.

django/db/models/query.py

             return False
     ordered = property(ordered)
 
+    @property
     def db(self):
         "Return the database that will be used if this query is executed now"
         return self._db or DEFAULT_DB_ALIAS
-    db = property(db)
 
     ###################
     # PRIVATE METHODS #
     Provides an iterator which converts the results of raw SQL queries into
     annotated model instances.
     """
-    def __init__(self, query, model=None, query_obj=None, params=None,
+    def __init__(self, raw_query, model=None, query=None, params=None,
         translations=None, using=None):
+        self.raw_query = raw_query
         self.model = model
-        self.using = using
-        self.query = query_obj or sql.RawQuery(sql=query, connection=connections[using], params=params)
+        self._db = using
+        self.query = query or sql.RawQuery(sql=raw_query, using=self.db, params=params)
         self.params = params or ()
         self.translations = translations or {}
 
             yield self.transform_results(row)
 
     def __repr__(self):
-        return "<RawQuerySet: %r>" % (self.query.sql % self.params)
+        return "<RawQuerySet: %r>" % (self.raw_query % self.params)
+
+    @property
+    def db(self):
+        "Return the database that will be used if this query is executed now"
+        return self._db or DEFAULT_DB_ALIAS
+
+    def using(self, alias):
+        """
+        Selects which database this Raw QuerySet should excecute it's query against.
+        """
+        return RawQuerySet(self.raw_query, model=self.model,
+                query=self.query.clone(using=alias),
+                params=self.params, translations=self.translations,
+                using=alias)
 
     @property
     def columns(self):
 
         for field, value in annotations:
             setattr(instance, field, value)
-        
-        instance._state.db = self.using
+
+        instance._state.db = self.query.using
 
         return instance
 

django/db/models/sql/query.py

     A single raw SQL query
     """
 
-    def __init__(self, sql, connection, params=None):
+    def __init__(self, sql, using, params=None):
         self.validate_sql(sql)
         self.params = params or ()
         self.sql = sql
-        self.connection = connection
+        self.using = using
         self.cursor = None
 
+    def clone(self, using):
+        return RawQuery(self.sql, using, params=self.params)
+
     def get_columns(self):
         if self.cursor is None:
             self._execute_query()
         return "<RawQuery: %r>" % (self.sql % self.params)
 
     def _execute_query(self):
-        self.cursor = self.connection.cursor()
+        self.cursor = connections[self.using].cursor()
         self.cursor.execute(self.sql, self.params)
 
 

docs/topics/db/sql.txt

 The ``raw()`` manager method can be used to perform raw SQL queries that
 return model instances:
 
-.. method:: Manager.raw(query, params=None, translations=None)
+.. method:: Manager.raw(raw_query, params=None, translations=None)
 
 This method method takes a raw SQL query, executes it, and returns model
 instances.

tests/modeltests/raw_query/tests.py

         """
         Execute the passed query against the passed model and check the output
         """
-        results = list(model.objects.raw(query=query, params=params, translations=translations))
+        results = list(model.objects.raw(query, params=params, translations=translations))
         self.assertProcessed(results, expected_results, expected_annotations)
         self.assertAnnotations(results, expected_annotations)
 
         query = "SELECT * FROM raw_query_author WHERE first_name = %s"
         author = Author.objects.all()[2]
         params = [author.first_name]
-        results = list(Author.objects.raw(query=query, params=params))
+        results = list(Author.objects.raw(query, params=params))
         self.assertProcessed(results, [author])
         self.assertNoAnnotations(results)
         self.assertEqual(len(results), 1)

tests/regressiontests/multiple_database/tests.py

 
         self.assertEquals(learn.get_next_by_published().title, "Dive into Python")
         self.assertEquals(dive.get_previous_by_published().title, "Learning Python")
-    
+
     def test_raw(self):
         "test the raw() method across databases"
         dive = Book.objects.using('other').create(title="Dive into Python",
         val = Book.objects.db_manager("other").raw('SELECT id FROM "multiple_database_book"')
         self.assertEqual(map(lambda o: o.pk, val), [dive.pk])
 
+        val = Book.objects.raw('SELECT id FROM "multiple_database_book"').using('other')
+        self.assertEqual(map(lambda o: o.pk, val), [dive.pk])
+
 
 class UserProfileTestCase(TestCase):
     def setUp(self):