Index: django/db/__init__.py
===================================================================
--- django/db/__init__.py	(revision 6979)
+++ django/db/__init__.py	(working copy)
@@ -1,6 +1,6 @@
 import os
 from django.conf import settings
-from django.core import signals
+from django.core import signals as core_signals
 from django.core.exceptions import ImproperlyConfigured
 from django.dispatch import dispatcher
 from django.utils.functional import curry
@@ -54,17 +54,17 @@
 
 # Register an event that closes the database connection
 # when a Django request is finished.
-dispatcher.connect(connection.close, signal=signals.request_finished)
+dispatcher.connect(connection.close, signal=core_signals.request_finished)
 
 # Register an event that resets connection.queries
 # when a Django request is started.
 def reset_queries():
     connection.queries = []
-dispatcher.connect(reset_queries, signal=signals.request_started)
+dispatcher.connect(reset_queries, signal=core_signals.request_started)
 
 # Register an event that rolls back the connection
 # when a Django request has an exception.
 def _rollback_on_exception():
     from django.db import transaction
     transaction.rollback_unless_managed()
-dispatcher.connect(_rollback_on_exception, signal=signals.got_request_exception)
+dispatcher.connect(_rollback_on_exception, signal=core_signals.got_request_exception)
Index: django/db/signals.py
===================================================================
--- django/db/signals.py	(revision 0)
+++ django/db/signals.py	(revision 0)
@@ -0,0 +1 @@
+query_execute = object()
Index: django/db/backends/util.py
===================================================================
--- django/db/backends/util.py	(revision 6979)
+++ django/db/backends/util.py	(working copy)
@@ -1,4 +1,6 @@
 import datetime
+from django.db import signals
+from django.dispatch import dispatcher
 import md5
 from time import time
 
@@ -41,6 +43,43 @@
         else:
             return getattr(self.cursor, attr)
 
+    def __iter__(self):
+        return iter(self.cursor)
+
+
+class CursorSignalWrapper(object):
+    def __init__(self, cursor, db):
+        self.cursor = cursor
+        self.db = db # Instance of a BaseDatabaseWrapper subclass
+
+    def execute(self, sql, params=()):
+        start = time()
+        try:
+            return self.cursor.execute(sql, params)
+        finally:
+            stop = time()
+            dispatcher.send(signal=signals.query_execute, sender=self, sql=sql, params=params, time=stop-start)
+
+    def executemany(self, sql, param_list):
+        start = time()
+        try:
+            return self.cursor.executemany(sql, param_list)
+        finally:
+            stop = time()
+            # XXX: Should this be a special signal that only gets called once for efficiency?
+            for params in param_list:
+                dispatcher.send(signal=signals.query_execute, sender=self, sql=sql, params=params, time=stop-start)
+
+    def __getattr__(self, attr):
+        if attr in self.__dict__:
+            return self.__dict__[attr]
+        else:
+            return getattr(self.cursor, attr)
+
+    def __iter__(self):
+        return iter(self.cursor)
+
+
 ###############################################
 # Converters from database (string) to Python #
 ###############################################
Index: django/db/backends/__init__.py
===================================================================
--- django/db/backends/__init__.py	(revision 6979)
+++ django/db/backends/__init__.py	(working copy)
@@ -14,6 +14,7 @@
         self.connection = None
         self.queries = []
         self.options = kwargs
+        self.use_signal_cursor = None
 
     def _commit(self):
         if self.connection is not None:
@@ -32,13 +33,20 @@
         from django.conf import settings
         cursor = self._cursor(settings)
         if settings.DEBUG:
-            return self.make_debug_cursor(cursor)
+            return self.make_signal_cursor(self.make_debug_cursor(cursor))
+        elif self.use_signal_cursor:
+            return self.make_signal_cursor(cursor)
         return cursor
 
     def make_debug_cursor(self, cursor):
         from django.db.backends import util
         return util.CursorDebugWrapper(cursor, self)
+    
+    def make_signal_cursor(self, cursor):
+        from django.db.backends import util
+        return util.CursorSignalWrapper(cursor, self)
 
