Author: russellm
Date: 2010-04-01 11:48:16 -0500 (Thu, 01 Apr 2010)
New Revision: 12904

Added:
   django/trunk/tests/modeltests/raw_query/fixtures/raw_query_books.json
Removed:
   django/trunk/tests/modeltests/raw_query/fixtures/initial_data.json
Modified:
   django/trunk/django/db/models/query.py
   django/trunk/django/db/models/sql/compiler.py
   django/trunk/django/db/models/sql/query.py
   django/trunk/tests/modeltests/raw_query/models.py
   django/trunk/tests/modeltests/raw_query/tests.py
Log:
Fixed #12429 -- Ensure that raw queries call resolve_columns if the backend 
defines it. This ensures (as much as possible) that the model values returned 
by a raw query match that in normal queries. Thanks to Ian Kelly for the report.

Modified: django/trunk/django/db/models/query.py
===================================================================
--- django/trunk/django/db/models/query.py      2010-04-01 15:29:58 UTC (rev 
12903)
+++ django/trunk/django/db/models/query.py      2010-04-01 16:48:16 UTC (rev 
12904)
@@ -1407,20 +1407,27 @@
             self._model_fields = {}
             for field in self.model._meta.fields:
                 name, column = field.get_attname_column()
-                self._model_fields[converter(column)] = name
+                self._model_fields[converter(column)] = field
         return self._model_fields
 
     def transform_results(self, values):
         model_init_kwargs = {}
         annotations = ()
 
+        # Perform database backend type resolution
+        connection = connections[self.db]
+        compiler = connection.ops.compiler('SQLCompiler')(self.query, 
connection, self.db)
+        if hasattr(compiler, 'resolve_columns'):
+            fields = [self.model_fields.get(c,None) for c in self.columns]
+            values = compiler.resolve_columns(values, fields)
+
         # Associate fields to values
         for pos, value in enumerate(values):
             column = self.columns[pos]
 
             # Separate properties from annotations
             if column in self.model_fields.keys():
-                model_init_kwargs[self.model_fields[column]] = value
+                model_init_kwargs[self.model_fields[column].attname] = value
             else:
                 annotations += (column, value),
 

Modified: django/trunk/django/db/models/sql/compiler.py
===================================================================
--- django/trunk/django/db/models/sql/compiler.py       2010-04-01 15:29:58 UTC 
(rev 12903)
+++ django/trunk/django/db/models/sql/compiler.py       2010-04-01 16:48:16 UTC 
(rev 12904)
@@ -14,10 +14,6 @@
         self.using = using
         self.quote_cache = {}
 
