]> git.parisson.com Git - django-postman.git/commitdiff
fix query to speedup filters
authorGuillaume Pellerin <yomguy@parisson.com>
Mon, 22 Apr 2013 15:21:44 +0000 (17:21 +0200)
committerGuillaume Pellerin <yomguy@parisson.com>
Mon, 22 Apr 2013 15:21:44 +0000 (17:21 +0200)
postman/models.py

index 9da2e282c9033a5132f141c200249c508016ab6e..9bef0d8ffa403df8a713cc93964c7a1e829ee7ba 100644 (file)
@@ -8,6 +8,7 @@ except ImportError:
     from postman.future_1_5 import get_user_model
 from django.core.exceptions import ValidationError
 from django.db import models
+from django.db.models.query import QuerySet
 try:
     from django.utils.text import Truncator  # Django 1.4
 except ImportError:
@@ -19,6 +20,7 @@ except ImportError:
     from datetime import datetime
     now = datetime.now
 
+from postman.query import PostmanQuery
 from postman.urls import OPTION_MESSAGES
 from postman.utils import email_visitor, notify_user
 
@@ -41,8 +43,8 @@ ORDER_BY_FIELDS = {
 }
 ORDER_BY_MAPPER = {'sender': 'f', 'recipient': 't', 'subject': 's', 'date': 'd'}  # for templatetags usage
 
-dbms = settings.DATABASES['default']['ENGINE'].rsplit('.', 1)[-1]
-QUOTE_CHAR = '`' if dbms == 'mysql' else '"'
+dbms = settings.DATABASES['default']['ENGINE'].rsplit('.', 1)[-1]
+QUOTE_CHAR = '`' if dbms == 'mysql' else '"'
 
 
 def get_order_by(query_dict):
@@ -80,22 +82,22 @@ def get_user_representation(user):
             pass
     return unicode(user)  # default value, or in case of empty attribute or exception
 
-
+# import logging
+# logging.getLogger('django.db.backends').setLevel(logging.DEBUG)
 class MessageManager(models.Manager):
     """The manager for Message."""
 
-    @property
-    def _last_in_thread(self):
-        """Return the latest message id for each conversation."""
-        return self.filter(thread__isnull=False).values('thread').annotate(models.Max('pk'))\
-            .values_list('pk__max', flat=True).order_by()
+    @property
+    def _last_in_thread(self):
+        """Return the latest message id for each conversation."""
+        return self.filter(thread__isnull=False).values('thread').annotate(models.Max('pk'))\
+            .values_list('pk__max', flat=True).order_by()
 
     def _folder(self, related, filters, option=None, order_by=None):
         """Base code, in common to the folders."""
+        qs = self.all() if option == OPTION_MESSAGES else QuerySet(self.model, PostmanQuery(self.model), using=self._db)
         if related:
-            qs = self.select_related(*related)
-        else:
-            qs = self.all()
+            qs = qs.select_related(*related)
         if order_by:
             qs = qs.order_by(order_by)
         if isinstance(filters, (list, tuple)):
@@ -110,12 +112,25 @@ class MessageManager(models.Manager):
             # should not be necessary. Otherwise add:
             # .extra(select={'count': 'SELECT 1'})
         else:
-            return qs.filter(
-                models.Q(id__in=self._last_in_thread.filter(lookups)) | models.Q(lookups, thread__isnull=True)
-            ).extra(select={'count': QUOTE_CHAR.join([
-            'SELECT COUNT(*) FROM ', 'postman_message', ' T'
-            ' WHERE T.', 'thread_id', ' = ', 'postman_message', '.', 'thread_id', ' '
-            ])})
+            qs = qs.extra(select={'count': '{0}.count'.format(qs.query.pm_alias_prefix)})
+            qs.query.pm_set_extra(table=(
+                self.filter(lookups, thread_id__isnull=True).extra(select={'count': 0})\
+                    .values_list('id', 'count').order_by(),
+                self.filter(lookups, thread_id__isnull=False).values('thread').annotate(id=models.Max('pk'), count=models.Count('pk'))\
+                    .values_list('id', 'count').order_by(),
+            ))
+            return qs
+            # from rqs import PostmanRawQuery, PostmanRawQuerySet
+            # raw_query = 'select *, 12 as count from postman_message'
+            # query = PostmanRawQuery(sql=raw_query, using=Message.objects.db)
+            # rqs = PostmanRawQuerySet(raw_query=raw_query, model=Message, query=query)
+            # return rqs
+            # return qs.filter(
+                # models.Q(id__in=self._last_in_thread.filter(lookups)) | models.Q(lookups, thread__isnull=True)
+            # ).extra(select={'count': QUOTE_CHAR.join([
+            # 'SELECT COUNT(*) FROM ', 'postman_message', ' T'
+            # ' WHERE T.', 'thread_id', ' = ', 'postman_message', '.', 'thread_id', ' '
+            # ])})
             # For single message, 'count' is returned as 0. Should be acceptable if known.
             # If not, replace "COUNT(*)" by "1+COUNT(*)" and add:
             # ' AND T."id" <> T."thread_id"'