+
 class BaseDatabaseFeatures(object):
     allows_group_by_ordinal = True
     allows_unique_and_pk = True
Index: tests/modeltests/select_related/models.py
===================================================================
--- tests/modeltests/select_related/models.py	(revision 6979)
+++ tests/modeltests/select_related/models.py	(working copy)
@@ -7,7 +7,8 @@
 the select-related behavior will traverse.
 """
 
-from django.db import models
+from django.db import models, signals
+from django.dispatch import dispatcher
 
 # Who remembers high school biology?
 
@@ -75,6 +76,22 @@
         obj.save()
         parent = obj
 
+class QueryCounter(object):
+    counter = 0
+
+    @staticmethod
+    def add():
+        QueryCounter.counter += 1
+        
+    @staticmethod
+    def clear():
+        QueryCounter.counter = 0
+
+
+def track_query(sender, *args, **kwargs):
+    QueryCounter.add()
+dispatcher.connect(track_query, signal=signals.query_execute, weak=False)
+
 __test__ = {'API_TESTS':"""
 
 # Set up.
@@ -92,39 +109,52 @@
 
 # Normally, accessing FKs doesn't fill in related objects:
 >>> db.reset_queries()
+>>> QueryCounter.clear()
 >>> fly = Species.objects.get(name="melanogaster")
 >>> fly.genus.family.order.klass.phylum.kingdom.domain
 <Domain: Eukaryota>
 >>> len(db.connection.queries)
 8
+>>> QueryCounter.counter
+8
 
 # However, a select_related() call will fill in those related objects without any extra queries:
 >>> db.reset_queries()
+>>> QueryCounter.clear()
 >>> person = Species.objects.select_related().get(name="sapiens")
 >>> person.genus.family.order.klass.phylum.kingdom.domain
 <Domain: Eukaryota>
 >>> len(db.connection.queries)
 1
+>>> QueryCounter.counter
+1
 
 # select_related() also of course applies to entire lists, not just items.
 # Without select_related()
 >>> db.reset_queries()
+>>> QueryCounter.clear()
 >>> world = Species.objects.all()
 >>> [o.genus.family for o in world]
 [<Family: Drosophilidae>, <Family: Hominidae>, <Family: Fabaceae>, <Family: Amanitacae>]
 >>> len(db.connection.queries)
 9
+>>> QueryCounter.counter
+9
 
 # With select_related():
 >>> db.reset_queries()
+>>> QueryCounter.clear()
 >>> world = Species.objects.all().select_related()
 >>> [o.genus.family for o in world]
 [<Family: Drosophilidae>, <Family: Hominidae>, <Family: Fabaceae>, <Family: Amanitacae>]
 >>> len(db.connection.queries)
 1
+>>> QueryCounter.counter
+1
 
 # The "depth" argument to select_related() will stop the descent at a particular level:
 >>> db.reset_queries()
+>>> QueryCounter.clear()
 >>> pea = Species.objects.select_related(depth=1).get(name="sativum")
 >>> pea.genus.family.order.klass.phylum.kingdom.domain
 <Domain: Eukaryota>
@@ -132,20 +162,28 @@
 # Notice: one few query than above because of depth=1
 >>> len(db.connection.queries)
 7
+>>> QueryCounter.counter
+7
 
 >>> db.reset_queries()
+>>> QueryCounter.clear()
 >>> pea = Species.objects.select_related(depth=5).get(name="sativum")
 >>> pea.genus.family.order.klass.phylum.kingdom.domain
 <Domain: Eukaryota>
 >>> len(db.connection.queries)
 3
+>>> QueryCounter.counter
+3
 
 >>> db.reset_queries()
+>>> QueryCounter.clear()
 >>> world = Species.objects.all().select_related(depth=2)
 >>> [o.genus.family.order for o in world]
 [<Order: Diptera>, <Order: Primates>, <Order: Fabales>, <Order: Agaricales>]
 >>> len(db.connection.queries)
 5
+>>> QueryCounter.counter
+5
 
 # Reset DEBUG to where we found it.
 >>> settings.DEBUG = False