-        # Check that the compiler will be able to execute the query
-        for alias, aggregate in self.query.aggregate_select.items():
-            self.connection.ops.check_aggregate_support(aggregate)
-
     def pre_sql_setup(self):
         """
         Does any necessary class setup immediately prior to producing SQL. This

Modified: django/trunk/django/db/models/sql/query.py
===================================================================
--- django/trunk/django/db/models/sql/query.py  2010-04-01 15:29:58 UTC (rev 
12903)
+++ django/trunk/django/db/models/sql/query.py  2010-04-01 16:48:16 UTC (rev 
12904)
@@ -189,6 +189,11 @@
             raise ValueError("Need either using or connection")
         if using:
             connection = connections[using]
+
+        # Check that the compiler will be able to execute the query
+        for alias, aggregate in self.aggregate_select.items():
+            connection.ops.check_aggregate_support(aggregate)
+
         return connection.ops.compiler(self.compiler)(self, connection, using)
 
     def get_meta(self):

Deleted: django/trunk/tests/modeltests/raw_query/fixtures/initial_data.json
===================================================================
--- django/trunk/tests/modeltests/raw_query/fixtures/initial_data.json  
2010-04-01 15:29:58 UTC (rev 12903)
+++ django/trunk/tests/modeltests/raw_query/fixtures/initial_data.json  
2010-04-01 16:48:16 UTC (rev 12904)
@@ -1,102 +0,0 @@
-[
-    {
-        "pk": 1,
-        "model": "raw_query.author",
-        "fields": {
-            "dob": "1950-09-20",
-            "first_name": "Joe",
-            "last_name": "Smith"
-        }
-    },
-    {
-        "pk": 2,
-        "model": "raw_query.author",
-        "fields": {
-            "dob": "1920-04-02",
-            "first_name": "Jill",
-            "last_name": "Doe"
-        }
-    },
-    {
-        "pk": 3,
-        "model": "raw_query.author",
-        "fields": {
-            "dob": "1986-01-25",
-            "first_name": "Bob",
-            "last_name": "Smith"
-        }
-    },
-    {
-        "pk": 4,
-        "model": "raw_query.author",
-        "fields": {
-            "dob": "1932-05-10",
-            "first_name": "Bill",
-            "last_name": "Jones"
-        }
-    },
-    {
-        "pk": 1,
-        "model": "raw_query.book",
-        "fields": {
-            "author": 1,
-            "title": "The awesome book"
-        }
-    },
-    {
-        "pk": 2,
-        "model": "raw_query.book",
-        "fields": {
-            "author": 1,
-            "title": "The horrible book"
-        }
-    },
-    {
-        "pk": 3,
-        "model": "raw_query.book",
-        "fields": {
-            "author": 1,
-            "title": "Another awesome book"
-        }
-    },
-    {
-        "pk": 4,
-        "model": "raw_query.book",
-        "fields": {
-            "author": 3,
-            "title": "Some other book"
-        }
-    },
-    {
-        "pk": 1,
-        "model": "raw_query.coffee",
-        "fields": {
-            "brand": "dunkin doughnuts"
-        }
-    },
-    {
-        "pk": 2,
-        "model": "raw_query.coffee",
-        "fields": {
-            "brand": "starbucks"
-        }
-    },
-    {
-        "pk": 1,
-        "model": "raw_query.reviewer",
-        "fields": {
-            "reviewed": [
-                2,
-                3,
-                4
-            ]
-        }
-    },
-    {
-        "pk": 2,
-        "model": "raw_query.reviewer",
-        "fields": {
-            "reviewed": []
-        }
-    }
-]

Copied: django/trunk/tests/modeltests/raw_query/fixtures/raw_query_books.json 
(from rev 12903, 
django/trunk/tests/modeltests/raw_query/fixtures/initial_data.json)
===================================================================
--- django/trunk/tests/modeltests/raw_query/fixtures/raw_query_books.json       
                        (rev 0)
+++ django/trunk/tests/modeltests/raw_query/fixtures/raw_query_books.json       
2010-04-01 16:48:16 UTC (rev 12904)
@@ -0,0 +1,110 @@
+[
+    {
+        "pk": 1,
+        "model": "raw_query.author",
+        "fields": {
+            "dob": "1950-09-20",
+            "first_name": "Joe",
+            "last_name": "Smith"
+        }
+    },
+    {
+        "pk": 2,
+        "model": "raw_query.author",
+        "fields": {
+            "dob": "1920-04-02",
+            "first_name": "Jill",
+            "last_name": "Doe"
+        }
+    },
+    {
+        "pk": 3,
+        "model": "raw_query.author",
+        "fields": {
+            "dob": "1986-01-25",
+            "first_name": "Bob",
+            "last_name": "Smith"
+        }
+    },
+    {
+        "pk": 4,
+        "model": "raw_query.author",
+        "fields": {
+            "dob": "1932-05-10",
+            "first_name": "Bill",
+            "last_name": "Jones"
+        }
+    },
+    {
+        "pk": 1,
+        "model": "raw_query.book",
+        "fields": {
+            "author": 1,
+            "title": "The awesome book",
+            "paperback": false,
+            "opening_line": "It was a bright cold day in April and the clocks 
were striking thirteen."
+        }
+    },
+    {
+        "pk": 2,
+        "model": "raw_query.book",
+        "fields": {
+            "author": 1,
+            "title": "The horrible book",
+            "paperback": true,
+            "opening_line": "On an evening in the latter part of May a 
middle-aged man was walking homeward from Shaston to the village of Marlott, in 
the adjoining Vale of Blakemore, or Blackmoor."
+        }
+    },
+    {
+        "pk": 3,
+        "model": "raw_query.book",
+        "fields": {
+            "author": 1,
+            "title": "Another awesome book",
+            "paperback": false,
+            "opening_line": "A squat grey building of only thirty-four 
stories."
+        }
+    },
+    {
+        "pk": 4,
+        "model": "raw_query.book",
+        "fields": {
+            "author": 3,
+            "title": "Some other book",
+            "paperback": true,
+            "opening_line": "It was the day my grandmother exploded."
+        }
+    },
+    {
+        "pk": 1,
+        "model": "raw_query.coffee",
+        "fields": {
+            "brand": "dunkin doughnuts"
+        }
+    },
+    {
+        "pk": 2,
+        "model": "raw_query.coffee",
+        "fields": {
+            "brand": "starbucks"
+        }
+    },
+    {
+        "pk": 1,
+        "model": "raw_query.reviewer",
+        "fields": {
+            "reviewed": [
+                2,
+                3,
+                4
+            ]
+        }
+    },
+    {
+        "pk": 2,
+        "model": "raw_query.reviewer",
+        "fields": {
+            "reviewed": []
+        }
+    }
+]

Modified: django/trunk/tests/modeltests/raw_query/models.py
===================================================================
--- django/trunk/tests/modeltests/raw_query/models.py   2010-04-01 15:29:58 UTC 
(rev 12903)
+++ django/trunk/tests/modeltests/raw_query/models.py   2010-04-01 16:48:16 UTC 
(rev 12904)
@@ -17,6 +17,8 @@
 class Book(models.Model):
     title = models.CharField(max_length=255)
     author = models.ForeignKey(Author)
+    paperback = models.BooleanField()
+    opening_line = models.TextField()
 
 class Coffee(models.Model):
     brand = models.CharField(max_length=255, db_column="name")

Modified: django/trunk/tests/modeltests/raw_query/tests.py
===================================================================
--- django/trunk/tests/modeltests/raw_query/tests.py    2010-04-01 15:29:58 UTC 
(rev 12903)
+++ django/trunk/tests/modeltests/raw_query/tests.py    2010-04-01 16:48:16 UTC 
(rev 12904)
@@ -7,6 +7,7 @@
 
 
 class RawQueryTests(TestCase):
+    fixtures = ['raw_query_books.json']
 
     def assertSuccessfulRawQuery(self, model, query, expected_results,
             expected_annotations=(), params=[], translations=None):
@@ -14,10 +15,10 @@
         Execute the passed query against the passed model and check the output
         """
         results = list(model.objects.raw(query, params=params, 
translations=translations))
-        self.assertProcessed(results, expected_results, expected_annotations)
+        self.assertProcessed(model, results, expected_results, 
expected_annotations)
         self.assertAnnotations(results, expected_annotations)
 
-    def assertProcessed(self, results, orig, expected_annotations=()):
+    def assertProcessed(self, model, results, orig, expected_annotations=()):
         """
         Compare the results of a raw query against expected results
         """
@@ -27,7 +28,13 @@
             for annotation in expected_annotations:
                 setattr(orig_item, *annotation)
 
-            self.assertEqual(item.id, orig_item.id)
+            for field in model._meta.fields:
+                # Check that all values on the model are equal
+                self.assertEquals(getattr(item,field.attname),
+                                  getattr(orig_item,field.attname))
+                # This includes checking that they are the same type
+                self.assertEquals(type(getattr(item,field.attname)),
+                                  type(getattr(orig_item,field.attname)))
 
     def assertNoAnnotations(self, results):
         """
@@ -115,7 +122,7 @@
         author = Author.objects.all()[2]
         params = [author.first_name]
         results = list(Author.objects.raw(query, params=params))
-        self.assertProcessed(results, [author])
+        self.assertProcessed(Author, results, [author])
         self.assertNoAnnotations(results)
         self.assertEqual(len(results), 1)
 

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/django-updates?hl=en.

Reply via email to