Account Options

  1. Sign in
The old Google Groups will be going away soon.
Switch to the new Google Groups.
Google Groups Home
« Groups Home
Message from discussion Adding hooks to methods that generate SQL in django/core/management.py
The group you are posting to is a Usenet group. Messages posted to this group will make your email address visible to anyone on the Internet.
Your reply message has not been sent.
Your post was successful
 
From:
To:
Cc:
Followup To:
Add Cc | Add Followup-to | Edit Subject
Subject:
Validation:
For verification purposes please type the characters you see in the picture below or the numbers you hear by clicking the accessibility icon. Listen and type the numbers you hear
 
George Vilches  
View profile  
 More options Aug 19 2007, 10:23 pm
From: George Vilches <g...@thataddress.com>
Date: Sun, 19 Aug 2007 22:23:54 -0400
Local: Sun, Aug 19 2007 10:23 pm
Subject: Re: Adding hooks to methods that generate SQL in django/core/management.py

Russell Keith-Magee wrote:
> On 8/13/07, George Vilches <g...@thataddress.com> wrote:
>> Russell Keith-Magee wrote:
>>> The configuration option will need to be a little more generic - i.e.,
>>> putting the entire backend into a record mode - not just a single
>>> cursor call.
>> Second, we could add a class level variable to each DatabaseWrapper,
>> since the handle to those seem to be instantiated only once at runtime
>> (at least, my short testing with just the Django built-in webserver
>> seemed to do so, I only assume that for Apache it's once per thread).
>> That would be an easy enough variable to update from pretty much
>> anywhere in the app:

>>      connection.playback_only = True

> There's another possibility you haven't considered - dynamically
> replacing/wrapping the connection object. The test system already does
> this for the email framework - when the test framework is set up, the
> email framework is dynamically replaced with a mock; when the test
> framework is torn down, the mock is uninstalled. A similar approach
> could be used to 'start/end SQL recording'.

Since Adrian has done great work tonight landing Brian Harring's
database refactoring, it seemed like a good time to revisit this,
because dropping the addition of "non-executing" or "playback only" SQL
(what do we want to call this?) will be in a single place and very painless.

As far as dynamically wrapping it, that's a neat idea, and I think it
would have been very appropriate before the refactor.  Now, we've
already got a debug cursor, and we're already tracking queries, so the
change seems very natural.

The two needed file patches are at the bottom of the e-mail.  This
change is small and totally non-destructive to existing apps.  If you
want to turn your DB to playback_only, you just have to call:

from django.db import connection
connection.playback_only = True

And since the connection variable are only be initialized once per
runtime, setting it once anywhere means that the app is in playback only
mode for the rest of the run.  This could easily be controlled from a
middleware, so all the items below this middleware could be playback
only, but outer middlewares can still write to the database if necessary.

The only way this could be simpler or easier for the user to control is
if there was an entry in settings.py that the user could also use.
settings.DATABASE_PLAYBACK_ONLY, maybe?  I'm only +0 on this.  It would
have to be optional, because I can definitely see a reason for wanting
to turn this ability on and off during runtime without changing the code
at all.  Specifically, I could imagine several setup programs in the
style of phpBB (I know, it's a sin to mention PHP apps on here, but
everything I can think of right this second is in PHP) that might want
to turn it off based on whether the user asked to display the queries or
actually execute them on install on the previous web page.

How do people feel about this approach?

Thanks,
gav

--- django_orig/django/db/backends/__init__.py  2007-08-19
21:22:44.000000000 -0400
+++ django_live/django/db/backends/__init__.py  2007-08-19
22:03:11.000000000 -0400
@@ -12,6 +12,7 @@ class BaseDatabaseWrapper(local):
      ops = None
      def __init__(self, **kwargs):
          self.connection = None
+        self.playback_only = False
          self.queries = []
          self.options = kwargs

@@ -31,13 +32,13 @@ class BaseDatabaseWrapper(local):
      def cursor(self):
          from django.conf import settings
          cursor = self._cursor(settings)
-        if settings.DEBUG:
+        if settings.DEBUG or self.playback_only:
              return self.make_debug_cursor(cursor)
          return cursor

      def make_debug_cursor(self, cursor):
          from django.db.backends import util
-        return util.CursorDebugWrapper(cursor, self)
+        return util.CursorDebugWrapper(cursor, self,
playback_only=self.playback_only)

  class BaseDatabaseOperations(object):
      """
--- django_orig/django/db/backends/util.py      2007-08-19
21:22:44.000000000 -0400
+++ django_live/django/db/backends/util.py      2007-08-19
21:31:12.000000000 -0400
@@ -9,14 +9,16 @@ except ImportError:
      from django.utils import _decimal as decimal    # for Python 2.3

  class CursorDebugWrapper(object):
-    def __init__(self, cursor, db):
+    def __init__(self, cursor, db, playback_only=False):
          self.cursor = cursor
          self.db = db
+        self.allow_execute = not playback_only

      def execute(self, sql, params=()):
          start = time()
          try:
-            return self.cursor.execute(sql, params)
+            if self.allow_execute:
+                return self.cursor.execute(sql, params)
          finally:
              stop = time()
              self.db.queries.append({
@@ -27,7 +29,8 @@ class CursorDebugWrapper(object):
      def executemany(self, sql, param_list):
          start = time()
          try:
-            return self.cursor.executemany(sql, param_list)
+            if self.allow_execute:
+                return self.cursor.executemany(sql, param_list)
          finally:
              stop = time()
              self.db.queries.append({


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.